Merge "Add audioserver state callback"
diff --git a/Android.mk b/Android.mk
index a78a01a..3b8d6a8 100644
--- a/Android.mk
+++ b/Android.mk
@@ -36,7 +36,7 @@
 define stubs-to-aidl-parcelables
   gen := $(TARGET_OUT_COMMON_INTERMEDIATES)/$1.aidl
   aidl_parcelables += $$(gen)
-  $$(gen): $(call java-lib-header-files,$1) | $(HOST_OUT_EXECUTABLES)/sdkparcelables
+  $$(gen): $(call java-lib-header-files,$1) $(HOST_OUT_EXECUTABLES)/sdkparcelables
 	@echo Extract SDK parcelables: $$@
 	rm -f $$@
 	$(HOST_OUT_EXECUTABLES)/sdkparcelables $$< $$@
@@ -804,7 +804,7 @@
     -Iexternal/protobuf/src
 LOCAL_PROTO_JAVA_OUTPUT_PARAMS := \
     store_unknown_fields = true
-LOCAL_JAVA_LIBRARIES := core-oj core-libart
+LOCAL_SDK_VERSION := current
 LOCAL_SRC_FILES := \
     $(call all-proto-files-under, core/proto) \
     $(call all-proto-files-under, libs/incident/proto/android/os)
diff --git a/apct-tests/perftests/core/src/android/text/MeasuredTextMemoryUsageTest.java b/apct-tests/perftests/core/src/android/text/PrecomputedTextMemoryUsageTest.java
similarity index 73%
rename from apct-tests/perftests/core/src/android/text/MeasuredTextMemoryUsageTest.java
rename to apct-tests/perftests/core/src/android/text/PrecomputedTextMemoryUsageTest.java
index fc6302e..73e1724 100644
--- a/apct-tests/perftests/core/src/android/text/MeasuredTextMemoryUsageTest.java
+++ b/apct-tests/perftests/core/src/android/text/PrecomputedTextMemoryUsageTest.java
@@ -45,7 +45,7 @@
 
 @LargeTest
 @RunWith(AndroidJUnit4.class)
-public class MeasuredTextMemoryUsageTest {
+public class PrecomputedTextMemoryUsageTest {
     private static final int WORD_LENGTH = 9;  // Random word has 9 characters.
     private static final boolean NO_STYLE_TEXT = false;
 
@@ -53,7 +53,7 @@
 
     private static int TRIAL_COUNT = 100;
 
-    public MeasuredTextMemoryUsageTest() {}
+    public PrecomputedTextMemoryUsageTest() {}
 
     private TextPerfUtils mTextUtil = new TextPerfUtils();
 
@@ -77,13 +77,16 @@
     @Test
     public void testMemoryUsage_NoHyphenation() {
         int[] memories = new int[TRIAL_COUNT];
-        // Report median of randomly generated MeasuredText.
-        for (int i = 0; i < TRIAL_COUNT; ++i) {
-            memories[i] = new MeasuredText.Builder(
-                    mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), PAINT)
+        final PrecomputedText.Params param = new PrecomputedText.Params.Builder(PAINT)
                 .setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE)
                 .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NONE)
-                .build().getMemoryUsage();
+                .build();
+
+        // Report median of randomly generated PrecomputedText.
+        for (int i = 0; i < TRIAL_COUNT; ++i) {
+            memories[i] = PrecomputedText.create(
+                    mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), param)
+                .getMemoryUsage();
         }
         reportMemoryUsage(median(memories), "MemoryUsage_NoHyphenation");
     }
@@ -91,13 +94,16 @@
     @Test
     public void testMemoryUsage_Hyphenation() {
         int[] memories = new int[TRIAL_COUNT];
-        // Report median of randomly generated MeasuredText.
-        for (int i = 0; i < TRIAL_COUNT; ++i) {
-            memories[i] = new MeasuredText.Builder(
-                    mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), PAINT)
+        final PrecomputedText.Params param = new PrecomputedText.Params.Builder(PAINT)
                 .setBreakStrategy(Layout.BREAK_STRATEGY_BALANCED)
                 .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL)
-                .build().getMemoryUsage();
+                .build();
+
+        // Report median of randomly generated PrecomputedText.
+        for (int i = 0; i < TRIAL_COUNT; ++i) {
+            memories[i] = PrecomputedText.create(
+                    mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), param)
+                .getMemoryUsage();
         }
         reportMemoryUsage(median(memories), "MemoryUsage_Hyphenation");
     }
@@ -105,13 +111,16 @@
     @Test
     public void testMemoryUsage_NoHyphenation_WidthOnly() {
         int[] memories = new int[TRIAL_COUNT];
-        // Report median of randomly generated MeasuredText.
-        for (int i = 0; i < TRIAL_COUNT; ++i) {
-            memories[i] = new MeasuredText.Builder(
-                    mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), PAINT)
+        final PrecomputedText.Params param = new PrecomputedText.Params.Builder(PAINT)
                 .setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE)
                 .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NONE)
-                .build(false /* width only */).getMemoryUsage();
+                .build();
+
+        // Report median of randomly generated PrecomputedText.
+        for (int i = 0; i < TRIAL_COUNT; ++i) {
+            CharSequence cs = mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT);
+            memories[i] = PrecomputedText.createWidthOnly(cs, param, 0, cs.length())
+                .getMemoryUsage();
         }
         reportMemoryUsage(median(memories), "MemoryUsage_NoHyphenation_WidthOnly");
     }
@@ -119,13 +128,16 @@
     @Test
     public void testMemoryUsage_Hyphenatation_WidthOnly() {
         int[] memories = new int[TRIAL_COUNT];
-        // Report median of randomly generated MeasuredText.
-        for (int i = 0; i < TRIAL_COUNT; ++i) {
-            memories[i] = new MeasuredText.Builder(
-                    mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), PAINT)
+        final PrecomputedText.Params param = new PrecomputedText.Params.Builder(PAINT)
                 .setBreakStrategy(Layout.BREAK_STRATEGY_BALANCED)
                 .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL)
-                .build(false /* width only */).getMemoryUsage();
+                .build();
+
+        // Report median of randomly generated PrecomputedText.
+        for (int i = 0; i < TRIAL_COUNT; ++i) {
+            CharSequence cs = mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT);
+            memories[i] = PrecomputedText.createWidthOnly(cs, param, 0, cs.length())
+                .getMemoryUsage();
         }
         reportMemoryUsage(median(memories), "MemoryUsage_Hyphenation_WidthOnly");
     }
diff --git a/apct-tests/perftests/core/src/android/text/MeasuredTextPerfTest.java b/apct-tests/perftests/core/src/android/text/PrecomputedTextPerfTest.java
similarity index 66%
rename from apct-tests/perftests/core/src/android/text/MeasuredTextPerfTest.java
rename to apct-tests/perftests/core/src/android/text/PrecomputedTextPerfTest.java
index 98f2bd5..1cd0ae1 100644
--- a/apct-tests/perftests/core/src/android/text/MeasuredTextPerfTest.java
+++ b/apct-tests/perftests/core/src/android/text/PrecomputedTextPerfTest.java
@@ -42,7 +42,7 @@
 
 @LargeTest
 @RunWith(AndroidJUnit4.class)
-public class MeasuredTextPerfTest {
+public class PrecomputedTextPerfTest {
     private static final int WORD_LENGTH = 9;  // Random word has 9 characters.
     private static final int WORDS_IN_LINE = 8;  // Roughly, 8 words in a line.
     private static final boolean NO_STYLE_TEXT = false;
@@ -51,7 +51,7 @@
     private static TextPaint PAINT = new TextPaint();
     private static final int TEXT_WIDTH = WORDS_IN_LINE * WORD_LENGTH * (int) PAINT.getTextSize();
 
-    public MeasuredTextPerfTest() {}
+    public PrecomputedTextPerfTest() {}
 
     @Rule
     public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
@@ -66,120 +66,136 @@
     @Test
     public void testCreate_NoStyled_Hyphenation() {
         final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        final PrecomputedText.Params param = new PrecomputedText.Params.Builder(PAINT)
+                .setBreakStrategy(Layout.BREAK_STRATEGY_BALANCED)
+                .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL)
+                .build();
+
         while (state.keepRunning()) {
             state.pauseTiming();
             final CharSequence text = mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT);
             state.resumeTiming();
 
-            new MeasuredText.Builder(text, PAINT)
-                    .setBreakStrategy(Layout.BREAK_STRATEGY_BALANCED)
-                    .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL)
-                    .build(true /* do full layout */);
+            PrecomputedText.create(text, param);
         }
     }
 
     @Test
     public void testCreate_NoStyled_NoHyphenation() {
         final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        final PrecomputedText.Params param = new PrecomputedText.Params.Builder(PAINT)
+                .setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE)
+                .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NONE)
+                .build();
+
         while (state.keepRunning()) {
             state.pauseTiming();
             final CharSequence text = mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT);
             state.resumeTiming();
 
-            new MeasuredText.Builder(text, PAINT)
-                    .setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE)
-                    .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NONE)
-                    .build(true /* do full layout */);
+            PrecomputedText.create(text, param);
         }
     }
 
     @Test
     public void testCreate_NoStyled_Hyphenation_WidthOnly() {
         final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        final PrecomputedText.Params param = new PrecomputedText.Params.Builder(PAINT)
+                .setBreakStrategy(Layout.BREAK_STRATEGY_BALANCED)
+                .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL)
+                .build();
+
         while (state.keepRunning()) {
             state.pauseTiming();
             final CharSequence text = mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT);
             state.resumeTiming();
 
-            new MeasuredText.Builder(text, PAINT)
-                    .setBreakStrategy(Layout.BREAK_STRATEGY_BALANCED)
-                    .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL)
-                    .build(false /* width only */);
+            PrecomputedText.create(text, param);
         }
     }
 
     @Test
     public void testCreate_NoStyled_NoHyphenation_WidthOnly() {
         final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        final PrecomputedText.Params param = new PrecomputedText.Params.Builder(PAINT)
+                .setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE)
+                .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NONE)
+                .build();
+
         while (state.keepRunning()) {
             state.pauseTiming();
             final CharSequence text = mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT);
             state.resumeTiming();
 
-            new MeasuredText.Builder(text, PAINT)
-                    .setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE)
-                    .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NONE)
-                    .build(false /* width only */);
+            PrecomputedText.create(text, param);
         }
     }
 
     @Test
     public void testCreate_Styled_Hyphenation() {
         final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        final PrecomputedText.Params param = new PrecomputedText.Params.Builder(PAINT)
+                .setBreakStrategy(Layout.BREAK_STRATEGY_BALANCED)
+                .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL)
+                .build();
+
         while (state.keepRunning()) {
             state.pauseTiming();
             final CharSequence text = mTextUtil.nextRandomParagraph(WORD_LENGTH, STYLE_TEXT);
             state.resumeTiming();
 
-            new MeasuredText.Builder(text, PAINT)
-                    .setBreakStrategy(Layout.BREAK_STRATEGY_BALANCED)
-                    .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL)
-                    .build(true /* do full layout */);
+            PrecomputedText.create(text, param);
         }
     }
 
     @Test
     public void testCreate_Styled_NoHyphenation() {
         final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        final PrecomputedText.Params param = new PrecomputedText.Params.Builder(PAINT)
+                .setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE)
+                .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NONE)
+                .build();
+
         while (state.keepRunning()) {
             state.pauseTiming();
             final CharSequence text = mTextUtil.nextRandomParagraph(WORD_LENGTH, STYLE_TEXT);
             state.resumeTiming();
 
-            new MeasuredText.Builder(text, PAINT)
-                    .setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE)
-                    .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NONE)
-                    .build(true /* do full layout */);
+            PrecomputedText.create(text, param);
         }
     }
 
     @Test
     public void testCreate_Styled_Hyphenation_WidthOnly() {
         final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        final PrecomputedText.Params param = new PrecomputedText.Params.Builder(PAINT)
+                .setBreakStrategy(Layout.BREAK_STRATEGY_BALANCED)
+                .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL)
+                .build();
+
         while (state.keepRunning()) {
             state.pauseTiming();
             final CharSequence text = mTextUtil.nextRandomParagraph(WORD_LENGTH, STYLE_TEXT);
             state.resumeTiming();
 
-            new MeasuredText.Builder(text, PAINT)
-                    .setBreakStrategy(Layout.BREAK_STRATEGY_BALANCED)
-                    .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL)
-                    .build(false /* width only */);
+            PrecomputedText.create(text, param);
         }
     }
 
     @Test
     public void testCreate_Styled_NoHyphenation_WidthOnly() {
         final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        final PrecomputedText.Params param = new PrecomputedText.Params.Builder(PAINT)
+                .setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE)
+                .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NONE)
+                .build();
+
         while (state.keepRunning()) {
             state.pauseTiming();
             final CharSequence text = mTextUtil.nextRandomParagraph(WORD_LENGTH, STYLE_TEXT);
             state.resumeTiming();
 
-            new MeasuredText.Builder(text, PAINT)
-                    .setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE)
-                    .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NONE)
-                    .build(false /* width only */);
+            PrecomputedText.create(text, param);
         }
     }
 }
diff --git a/apct-tests/perftests/core/src/android/text/StaticLayoutPerfTest.java b/apct-tests/perftests/core/src/android/text/StaticLayoutPerfTest.java
index 231aaf2..8823af1 100644
--- a/apct-tests/perftests/core/src/android/text/StaticLayoutPerfTest.java
+++ b/apct-tests/perftests/core/src/android/text/StaticLayoutPerfTest.java
@@ -63,6 +63,18 @@
         mTextUtil.resetRandom(0 /* seed */);
     }
 
+    private PrecomputedText makeMeasured(CharSequence text, TextPaint paint) {
+        PrecomputedText.Params param = new PrecomputedText.Params.Builder(paint).build();
+        return PrecomputedText.create(text, param);
+    }
+
+    private PrecomputedText makeMeasured(CharSequence text, TextPaint paint, int strategy,
+                                      int frequency) {
+        PrecomputedText.Params param = new PrecomputedText.Params.Builder(paint)
+                .setHyphenationFrequency(frequency).setBreakStrategy(strategy).build();
+        return PrecomputedText.create(text, param);
+    }
+
     @Test
     public void testCreate_FixedText_NoStyle_Greedy_NoHyphenation() {
         final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
@@ -151,18 +163,16 @@
     }
 
     @Test
-    public void testCreate_MeasuredText_NoStyled_Greedy_NoHyphenation() {
+    public void testCreate_PrecomputedText_NoStyled_Greedy_NoHyphenation() {
         final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
         while (state.keepRunning()) {
             state.pauseTiming();
-            final MeasuredText text = new MeasuredText.Builder(
-                    mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), PAINT)
-                    .setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE)
-                    .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NONE)
-                    .build();
+            final PrecomputedText text = makeMeasured(
+                    mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), PAINT,
+                    Layout.BREAK_STRATEGY_SIMPLE, Layout.HYPHENATION_FREQUENCY_NONE);
             state.resumeTiming();
 
-            StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH)
+            StaticLayout.Builder.obtain(text, 0, text.getText().length(), PAINT, TEXT_WIDTH)
                     .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NONE)
                     .setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE)
                     .build();
@@ -170,18 +180,16 @@
     }
 
     @Test
-    public void testCreate_MeasuredText_NoStyled_Greedy_Hyphenation() {
+    public void testCreate_PrecomputedText_NoStyled_Greedy_Hyphenation() {
         final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
         while (state.keepRunning()) {
             state.pauseTiming();
-            final MeasuredText text = new MeasuredText.Builder(
-                    mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), PAINT)
-                    .setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE)
-                    .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL)
-                    .build();
+            final PrecomputedText text = makeMeasured(
+                    mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), PAINT,
+                    Layout.BREAK_STRATEGY_SIMPLE, Layout.HYPHENATION_FREQUENCY_NORMAL);
             state.resumeTiming();
 
-            StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH)
+            StaticLayout.Builder.obtain(text, 0, text.getText().length(), PAINT, TEXT_WIDTH)
                     .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL)
                     .setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE)
                     .build();
@@ -189,18 +197,16 @@
     }
 
     @Test
-    public void testCreate_MeasuredText_NoStyled_Balanced_NoHyphenation() {
+    public void testCreate_PrecomputedText_NoStyled_Balanced_NoHyphenation() {
         final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
         while (state.keepRunning()) {
             state.pauseTiming();
-            final MeasuredText text = new MeasuredText.Builder(
-                    mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), PAINT)
-                    .setBreakStrategy(Layout.BREAK_STRATEGY_BALANCED)
-                    .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NONE)
-                    .build();
+            final PrecomputedText text = makeMeasured(
+                    mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), PAINT,
+                    Layout.BREAK_STRATEGY_BALANCED, Layout.HYPHENATION_FREQUENCY_NONE);
             state.resumeTiming();
 
-            StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH)
+            StaticLayout.Builder.obtain(text, 0, text.getText().length(), PAINT, TEXT_WIDTH)
                     .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NONE)
                     .setBreakStrategy(Layout.BREAK_STRATEGY_BALANCED)
                     .build();
@@ -208,18 +214,16 @@
     }
 
     @Test
-    public void testCreate_MeasuredText_NoStyled_Balanced_Hyphenation() {
+    public void testCreate_PrecomputedText_NoStyled_Balanced_Hyphenation() {
         final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
         while (state.keepRunning()) {
             state.pauseTiming();
-            final MeasuredText text = new MeasuredText.Builder(
-                    mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), PAINT)
-                    .setBreakStrategy(Layout.BREAK_STRATEGY_BALANCED)
-                    .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL)
-                    .build();
+            final PrecomputedText text = makeMeasured(
+                    mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), PAINT,
+                    Layout.BREAK_STRATEGY_BALANCED, Layout.HYPHENATION_FREQUENCY_NORMAL);
             state.resumeTiming();
 
-            StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH)
+            StaticLayout.Builder.obtain(text, 0, text.getText().length(), PAINT, TEXT_WIDTH)
                     .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL)
                     .setBreakStrategy(Layout.BREAK_STRATEGY_BALANCED)
                     .build();
@@ -227,18 +231,16 @@
     }
 
     @Test
-    public void testCreate_MeasuredText_Styled_Greedy_NoHyphenation() {
+    public void testCreate_PrecomputedText_Styled_Greedy_NoHyphenation() {
         final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
         while (state.keepRunning()) {
             state.pauseTiming();
-            final MeasuredText text = new MeasuredText.Builder(
-                    mTextUtil.nextRandomParagraph(WORD_LENGTH, STYLE_TEXT), PAINT)
-                    .setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE)
-                    .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NONE)
-                    .build();
+            final PrecomputedText text = makeMeasured(
+                    mTextUtil.nextRandomParagraph(WORD_LENGTH, STYLE_TEXT), PAINT,
+                    Layout.BREAK_STRATEGY_SIMPLE, Layout.HYPHENATION_FREQUENCY_NONE);
             state.resumeTiming();
 
-            StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH)
+            StaticLayout.Builder.obtain(text, 0, text.getText().length(), PAINT, TEXT_WIDTH)
                     .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NONE)
                     .setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE)
                     .build();
@@ -328,15 +330,16 @@
     }
 
     @Test
-    public void testDraw_MeasuredText_Styled() {
+    public void testDraw_PrecomputedText_Styled() {
         final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
         final RenderNode node = RenderNode.create("benchmark", null);
         while (state.keepRunning()) {
             state.pauseTiming();
-            final MeasuredText text = new MeasuredText.Builder(
-                    mTextUtil.nextRandomParagraph(WORD_LENGTH, STYLE_TEXT), PAINT).build();
+            final PrecomputedText text = makeMeasured(
+                    mTextUtil.nextRandomParagraph(WORD_LENGTH, STYLE_TEXT), PAINT);
             final StaticLayout layout =
-                    StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH).build();
+                    StaticLayout.Builder.obtain(
+                            text, 0, text.getText().length(), PAINT, TEXT_WIDTH).build();
             final DisplayListCanvas c = node.start(1200, 200);
             state.resumeTiming();
 
@@ -345,15 +348,16 @@
     }
 
     @Test
-    public void testDraw_MeasuredText_NoStyled() {
+    public void testDraw_PrecomputedText_NoStyled() {
         final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
         final RenderNode node = RenderNode.create("benchmark", null);
         while (state.keepRunning()) {
             state.pauseTiming();
-            final MeasuredText text = new MeasuredText.Builder(
-                    mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), PAINT).build();
+            final PrecomputedText text = makeMeasured(
+                    mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), PAINT);
             final StaticLayout layout =
-                    StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH).build();
+                    StaticLayout.Builder.obtain(
+                            text, 0, text.getText().length(), PAINT, TEXT_WIDTH).build();
             final DisplayListCanvas c = node.start(1200, 200);
             state.resumeTiming();
 
@@ -362,15 +366,16 @@
     }
 
     @Test
-    public void testDraw_MeasuredText_Styled_WithoutCache() {
+    public void testDraw_PrecomputedText_Styled_WithoutCache() {
         final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
         final RenderNode node = RenderNode.create("benchmark", null);
         while (state.keepRunning()) {
             state.pauseTiming();
-            final MeasuredText text = new MeasuredText.Builder(
-                    mTextUtil.nextRandomParagraph(WORD_LENGTH, STYLE_TEXT), PAINT).build();
+            final PrecomputedText text = makeMeasured(
+                    mTextUtil.nextRandomParagraph(WORD_LENGTH, STYLE_TEXT), PAINT);
             final StaticLayout layout =
-                    StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH).build();
+                    StaticLayout.Builder.obtain(
+                            text, 0, text.getText().length(), PAINT, TEXT_WIDTH).build();
             final DisplayListCanvas c = node.start(1200, 200);
             Canvas.freeTextLayoutCaches();
             state.resumeTiming();
@@ -380,15 +385,16 @@
     }
 
     @Test
-    public void testDraw_MeasuredText_NoStyled_WithoutCache() {
+    public void testDraw_PrecomputedText_NoStyled_WithoutCache() {
         final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
         final RenderNode node = RenderNode.create("benchmark", null);
         while (state.keepRunning()) {
             state.pauseTiming();
-            final MeasuredText text = new MeasuredText.Builder(
-                    mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), PAINT).build();
+            final PrecomputedText text = makeMeasured(
+                    mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), PAINT);
             final StaticLayout layout =
-                    StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH).build();
+                    StaticLayout.Builder.obtain(
+                            text, 0, text.getText().length(), PAINT, TEXT_WIDTH).build();
             final DisplayListCanvas c = node.start(1200, 200);
             Canvas.freeTextLayoutCaches();
             state.resumeTiming();
diff --git a/api/current.txt b/api/current.txt
index e454b07..3edd2c0 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -73,7 +73,6 @@
     field public static final java.lang.String DUMP = "android.permission.DUMP";
     field public static final java.lang.String EXPAND_STATUS_BAR = "android.permission.EXPAND_STATUS_BAR";
     field public static final java.lang.String FACTORY_TEST = "android.permission.FACTORY_TEST";
-    field public static final java.lang.String FOREGROUND_SERVICE = "android.permission.FOREGROUND_SERVICE";
     field public static final java.lang.String GET_ACCOUNTS = "android.permission.GET_ACCOUNTS";
     field public static final java.lang.String GET_ACCOUNTS_PRIVILEGED = "android.permission.GET_ACCOUNTS_PRIVILEGED";
     field public static final java.lang.String GET_PACKAGE_SIZE = "android.permission.GET_PACKAGE_SIZE";
@@ -6706,6 +6705,7 @@
     field public static final int USER_OPERATION_ERROR_MAX_RUNNING_USERS = 3; // 0x3
     field public static final int USER_OPERATION_ERROR_UNKNOWN = 1; // 0x1
     field public static final int USER_OPERATION_SUCCESS = 0; // 0x0
+    field public static final int WIPE_EUICC = 4; // 0x4
     field public static final int WIPE_EXTERNAL_STORAGE = 1; // 0x1
     field public static final int WIPE_RESET_PROTECTION_DATA = 2; // 0x2
   }
@@ -6874,6 +6874,7 @@
     method public java.lang.String getIdEntry();
     method public java.lang.String getIdPackage();
     method public java.lang.String getIdType();
+    method public int getImportantForAutofill();
     method public int getInputType();
     method public int getLeft();
     method public android.os.LocaleList getLocaleList();
@@ -9441,6 +9442,7 @@
     field public static final java.lang.String DISPLAY_SERVICE = "display";
     field public static final java.lang.String DOWNLOAD_SERVICE = "download";
     field public static final java.lang.String DROPBOX_SERVICE = "dropbox";
+    field public static final java.lang.String EUICC_SERVICE = "euicc";
     field public static final java.lang.String FINGERPRINT_SERVICE = "fingerprint";
     field public static final java.lang.String HARDWARE_PROPERTIES_SERVICE = "hardware_properties";
     field public static final java.lang.String INPUT_METHOD_SERVICE = "input_method";
@@ -11266,6 +11268,7 @@
     field public static final java.lang.String FEATURE_STRONGBOX_KEYSTORE = "android.hardware.strongbox_keystore";
     field public static final java.lang.String FEATURE_TELEPHONY = "android.hardware.telephony";
     field public static final java.lang.String FEATURE_TELEPHONY_CDMA = "android.hardware.telephony.cdma";
+    field public static final java.lang.String FEATURE_TELEPHONY_EUICC = "android.hardware.telephony.euicc";
     field public static final java.lang.String FEATURE_TELEPHONY_GSM = "android.hardware.telephony.gsm";
     field public static final java.lang.String FEATURE_TELEPHONY_MBMS = "android.hardware.telephony.mbms";
     field public static final deprecated java.lang.String FEATURE_TELEVISION = "android.hardware.type.television";
@@ -13832,6 +13835,7 @@
     method public int breakText(java.lang.String, boolean, float, float[]);
     method public void clearShadowLayer();
     method public float descent();
+    method public boolean equalsForTextMeasurement(android.graphics.Paint);
     method public int getAlpha();
     method public int getColor();
     method public android.graphics.ColorFilter getColorFilter();
@@ -15843,8 +15847,6 @@
     method public abstract void createReprocessableCaptureSessionByConfigurations(android.hardware.camera2.params.InputConfiguration, java.util.List<android.hardware.camera2.params.OutputConfiguration>, android.hardware.camera2.CameraCaptureSession.StateCallback, android.os.Handler) throws android.hardware.camera2.CameraAccessException;
     method public abstract java.lang.String getId();
     field public static final int TEMPLATE_MANUAL = 6; // 0x6
-    field public static final int TEMPLATE_MOTION_TRACKING_BEST = 8; // 0x8
-    field public static final int TEMPLATE_MOTION_TRACKING_PREVIEW = 7; // 0x7
     field public static final int TEMPLATE_PREVIEW = 1; // 0x1
     field public static final int TEMPLATE_RECORD = 3; // 0x3
     field public static final int TEMPLATE_STILL_CAPTURE = 2; // 0x2
@@ -23371,6 +23373,7 @@
     method public android.media.MediaDrm.CryptoSession getCryptoSession(byte[], java.lang.String, java.lang.String);
     method public android.media.MediaDrm.KeyRequest getKeyRequest(byte[], byte[], java.lang.String, int, java.util.HashMap<java.lang.String, java.lang.String>) throws android.media.NotProvisionedException;
     method public int getMaxHdcpLevel();
+    method public static int getMaxSecurityLevel();
     method public int getMaxSessionCount();
     method public android.os.PersistableBundle getMetrics();
     method public int getOpenSessionCount();
@@ -23384,6 +23387,7 @@
     method public static boolean isCryptoSchemeSupported(java.util.UUID);
     method public static boolean isCryptoSchemeSupported(java.util.UUID, java.lang.String);
     method public byte[] openSession() throws android.media.NotProvisionedException, android.media.ResourceBusyException;
+    method public byte[] openSession(int) throws android.media.NotProvisionedException, android.media.ResourceBusyException;
     method public byte[] provideKeyResponse(byte[], byte[]) throws android.media.DeniedByServerException, android.media.NotProvisionedException;
     method public void provideProvisionResponse(byte[]) throws android.media.DeniedByServerException;
     method public java.util.HashMap<java.lang.String, java.lang.String> queryKeyStatus(byte[]);
@@ -23399,7 +23403,6 @@
     method public void setOnKeyStatusChangeListener(android.media.MediaDrm.OnKeyStatusChangeListener, android.os.Handler);
     method public void setPropertyByteArray(java.lang.String, byte[]);
     method public void setPropertyString(java.lang.String, java.lang.String);
-    method public void setSecurityLevel(byte[], int);
     field public static final deprecated int EVENT_KEY_EXPIRED = 3; // 0x3
     field public static final int EVENT_KEY_REQUIRED = 2; // 0x2
     field public static final deprecated int EVENT_PROVISION_REQUIRED = 1; // 0x1
@@ -36774,6 +36777,13 @@
     field public static final java.lang.String ADDRESS = "address";
   }
 
+  public static final class Telephony.CarrierIdentification implements android.provider.BaseColumns {
+    method public static android.net.Uri getUriForSubscriptionId(int);
+    field public static final java.lang.String CID = "carrier_id";
+    field public static final android.net.Uri CONTENT_URI;
+    field public static final java.lang.String NAME = "carrier_name";
+  }
+
   public static final class Telephony.Carriers implements android.provider.BaseColumns {
     field public static final java.lang.String APN = "apn";
     field public static final java.lang.String AUTH_TYPE = "authtype";
@@ -42198,13 +42208,16 @@
     method public java.lang.String getNumber();
     method public int getSimSlotIndex();
     method public int getSubscriptionId();
+    method public boolean isEmbedded();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.telephony.SubscriptionInfo> CREATOR;
   }
 
   public class SubscriptionManager {
     method public void addOnSubscriptionsChangedListener(android.telephony.SubscriptionManager.OnSubscriptionsChangedListener);
+    method public boolean canManageSubscription(android.telephony.SubscriptionInfo);
     method public static deprecated android.telephony.SubscriptionManager from(android.content.Context);
+    method public java.util.List<android.telephony.SubscriptionInfo> getAccessibleSubscriptionInfoList();
     method public android.telephony.SubscriptionInfo getActiveSubscriptionInfo(int);
     method public int getActiveSubscriptionInfoCount();
     method public int getActiveSubscriptionInfoCountMax();
@@ -42589,6 +42602,44 @@
 
 }
 
+package android.telephony.euicc {
+
+  public final class DownloadableSubscription implements android.os.Parcelable {
+    method public int describeContents();
+    method public static android.telephony.euicc.DownloadableSubscription forActivationCode(java.lang.String);
+    method public java.lang.String getConfirmationCode();
+    method public java.lang.String getEncodedActivationCode();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.telephony.euicc.DownloadableSubscription> CREATOR;
+  }
+
+  public final class EuiccInfo implements android.os.Parcelable {
+    ctor public EuiccInfo(java.lang.String);
+    method public int describeContents();
+    method public java.lang.String getOsVersion();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.telephony.euicc.EuiccInfo> CREATOR;
+  }
+
+  public class EuiccManager {
+    method public void deleteSubscription(int, android.app.PendingIntent);
+    method public void downloadSubscription(android.telephony.euicc.DownloadableSubscription, boolean, android.app.PendingIntent);
+    method public java.lang.String getEid();
+    method public android.telephony.euicc.EuiccInfo getEuiccInfo();
+    method public boolean isEnabled();
+    method public void startResolutionActivity(android.app.Activity, int, android.content.Intent, android.app.PendingIntent) throws android.content.IntentSender.SendIntentException;
+    method public void switchToSubscription(int, android.app.PendingIntent);
+    field public static final java.lang.String ACTION_MANAGE_EMBEDDED_SUBSCRIPTIONS = "android.telephony.euicc.action.MANAGE_EMBEDDED_SUBSCRIPTIONS";
+    field public static final java.lang.String ACTION_NOTIFY_CARRIER_SETUP_INCOMPLETE = "android.telephony.euicc.action.NOTIFY_CARRIER_SETUP_INCOMPLETE";
+    field public static final int EMBEDDED_SUBSCRIPTION_RESULT_ERROR = 2; // 0x2
+    field public static final int EMBEDDED_SUBSCRIPTION_RESULT_OK = 0; // 0x0
+    field public static final int EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR = 1; // 0x1
+    field public static final java.lang.String EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE = "android.telephony.euicc.extra.EMBEDDED_SUBSCRIPTION_DETAILED_CODE";
+    field public static final java.lang.String META_DATA_CARRIER_ICON = "android.telephony.euicc.carriericon";
+  }
+
+}
+
 package android.telephony.gsm {
 
   public class GsmCellLocation extends android.telephony.CellLocation {
@@ -43174,36 +43225,6 @@
     method public boolean isAllowed(char);
   }
 
-  public class MeasuredText implements android.text.Spanned {
-    method public char charAt(int);
-    method public int getBreakStrategy();
-    method public int getEnd();
-    method public int getHyphenationFrequency();
-    method public android.text.TextPaint getPaint();
-    method public int getParagraphCount();
-    method public int getParagraphEnd(int);
-    method public int getParagraphStart(int);
-    method public int getSpanEnd(java.lang.Object);
-    method public int getSpanFlags(java.lang.Object);
-    method public int getSpanStart(java.lang.Object);
-    method public <T> T[] getSpans(int, int, java.lang.Class<T>);
-    method public int getStart();
-    method public java.lang.CharSequence getText();
-    method public android.text.TextDirectionHeuristic getTextDir();
-    method public int length();
-    method public int nextSpanTransition(int, int, java.lang.Class);
-    method public java.lang.CharSequence subSequence(int, int);
-  }
-
-  public static final class MeasuredText.Builder {
-    ctor public MeasuredText.Builder(java.lang.CharSequence, android.text.TextPaint);
-    method public android.text.MeasuredText build();
-    method public android.text.MeasuredText.Builder setBreakStrategy(int);
-    method public android.text.MeasuredText.Builder setHyphenationFrequency(int);
-    method public android.text.MeasuredText.Builder setRange(int, int);
-    method public android.text.MeasuredText.Builder setTextDirection(android.text.TextDirectionHeuristic);
-  }
-
   public abstract interface NoCopySpan {
   }
 
@@ -43215,6 +43236,31 @@
     method public abstract int getSpanTypeId();
   }
 
+  public class PrecomputedText {
+    method public static android.text.PrecomputedText create(java.lang.CharSequence, android.text.PrecomputedText.Params);
+    method public int getParagraphCount();
+    method public int getParagraphEnd(int);
+    method public int getParagraphStart(int);
+    method public android.text.PrecomputedText.Params getParams();
+    method public java.lang.CharSequence getText();
+  }
+
+  public static class PrecomputedText.Params {
+    method public int getBreakStrategy();
+    method public int getHyphenationFrequency();
+    method public android.text.TextDirectionHeuristic getTextDirection();
+    method public android.text.TextPaint getTextPaint();
+    method public boolean sameTextMetrics(android.text.PrecomputedText.Params);
+  }
+
+  public static class PrecomputedText.Params.Builder {
+    ctor public PrecomputedText.Params.Builder(android.text.TextPaint);
+    method public android.text.PrecomputedText.Params build();
+    method public android.text.PrecomputedText.Params.Builder setBreakStrategy(int);
+    method public android.text.PrecomputedText.Params.Builder setHyphenationFrequency(int);
+    method public android.text.PrecomputedText.Params.Builder setTextDirection(android.text.TextDirectionHeuristic);
+  }
+
   public class Selection {
     method public static boolean extendDown(android.text.Spannable, android.text.Layout);
     method public static boolean extendLeft(android.text.Spannable, android.text.Layout);
@@ -43346,6 +43392,7 @@
 
   public static final class StaticLayout.Builder {
     method public android.text.StaticLayout build();
+    method public static android.text.StaticLayout.Builder obtain(android.text.PrecomputedText, int, int, android.text.TextPaint, int);
     method public static android.text.StaticLayout.Builder obtain(java.lang.CharSequence, int, int, android.text.TextPaint, int);
     method public android.text.StaticLayout.Builder setAlignment(android.text.Layout.Alignment);
     method public android.text.StaticLayout.Builder setBreakStrategy(int);
@@ -48413,6 +48460,7 @@
     method public abstract void setHint(java.lang.CharSequence);
     method public abstract void setHtmlInfo(android.view.ViewStructure.HtmlInfo);
     method public abstract void setId(int, java.lang.String, java.lang.String, java.lang.String);
+    method public void setImportantForAutofill(int);
     method public abstract void setInputType(int);
     method public abstract void setLocaleList(android.os.LocaleList);
     method public abstract void setLongClickable(boolean);
@@ -50365,7 +50413,7 @@
     method public final void logSelectionModifiedEvent(int, int);
     method public final void logSelectionModifiedEvent(int, int, android.view.textclassifier.TextClassification);
     method public final void logSelectionModifiedEvent(int, int, android.view.textclassifier.TextSelection);
-    method public final void logSelectionStartedEvent(int);
+    method public final void logSelectionStartedEvent(int, int);
     method public abstract void writeEvent(android.view.textclassifier.logging.SelectionEvent);
     field public static final int OUT_OF_BOUNDS = 2147483647; // 0x7fffffff
     field public static final int OUT_OF_BOUNDS_NEGATIVE = -2147483648; // 0x80000000
@@ -50395,6 +50443,7 @@
     method public int getEventIndex();
     method public long getEventTime();
     method public int getEventType();
+    method public int getInvocationMethod();
     method public java.lang.String getPackageName();
     method public java.lang.String getSessionId();
     method public java.lang.String getSignature();
@@ -50419,6 +50468,8 @@
     field public static final int EVENT_SELECTION_STARTED = 1; // 0x1
     field public static final int EVENT_SMART_SELECTION_MULTI = 4; // 0x4
     field public static final int EVENT_SMART_SELECTION_SINGLE = 3; // 0x3
+    field public static final int INVOCATION_LINK = 2; // 0x2
+    field public static final int INVOCATION_MANUAL = 1; // 0x1
   }
 
 }
@@ -53593,6 +53644,7 @@
     method public final android.content.res.ColorStateList getTextColors();
     method public java.util.Locale getTextLocale();
     method public android.os.LocaleList getTextLocales();
+    method public android.text.PrecomputedText.Params getTextMetricsParams();
     method public float getTextScaleX();
     method public float getTextSize();
     method public int getTotalPaddingBottom();
@@ -53698,6 +53750,8 @@
     method public final void setMovementMethod(android.text.method.MovementMethod);
     method public void setOnEditorActionListener(android.widget.TextView.OnEditorActionListener);
     method public void setPaintFlags(int);
+    method public void setPrecomputedTextAndParams(android.text.PrecomputedText);
+    method public void setPrecomputedTextOrThrow(android.text.PrecomputedText);
     method public void setPrivateImeOptions(java.lang.String);
     method public void setRawInputType(int);
     method public void setScroller(android.widget.Scroller);
@@ -53722,6 +53776,7 @@
     method public final void setTextKeepState(java.lang.CharSequence, android.widget.TextView.BufferType);
     method public void setTextLocale(java.util.Locale);
     method public void setTextLocales(android.os.LocaleList);
+    method public void setTextMetricsParams(android.text.PrecomputedText.Params);
     method public void setTextScaleX(float);
     method public void setTextSize(float);
     method public void setTextSize(int, float);
diff --git a/api/system-current.txt b/api/system-current.txt
index 3388fc8..6b92af9 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -20,6 +20,7 @@
     field public static final java.lang.String BIND_APPWIDGET = "android.permission.BIND_APPWIDGET";
     field public static final deprecated java.lang.String BIND_CONNECTION_SERVICE = "android.permission.BIND_CONNECTION_SERVICE";
     field public static final java.lang.String BIND_DIRECTORY_SEARCH = "android.permission.BIND_DIRECTORY_SEARCH";
+    field public static final java.lang.String BIND_EUICC_SERVICE = "android.permission.BIND_EUICC_SERVICE";
     field public static final java.lang.String BIND_IMS_SERVICE = "android.permission.BIND_IMS_SERVICE";
     field public static final java.lang.String BIND_KEYGUARD_APPWIDGET = "android.permission.BIND_KEYGUARD_APPWIDGET";
     field public static final java.lang.String BIND_NETWORK_RECOMMENDATION_SERVICE = "android.permission.BIND_NETWORK_RECOMMENDATION_SERVICE";
@@ -186,6 +187,7 @@
     field public static final java.lang.String USE_RESERVED_DISK = "android.permission.USE_RESERVED_DISK";
     field public static final java.lang.String WRITE_APN_SETTINGS = "android.permission.WRITE_APN_SETTINGS";
     field public static final java.lang.String WRITE_DREAM_STATE = "android.permission.WRITE_DREAM_STATE";
+    field public static final java.lang.String WRITE_EMBEDDED_SUBSCRIPTIONS = "android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS";
     field public static final java.lang.String WRITE_GSERVICES = "android.permission.WRITE_GSERVICES";
     field public static final java.lang.String WRITE_MEDIA_STORAGE = "android.permission.WRITE_MEDIA_STORAGE";
     field public static final java.lang.String WRITE_SECURE_SETTINGS = "android.permission.WRITE_SECURE_SETTINGS";
@@ -341,11 +343,13 @@
     method public java.lang.String getChannelId();
     method public android.app.PendingIntent getContentIntent();
     method public android.app.PendingIntent getDeleteIntent();
+    method public boolean getSuppressShowOverApps();
     method public boolean isAvailableOnTv();
     method public android.app.Notification.TvExtender setChannel(java.lang.String);
     method public android.app.Notification.TvExtender setChannelId(java.lang.String);
     method public android.app.Notification.TvExtender setContentIntent(android.app.PendingIntent);
     method public android.app.Notification.TvExtender setDeleteIntent(android.app.PendingIntent);
+    method public android.app.Notification.TvExtender setSuppressShowOverApps(boolean);
   }
 
   public final class NotificationChannel implements android.os.Parcelable {
@@ -791,6 +795,7 @@
     method public abstract void sendOrderedBroadcast(android.content.Intent, java.lang.String, android.os.Bundle, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
     field public static final java.lang.String BACKUP_SERVICE = "backup";
     field public static final java.lang.String CONTEXTHUB_SERVICE = "contexthub";
+    field public static final java.lang.String EUICC_CARD_SERVICE = "euicc_card";
     field public static final java.lang.String HDMI_CONTROL_SERVICE = "hdmi_control";
     field public static final java.lang.String NETWORK_SCORE_SERVICE = "network_score";
     field public static final java.lang.String OEM_LOCK_SERVICE = "oem_lock";
@@ -3815,6 +3820,7 @@
     method public void resume();
     method public void suspend();
     method public boolean unbind();
+    method public boolean verifyPayloadMetadata(java.lang.String);
   }
 
   public static final class UpdateEngine.ErrorCodeConstants {
@@ -4142,6 +4148,7 @@
     method public static boolean putString(android.content.ContentResolver, java.lang.String, java.lang.String, java.lang.String, boolean);
     method public static void resetToDefaults(android.content.ContentResolver, java.lang.String);
     field public static final java.lang.String AUTOFILL_COMPAT_ALLOWED_PACKAGES = "autofill_compat_allowed_packages";
+    field public static final java.lang.String DEFAULT_SM_DP_PLUS = "default_sm_dp_plus";
     field public static final java.lang.String OTA_DISABLE_AUTOMATIC_UPDATE = "ota_disable_automatic_update";
     field public static final java.lang.String THEATER_MODE_ON = "theater_mode_on";
     field public static final java.lang.String WEBVIEW_MULTIPROCESS = "webview_multiprocess";
@@ -4315,6 +4322,125 @@
 
 }
 
+package android.service.euicc {
+
+  public final class EuiccProfileInfo implements android.os.Parcelable {
+    method public int describeContents();
+    method public android.service.carrier.CarrierIdentifier getCarrierIdentifier();
+    method public java.lang.String getIccid();
+    method public java.lang.String getNickname();
+    method public int getPolicyRules();
+    method public int getProfileClass();
+    method public java.lang.String getProfileName();
+    method public java.lang.String getServiceProviderName();
+    method public int getState();
+    method public java.util.List<android.telephony.UiccAccessRule> getUiccAccessRules();
+    method public boolean hasPolicyRule(int);
+    method public boolean hasPolicyRules();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.service.euicc.EuiccProfileInfo> CREATOR;
+    field public static final int POLICY_RULE_DELETE_AFTER_DISABLING = 4; // 0x4
+    field public static final int POLICY_RULE_DO_NOT_DELETE = 2; // 0x2
+    field public static final int POLICY_RULE_DO_NOT_DISABLE = 1; // 0x1
+    field public static final int PROFILE_CLASS_OPERATIONAL = 2; // 0x2
+    field public static final int PROFILE_CLASS_PROVISIONING = 1; // 0x1
+    field public static final int PROFILE_CLASS_TESTING = 0; // 0x0
+    field public static final int PROFILE_STATE_DISABLED = 0; // 0x0
+    field public static final int PROFILE_STATE_ENABLED = 1; // 0x1
+  }
+
+  public static final class EuiccProfileInfo.Builder {
+    ctor public EuiccProfileInfo.Builder(java.lang.String);
+    ctor public EuiccProfileInfo.Builder(android.service.euicc.EuiccProfileInfo);
+    method public android.service.euicc.EuiccProfileInfo build();
+    method public android.service.euicc.EuiccProfileInfo.Builder setCarrierIdentifier(android.service.carrier.CarrierIdentifier);
+    method public android.service.euicc.EuiccProfileInfo.Builder setIccid(java.lang.String);
+    method public android.service.euicc.EuiccProfileInfo.Builder setNickname(java.lang.String);
+    method public android.service.euicc.EuiccProfileInfo.Builder setPolicyRules(int);
+    method public android.service.euicc.EuiccProfileInfo.Builder setProfileClass(int);
+    method public android.service.euicc.EuiccProfileInfo.Builder setProfileName(java.lang.String);
+    method public android.service.euicc.EuiccProfileInfo.Builder setServiceProviderName(java.lang.String);
+    method public android.service.euicc.EuiccProfileInfo.Builder setState(int);
+    method public android.service.euicc.EuiccProfileInfo.Builder setUiccAccessRule(java.util.List<android.telephony.UiccAccessRule>);
+  }
+
+  public static abstract class EuiccProfileInfo.PolicyRule implements java.lang.annotation.Annotation {
+  }
+
+  public static abstract class EuiccProfileInfo.ProfileClass implements java.lang.annotation.Annotation {
+  }
+
+  public static abstract class EuiccProfileInfo.ProfileState implements java.lang.annotation.Annotation {
+  }
+
+  public abstract class EuiccService extends android.app.Service {
+    ctor public EuiccService();
+    method public android.os.IBinder onBind(android.content.Intent);
+    method public abstract int onDeleteSubscription(int, java.lang.String);
+    method public abstract int onDownloadSubscription(int, android.telephony.euicc.DownloadableSubscription, boolean, boolean);
+    method public abstract int onEraseSubscriptions(int);
+    method public abstract android.service.euicc.GetDefaultDownloadableSubscriptionListResult onGetDefaultDownloadableSubscriptionList(int, boolean);
+    method public abstract android.service.euicc.GetDownloadableSubscriptionMetadataResult onGetDownloadableSubscriptionMetadata(int, android.telephony.euicc.DownloadableSubscription, boolean);
+    method public abstract java.lang.String onGetEid(int);
+    method public abstract android.telephony.euicc.EuiccInfo onGetEuiccInfo(int);
+    method public abstract android.service.euicc.GetEuiccProfileInfoListResult onGetEuiccProfileInfoList(int);
+    method public abstract int onGetOtaStatus(int);
+    method public abstract int onRetainSubscriptionsForFactoryReset(int);
+    method public abstract void onStartOtaIfNecessary(int, android.service.euicc.EuiccService.OtaStatusChangedCallback);
+    method public abstract int onSwitchToSubscription(int, java.lang.String, boolean);
+    method public abstract int onUpdateSubscriptionNickname(int, java.lang.String, java.lang.String);
+    field public static final java.lang.String ACTION_MANAGE_EMBEDDED_SUBSCRIPTIONS = "android.service.euicc.action.MANAGE_EMBEDDED_SUBSCRIPTIONS";
+    field public static final java.lang.String ACTION_PROVISION_EMBEDDED_SUBSCRIPTION = "android.service.euicc.action.PROVISION_EMBEDDED_SUBSCRIPTION";
+    field public static final java.lang.String ACTION_RESOLVE_CONFIRMATION_CODE = "android.service.euicc.action.RESOLVE_CONFIRMATION_CODE";
+    field public static final java.lang.String ACTION_RESOLVE_DEACTIVATE_SIM = "android.service.euicc.action.RESOLVE_DEACTIVATE_SIM";
+    field public static final java.lang.String ACTION_RESOLVE_NO_PRIVILEGES = "android.service.euicc.action.RESOLVE_NO_PRIVILEGES";
+    field public static final java.lang.String CATEGORY_EUICC_UI = "android.service.euicc.category.EUICC_UI";
+    field public static final java.lang.String EUICC_SERVICE_INTERFACE = "android.service.euicc.EuiccService";
+    field public static final java.lang.String EXTRA_RESOLUTION_CALLING_PACKAGE = "android.service.euicc.extra.RESOLUTION_CALLING_PACKAGE";
+    field public static final java.lang.String EXTRA_RESOLUTION_CONFIRMATION_CODE = "android.service.euicc.extra.RESOLUTION_CONFIRMATION_CODE";
+    field public static final java.lang.String EXTRA_RESOLUTION_CONFIRMATION_CODE_RETRIED = "android.service.euicc.extra.RESOLUTION_CONFIRMATION_CODE_RETRIED";
+    field public static final java.lang.String EXTRA_RESOLUTION_CONSENT = "android.service.euicc.extra.RESOLUTION_CONSENT";
+    field public static final int RESULT_FIRST_USER = 1; // 0x1
+    field public static final int RESULT_MUST_DEACTIVATE_SIM = -1; // 0xffffffff
+    field public static final int RESULT_NEED_CONFIRMATION_CODE = -2; // 0xfffffffe
+    field public static final int RESULT_OK = 0; // 0x0
+  }
+
+  public static abstract class EuiccService.OtaStatusChangedCallback {
+    ctor public EuiccService.OtaStatusChangedCallback();
+    method public abstract void onOtaStatusChanged(int);
+  }
+
+  public final class GetDefaultDownloadableSubscriptionListResult implements android.os.Parcelable {
+    ctor public GetDefaultDownloadableSubscriptionListResult(int, android.telephony.euicc.DownloadableSubscription[]);
+    method public int describeContents();
+    method public java.util.List<android.telephony.euicc.DownloadableSubscription> getDownloadableSubscriptions();
+    method public int getResult();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.service.euicc.GetDefaultDownloadableSubscriptionListResult> CREATOR;
+  }
+
+  public final class GetDownloadableSubscriptionMetadataResult implements android.os.Parcelable {
+    ctor public GetDownloadableSubscriptionMetadataResult(int, android.telephony.euicc.DownloadableSubscription);
+    method public int describeContents();
+    method public android.telephony.euicc.DownloadableSubscription getDownloadableSubscription();
+    method public int getResult();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.service.euicc.GetDownloadableSubscriptionMetadataResult> CREATOR;
+  }
+
+  public final class GetEuiccProfileInfoListResult implements android.os.Parcelable {
+    ctor public GetEuiccProfileInfoListResult(int, android.service.euicc.EuiccProfileInfo[], boolean);
+    method public int describeContents();
+    method public boolean getIsRemovable();
+    method public java.util.List<android.service.euicc.EuiccProfileInfo> getProfiles();
+    method public int getResult();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.service.euicc.GetEuiccProfileInfoListResult> CREATOR;
+  }
+
+}
+
 package android.service.notification {
 
   public final class Adjustment implements android.os.Parcelable {
@@ -4915,8 +5041,14 @@
     field public static final int RESULT_SYSTEM_ERROR = 15; // 0xf
   }
 
+  public class SubscriptionInfo implements android.os.Parcelable {
+    method public java.util.List<android.telephony.UiccAccessRule> getAccessRules();
+  }
+
   public class SubscriptionManager {
+    method public java.util.List<android.telephony.SubscriptionInfo> getAvailableSubscriptionInfoList();
     method public java.util.List<android.telephony.SubscriptionPlan> getSubscriptionPlans(int);
+    method public void requestEmbeddedSubscriptionInfoListRefresh();
     method public void setSubscriptionOverrideCongested(int, boolean, long);
     method public void setSubscriptionOverrideUnmetered(int, boolean, long);
     method public void setSubscriptionPlans(int, java.util.List<android.telephony.SubscriptionPlan>);
@@ -5052,6 +5184,16 @@
     field public static final int SIM_STATE_PRESENT = 11; // 0xb
   }
 
+  public final class UiccAccessRule implements android.os.Parcelable {
+    ctor public UiccAccessRule(byte[], java.lang.String, long);
+    method public int describeContents();
+    method public int getCarrierPrivilegeStatus(android.content.pm.PackageInfo);
+    method public int getCarrierPrivilegeStatus(android.content.pm.Signature, java.lang.String);
+    method public java.lang.String getPackageName();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.telephony.UiccAccessRule> CREATOR;
+  }
+
   public class UiccSlotInfo implements android.os.Parcelable {
     ctor public UiccSlotInfo(boolean, boolean, java.lang.String, int, int);
     method public int describeContents();
@@ -5162,6 +5304,125 @@
 
 }
 
+package android.telephony.euicc {
+
+  public final class DownloadableSubscription implements android.os.Parcelable {
+    method public java.util.List<android.telephony.UiccAccessRule> getAccessRules();
+    method public java.lang.String getCarrierName();
+  }
+
+  public static final class DownloadableSubscription.Builder {
+    ctor public DownloadableSubscription.Builder();
+    ctor public DownloadableSubscription.Builder(android.telephony.euicc.DownloadableSubscription);
+    method public android.telephony.euicc.DownloadableSubscription build();
+    method public android.telephony.euicc.DownloadableSubscription.Builder setAccessRules(java.util.List<android.telephony.UiccAccessRule>);
+    method public android.telephony.euicc.DownloadableSubscription.Builder setCarrierName(java.lang.String);
+    method public android.telephony.euicc.DownloadableSubscription.Builder setConfirmationCode(java.lang.String);
+    method public android.telephony.euicc.DownloadableSubscription.Builder setEncodedActivationCode(java.lang.String);
+  }
+
+  public class EuiccCardManager {
+    method public void authenticateServer(java.lang.String, java.lang.String, byte[], byte[], byte[], byte[], java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<byte[]>);
+    method public void cancelSession(java.lang.String, byte[], int, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<byte[]>);
+    method public void deleteProfile(java.lang.String, java.lang.String, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<java.lang.Void>);
+    method public void disableProfile(java.lang.String, java.lang.String, boolean, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<java.lang.Void>);
+    method public void listNotifications(java.lang.String, int, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<android.telephony.euicc.EuiccNotification[]>);
+    method public void loadBoundProfilePackage(java.lang.String, byte[], java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<byte[]>);
+    method public void prepareDownload(java.lang.String, byte[], byte[], byte[], byte[], java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<byte[]>);
+    method public void removeNotificationFromList(java.lang.String, int, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<java.lang.Void>);
+    method public void requestAllProfiles(java.lang.String, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<android.service.euicc.EuiccProfileInfo[]>);
+    method public void requestDefaultSmdpAddress(java.lang.String, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<java.lang.String>);
+    method public void requestEuiccChallenge(java.lang.String, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<byte[]>);
+    method public void requestEuiccInfo1(java.lang.String, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<byte[]>);
+    method public void requestEuiccInfo2(java.lang.String, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<byte[]>);
+    method public void requestProfile(java.lang.String, java.lang.String, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<android.service.euicc.EuiccProfileInfo>);
+    method public void requestRulesAuthTable(java.lang.String, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<android.telephony.euicc.EuiccRulesAuthTable>);
+    method public void requestSmdsAddress(java.lang.String, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<java.lang.String>);
+    method public void resetMemory(java.lang.String, int, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<java.lang.Void>);
+    method public void retrieveNotification(java.lang.String, int, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<android.telephony.euicc.EuiccNotification>);
+    method public void retrieveNotificationList(java.lang.String, int, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<android.telephony.euicc.EuiccNotification[]>);
+    method public void setDefaultSmdpAddress(java.lang.String, java.lang.String, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<java.lang.Void>);
+    method public void setNickname(java.lang.String, java.lang.String, java.lang.String, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<java.lang.Void>);
+    method public void switchToProfile(java.lang.String, java.lang.String, boolean, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<android.service.euicc.EuiccProfileInfo>);
+    field public static final int CANCEL_REASON_END_USER_REJECTED = 0; // 0x0
+    field public static final int CANCEL_REASON_POSTPONED = 1; // 0x1
+    field public static final int CANCEL_REASON_PPR_NOT_ALLOWED = 3; // 0x3
+    field public static final int CANCEL_REASON_TIMEOUT = 2; // 0x2
+    field public static final int RESET_OPTION_DELETE_FIELD_LOADED_TEST_PROFILES = 2; // 0x2
+    field public static final int RESET_OPTION_DELETE_OPERATIONAL_PROFILES = 1; // 0x1
+    field public static final int RESET_OPTION_RESET_DEFAULT_SMDP_ADDRESS = 4; // 0x4
+    field public static final int RESULT_OK = 0; // 0x0
+    field public static final int RESULT_UNKNOWN_ERROR = -1; // 0xffffffff
+  }
+
+  public static abstract class EuiccCardManager.CancelReason implements java.lang.annotation.Annotation {
+  }
+
+  public static abstract class EuiccCardManager.ResetOption implements java.lang.annotation.Annotation {
+  }
+
+  public static abstract interface EuiccCardManager.ResultCallback<T> {
+    method public abstract void onComplete(int, T);
+  }
+
+  public class EuiccManager {
+    method public void continueOperation(android.content.Intent, android.os.Bundle);
+    method public void getDefaultDownloadableSubscriptionList(android.app.PendingIntent);
+    method public void getDownloadableSubscriptionMetadata(android.telephony.euicc.DownloadableSubscription, android.app.PendingIntent);
+    method public int getOtaStatus();
+    field public static final java.lang.String ACTION_OTA_STATUS_CHANGED = "android.telephony.euicc.action.OTA_STATUS_CHANGED";
+    field public static final java.lang.String ACTION_PROVISION_EMBEDDED_SUBSCRIPTION = "android.telephony.euicc.action.PROVISION_EMBEDDED_SUBSCRIPTION";
+    field public static final int EUICC_OTA_FAILED = 2; // 0x2
+    field public static final int EUICC_OTA_IN_PROGRESS = 1; // 0x1
+    field public static final int EUICC_OTA_NOT_NEEDED = 4; // 0x4
+    field public static final int EUICC_OTA_STATUS_UNAVAILABLE = 5; // 0x5
+    field public static final int EUICC_OTA_SUCCEEDED = 3; // 0x3
+    field public static final java.lang.String EXTRA_EMBEDDED_SUBSCRIPTION_DOWNLOADABLE_SUBSCRIPTION = "android.telephony.euicc.extra.EMBEDDED_SUBSCRIPTION_DOWNLOADABLE_SUBSCRIPTION";
+    field public static final java.lang.String EXTRA_EMBEDDED_SUBSCRIPTION_DOWNLOADABLE_SUBSCRIPTIONS = "android.telephony.euicc.extra.EMBEDDED_SUBSCRIPTION_DOWNLOADABLE_SUBSCRIPTIONS";
+  }
+
+  public static abstract class EuiccManager.OtaStatus implements java.lang.annotation.Annotation {
+  }
+
+  public final class EuiccNotification implements android.os.Parcelable {
+    ctor public EuiccNotification(int, java.lang.String, int, byte[]);
+    method public int describeContents();
+    method public byte[] getData();
+    method public int getEvent();
+    method public int getSeq();
+    method public java.lang.String getTargetAddr();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final int ALL_EVENTS = 15; // 0xf
+    field public static final android.os.Parcelable.Creator<android.telephony.euicc.EuiccNotification> CREATOR;
+    field public static final int EVENT_DELETE = 8; // 0x8
+    field public static final int EVENT_DISABLE = 4; // 0x4
+    field public static final int EVENT_ENABLE = 2; // 0x2
+    field public static final int EVENT_INSTALL = 1; // 0x1
+  }
+
+  public static abstract class EuiccNotification.Event implements java.lang.annotation.Annotation {
+  }
+
+  public final class EuiccRulesAuthTable implements android.os.Parcelable {
+    method public int describeContents();
+    method public int findIndex(int, android.service.carrier.CarrierIdentifier);
+    method public boolean hasPolicyRuleFlag(int, int);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.telephony.euicc.EuiccRulesAuthTable> CREATOR;
+    field public static final int POLICY_RULE_FLAG_CONSENT_REQUIRED = 1; // 0x1
+  }
+
+  public static final class EuiccRulesAuthTable.Builder {
+    ctor public EuiccRulesAuthTable.Builder(int);
+    method public android.telephony.euicc.EuiccRulesAuthTable.Builder add(int, java.util.List<android.service.carrier.CarrierIdentifier>, int);
+    method public android.telephony.euicc.EuiccRulesAuthTable build();
+  }
+
+  public static abstract class EuiccRulesAuthTable.PolicyRuleFlag implements java.lang.annotation.Annotation {
+  }
+
+}
+
 package android.telephony.ims {
 
   public final class ImsCallForwardInfo implements android.os.Parcelable {
diff --git a/cmds/incidentd/src/PrivacyBuffer.cpp b/cmds/incidentd/src/PrivacyBuffer.cpp
index 03faa92..f53befe 100644
--- a/cmds/incidentd/src/PrivacyBuffer.cpp
+++ b/cmds/incidentd/src/PrivacyBuffer.cpp
@@ -142,7 +142,7 @@
 PrivacyBuffer::clear()
 {
     mSize = 0;
-    mProto = ProtoOutputStream();
+    mProto.clear();
 }
 
 size_t
diff --git a/cmds/statsd/Android.mk b/cmds/statsd/Android.mk
index 90158a0..67b9089 100644
--- a/cmds/statsd/Android.mk
+++ b/cmds/statsd/Android.mk
@@ -19,11 +19,9 @@
     ../../core/java/android/os/IStatsManager.aidl \
     src/stats_log.proto \
     src/statsd_config.proto \
-    src/statsd_internal.proto \
     src/atoms.proto \
-    src/field_util.cpp \
+    src/FieldValue.cpp \
     src/stats_log_util.cpp \
-    src/dimension.cpp \
     src/anomaly/AnomalyMonitor.cpp \
     src/anomaly/AnomalyTracker.cpp \
     src/anomaly/DurationAnomalyTracker.cpp \
@@ -172,7 +170,6 @@
 
 LOCAL_SRC_FILES := \
     $(statsd_common_src) \
-    tests/dimension_test.cpp \
     tests/AnomalyMonitor_test.cpp \
     tests/anomaly/AnomalyTracker_test.cpp \
     tests/ConfigManager_test.cpp \
@@ -184,6 +181,7 @@
     tests/MetricsManager_test.cpp \
     tests/StatsLogProcessor_test.cpp \
     tests/UidMap_test.cpp \
+    tests/FieldValue_test.cpp \
     tests/condition/CombinationConditionTracker_test.cpp \
     tests/condition/SimpleConditionTracker_test.cpp \
     tests/metrics/OringDurationTracker_test.cpp \
@@ -242,7 +240,8 @@
 LOCAL_SRC_FILES := $(statsd_common_src) \
                    benchmark/main.cpp \
                    benchmark/hello_world_benchmark.cpp \
-                   benchmark/log_event_benchmark.cpp
+                   benchmark/log_event_benchmark.cpp \
+                   benchmark/stats_write_benchmark.cpp
 
 LOCAL_C_INCLUDES := $(statsd_common_c_includes)
 
@@ -261,7 +260,8 @@
     $(statsd_common_static_libraries)
 
 LOCAL_SHARED_LIBRARIES := $(statsd_common_shared_libraries) \
-    libgtest_prod
+    libgtest_prod \
+    libstatslog
 
 LOCAL_PROTOC_OPTIMIZE_TYPE := lite
 
diff --git a/cmds/statsd/AndroidTest.xml b/cmds/statsd/AndroidTest.xml
new file mode 100644
index 0000000..afe30a2
--- /dev/null
+++ b/cmds/statsd/AndroidTest.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<configuration description="Config for statsd_test">
+    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+        <option name="cleanup" value="true" />
+        <option name="push" value="statsd_test->/data/nativetest/statsd_test" />
+    </target_preparer>
+    <option name="test-suite-tag" value="apct" />
+    <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-device-path" value="/data/nativetest" />
+        <option name="module-name" value="statsd_test" />
+    </test>
+</configuration>
\ No newline at end of file
diff --git a/cmds/statsd/benchmark/stats_write_benchmark.cpp b/cmds/statsd/benchmark/stats_write_benchmark.cpp
new file mode 100644
index 0000000..f5a0cd5
--- /dev/null
+++ b/cmds/statsd/benchmark/stats_write_benchmark.cpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "benchmark/benchmark.h"
+#include <statslog.h>
+
+namespace android {
+namespace os {
+namespace statsd {
+
+static void BM_StatsWrite(benchmark::State& state) {
+    const char* reason = "test";
+    int64_t boot_end_time = 1234567;
+    int64_t total_duration = 100;
+    int64_t bootloader_duration = 10;
+    int64_t time_since_last_boot = 99999999;
+    while (state.KeepRunning()) {
+        android::util::stats_write(
+                android::util::BOOT_SEQUENCE_REPORTED, reason, reason,
+                boot_end_time, total_duration, bootloader_duration, time_since_last_boot);
+        total_duration++;
+    }
+}
+BENCHMARK(BM_StatsWrite);
+
+}  //  namespace statsd
+}  //  namespace os
+}  //  namespace android
diff --git a/cmds/statsd/src/FieldValue.cpp b/cmds/statsd/src/FieldValue.cpp
new file mode 100644
index 0000000..7b0b69a
--- /dev/null
+++ b/cmds/statsd/src/FieldValue.cpp
@@ -0,0 +1,186 @@
+/*
+ * 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.
+ */
+
+#define DEBUG false
+#include "Log.h"
+#include "FieldValue.h"
+#include "HashableDimensionKey.h"
+
+namespace android {
+namespace os {
+namespace statsd {
+
+bool Field::matches(const Matcher& matcher) const {
+    if (mTag != matcher.mMatcher.getTag()) {
+        return false;
+    }
+    if ((mField & matcher.mMask) == matcher.mMatcher.getField()) {
+        return true;
+    }
+
+    return false;
+};
+
+void translateFieldMatcher(int tag, const FieldMatcher& matcher, int depth, int* pos, int* mask,
+                           std::vector<Matcher>* output) {
+    if (depth > kMaxLogDepth) {
+        ALOGE("depth > 2");
+        return;
+    }
+
+    pos[depth] = matcher.field();
+    mask[depth] = 0x7f;
+
+    if (matcher.has_position()) {
+        depth++;
+        if (depth > 2) {
+            return;
+        }
+        switch (matcher.position()) {
+            case Position::ANY:
+                pos[depth] = 0;
+                mask[depth] = 0;
+                break;
+            case Position::FIRST:
+                pos[depth] = 1;
+                mask[depth] = 0x7f;
+                break;
+            case Position::LAST:
+                pos[depth] = 0x80;
+                mask[depth] = 0x80;
+                break;
+            case Position::POSITION_UNKNOWN:
+                pos[depth] = 0;
+                mask[depth] = 0;
+                break;
+        }
+    }
+
+    if (matcher.child_size() == 0) {
+        output->push_back(Matcher(Field(tag, pos, depth), encodeMatcherMask(mask, depth)));
+        Matcher matcher = Matcher(Field(tag, pos, depth), encodeMatcherMask(mask, depth));
+    } else {
+        for (const auto& child : matcher.child()) {
+            translateFieldMatcher(tag, child, depth + 1, pos, mask, output);
+        }
+    }
+}
+
+void translateFieldMatcher(const FieldMatcher& matcher, std::vector<Matcher>* output) {
+    int pos[] = {1, 1, 1};
+    int mask[] = {0x7f, 0x7f, 0x7f};
+    int tag = matcher.field();
+    for (const auto& child : matcher.child()) {
+        translateFieldMatcher(tag, child, 0, pos, mask, output);
+    }
+}
+
+bool isAttributionUidField(const FieldValue& value) {
+    int field = value.mField.getField() & 0xff007f;
+    if (field == 0x10001 && value.mValue.getType() == INT) {
+        return true;
+    }
+    return false;
+}
+
+bool isAttributionUidField(const Field& field, const Value& value) {
+    int f = field.getField() & 0xff007f;
+    if (f == 0x10001 && value.getType() == INT) {
+        return true;
+    }
+    return false;
+}
+
+Value::Value(const Value& from) {
+    type = from.getType();
+    switch (type) {
+        case INT:
+            int_value = from.int_value;
+            break;
+        case LONG:
+            long_value = from.long_value;
+            break;
+        case FLOAT:
+            float_value = from.float_value;
+            break;
+        case STRING:
+            str_value = from.str_value;
+            break;
+    }
+}
+
+std::string Value::toString() const {
+    switch (type) {
+        case INT:
+            return std::to_string(int_value) + "[I]";
+        case LONG:
+            return std::to_string(long_value) + "[L]";
+        case FLOAT:
+            return std::to_string(float_value) + "[F]";
+        case STRING:
+            return str_value + "[S]";
+    }
+}
+
+bool Value::operator==(const Value& that) const {
+    if (type != that.getType()) return false;
+
+    switch (type) {
+        case INT:
+            return int_value == that.int_value;
+        case LONG:
+            return long_value == that.long_value;
+        case FLOAT:
+            return float_value == that.float_value;
+        case STRING:
+            return str_value == that.str_value;
+    }
+}
+
+bool Value::operator!=(const Value& that) const {
+    if (type != that.getType()) return true;
+    switch (type) {
+        case INT:
+            return int_value != that.int_value;
+        case LONG:
+            return long_value != that.long_value;
+        case FLOAT:
+            return float_value != that.float_value;
+        case STRING:
+            return str_value != that.str_value;
+    }
+}
+
+bool Value::operator<(const Value& that) const {
+    if (type != that.getType()) return type < that.getType();
+
+    switch (type) {
+        case INT:
+            return int_value < that.int_value;
+        case LONG:
+            return long_value < that.long_value;
+        case FLOAT:
+            return float_value < that.float_value;
+        case STRING:
+            return str_value < that.str_value;
+        default:
+            return false;
+    }
+}
+
+}  // namespace statsd
+}  // namespace os
+}  // namespace android
\ No newline at end of file
diff --git a/cmds/statsd/src/FieldValue.h b/cmds/statsd/src/FieldValue.h
new file mode 100644
index 0000000..7484108
--- /dev/null
+++ b/cmds/statsd/src/FieldValue.h
@@ -0,0 +1,338 @@
+/*
+ * 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.
+ */
+#pragma once
+
+#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
+
+namespace android {
+namespace os {
+namespace statsd {
+
+class HashableDimensionKey;
+struct Matcher;
+struct Field;
+struct FieldValue;
+
+const int32_t kAttributionField = 1;
+const int32_t kMaxLogDepth = 2;
+const int32_t kLastBitMask = 0x80;
+const int32_t kClearLastBitDeco = 0x7f;
+
+enum Type { INT, LONG, FLOAT, STRING };
+
+
+static int32_t getEncodedField(int32_t pos[], int32_t depth, bool includeDepth) {
+    int32_t field = 0;
+    for (int32_t i = 0; i <= depth; i++) {
+        int32_t shiftBits = 8 * (kMaxLogDepth - i);
+        field |= (pos[i] << shiftBits);
+    }
+
+    if (includeDepth) {
+        field |= (depth << 24);
+    }
+    return field;
+}
+
+static int32_t encodeMatcherMask(int32_t mask[], int32_t depth) {
+    return getEncodedField(mask, depth, false) | 0xff000000;
+}
+
+// Get the encoded field for a leaf with a [field] number at depth 0;
+static int32_t getSimpleField(size_t field) {
+    return ((int32_t)field << 8 * 2);
+}
+
+/**
+ * Field is a wrapper class for 2 integers that represents the field of a log element in its Atom
+ * proto.
+ * [mTag]: the atom id.
+ * [mField]: encoded path from the root (atom) to leaf.
+ *
+ * For example:
+ * WakeLockStateChanged {
+ *    repeated AttributionNode = 1;
+ *    int state = 2;
+ *    string tag = 3;
+ * }
+ * Read from logd, the items are structured as below:
+ * [[[1000, "tag"], [2000, "tag2"],], 2,"hello"]
+ *
+ * When we read through the list, we will encode each field in a 32bit integer.
+ * 8bit segments   |--------|--------|--------|--------|
+ *                    Depth   field0 [L]field1 [L]field1
+ *
+ *  The first 8 bits are the depth of the field. for example, the uid 1000 has depth 2.
+ *  The following 3 8-bit are for the item's position at each level.
+ *  The first bit of each 8bits field is reserved to mark if the item is the last item at that level
+ *  this is to make matching easier later.
+ *
+ *  The above wakelock event is translated into FieldValue pairs.
+ *  0x02010101->1000
+ *  0x02010182->tag
+ *  0x02018201->2000
+ *  0x02018282->tag2
+ *  0x00020000->2
+ *  0x00030000->"hello"
+ *
+ *  This encoding is the building block for the later operations.
+ *  Please see the definition for Matcher below to see how the matching is done.
+ */
+struct Field {
+private:
+    int32_t mTag;
+    int32_t mField;
+
+public:
+    Field(int32_t tag, int32_t pos[], int32_t depth) : mTag(tag) {
+        mField = getEncodedField(pos, depth, true);
+    }
+
+    Field(const Field& from) : mTag(from.getTag()), mField(from.getField()) {
+    }
+
+    Field(int32_t tag, int32_t field) : mTag(tag), mField(field){};
+
+    inline void setField(int32_t field) {
+        mField = field;
+    }
+
+    inline void setTag(int32_t tag) {
+        mTag = tag;
+    }
+
+    inline void decorateLastPos(int32_t depth) {
+        int32_t mask = kLastBitMask << 8 * (kMaxLogDepth - depth);
+        mField |= mask;
+    }
+
+    inline int32_t getTag() const {
+        return mTag;
+    }
+
+    inline int32_t getDepth() const {
+        return (mField >> 24);
+    }
+
+    inline int32_t getPath(int32_t depth) const {
+        if (depth > 2 || depth < 0) return 0;
+
+        int32_t field = (mField & 0x00ffffff);
+        int32_t mask = 0xffffffff;
+        return (field & (mask << 8 * (kMaxLogDepth - depth)));
+    }
+
+    inline int32_t getPrefix(int32_t depth) const {
+        if (depth == 0) return 0;
+        return getPath(depth - 1);
+    }
+
+    inline int32_t getField() const {
+        return mField;
+    }
+
+    inline int32_t getRawPosAtDepth(int32_t depth) const {
+        int32_t field = (mField & 0x00ffffff);
+        int32_t shift = 8 * (kMaxLogDepth - depth);
+        int32_t mask = 0xff << shift;
+
+        return (field & mask) >> shift;
+    }
+
+    inline int32_t getPosAtDepth(int32_t depth) const {
+        return getRawPosAtDepth(depth) & kClearLastBitDeco;
+    }
+
+    // Check if the first bit of the 8-bit segment for depth is 1
+    inline bool isLastPos(int32_t depth) const {
+        int32_t field = (mField & 0x00ffffff);
+        int32_t mask = kLastBitMask << 8 * (kMaxLogDepth - depth);
+        return (field & mask) != 0;
+    }
+
+    // if the 8-bit segment is all 0's
+    inline bool isAnyPosMatcher(int32_t depth) const {
+        return getDepth() >= depth && getRawPosAtDepth(depth) == 0;
+    }
+    // if the 8bit is 0x80 (1000 0000)
+    inline bool isLastPosMatcher(int32_t depth) const {
+        return getDepth() >= depth && getRawPosAtDepth(depth) == kLastBitMask;
+    }
+
+    inline bool operator==(const Field& that) const {
+        return mTag == that.getTag() && mField == that.getField();
+    };
+
+    inline bool operator!=(const Field& that) const {
+        return mTag != that.getTag() || mField != that.getField();
+    };
+
+    bool operator<(const Field& that) const {
+        if (mTag != that.getTag()) {
+            return mTag < that.getTag();
+        }
+
+        if (mField != that.getField()) {
+            return mField < that.getField();
+        }
+
+        return false;
+    }
+    bool matches(const Matcher& that) const;
+};
+
+/**
+ * Matcher represents a leaf matcher in the FieldMatcher in statsd_config.
+ *
+ * It contains all information needed to match one or more leaf node.
+ * All information is encoded in a Field(2 ints) and a bit mask(1 int).
+ *
+ * For example, to match the first/any/last uid field in attribution chain in Atom 10,
+ * we have the following FieldMatcher in statsd_config
+ *    FieldMatcher {
+ *        field:10
+ *         FieldMatcher {
+ *              field:1
+ *              position: any/last/first
+ *              FieldMatcher {
+ *                  field:1
+ *              }
+ *          }
+ *     }
+ *
+ * We translate the FieldMatcher into a Field, and mask
+ * First: [Matcher Field] 0x02010101  [Mask]0xffff7fff
+ * Last:  [Matcher Field] 0x02018001  [Mask]0xffff80ff
+ * Any:   [Matcher Field] 0x02010001  [Mask]0xffff00ff
+ *
+ * [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
+ * equal. Nothing can beat the performance of this matching algorithm.
+ *
+ * TODO: ADD EXAMPLE HERE.
+ */
+struct Matcher {
+    Matcher(const Field& matcher, int32_t mask) : mMatcher(matcher), mMask(mask){};
+
+    const Field mMatcher;
+    const int32_t mMask;
+
+    bool hasAnyPositionMatcher(int* prefix) const {
+        if (mMatcher.getDepth() == 2 && mMatcher.getRawPosAtDepth(2) == 0) {
+            (*prefix) = mMatcher.getPrefix(2);
+            return true;
+        }
+        return false;
+    }
+};
+
+/**
+ * A wrapper for a union type to contain multiple types of values.
+ *
+ */
+struct Value {
+    Value(int32_t v) {
+        int_value = v;
+        type = INT;
+    }
+
+    Value(int64_t v) {
+        long_value = v;
+        type = LONG;
+    }
+
+    Value(float v) {
+        float_value = v;
+        type = FLOAT;
+    }
+
+    Value(const std::string& v) {
+        str_value = v;
+        type = STRING;
+    }
+
+    void setInt(int32_t v) {
+        int_value = v;
+        type = INT;
+    }
+
+    void setLong(int64_t v) {
+        long_value = v;
+        type = LONG;
+    }
+
+    union {
+        int32_t int_value;
+        int64_t long_value;
+        float float_value;
+    };
+    std::string str_value;
+
+    Type type;
+
+    std::string toString() const;
+
+    Type getType() const {
+        return type;
+    }
+
+    Value(const Value& from);
+
+    bool operator==(const Value& that) const;
+    bool operator!=(const Value& that) const;
+
+    bool operator<(const Value& that) const;
+
+private:
+    Value(){};
+};
+
+/**
+ * Represents a log item, or a dimension item (They are essentially the same).
+ */
+struct FieldValue {
+    FieldValue(const Field& field, const Value& value) : mField(field), mValue(value) {
+    }
+    bool operator==(const FieldValue& that) const {
+        return mField == that.mField && mValue == that.mValue;
+    }
+    bool operator!=(const FieldValue& that) const {
+        return mField != that.mField || mValue != that.mValue;
+    }
+    bool operator<(const FieldValue& that) const {
+        if (mField != that.mField) {
+            return mField < that.mField;
+        }
+
+        if (mValue != that.mValue) {
+            return mValue < that.mValue;
+        }
+
+        return false;
+    }
+
+    Field mField;
+    Value mValue;
+};
+
+bool isAttributionUidField(const FieldValue& value);
+
+void translateFieldMatcher(const FieldMatcher& matcher, std::vector<Matcher>* output);
+
+bool isAttributionUidField(const Field& field, const Value& value);
+}  // namespace statsd
+}  // namespace os
+}  // namespace android
diff --git a/cmds/statsd/src/HashableDimensionKey.cpp b/cmds/statsd/src/HashableDimensionKey.cpp
index 8483b02..68e2176 100644
--- a/cmds/statsd/src/HashableDimensionKey.cpp
+++ b/cmds/statsd/src/HashableDimensionKey.cpp
@@ -13,177 +13,253 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+#define DEBUG false  // STOPSHIP if true
+#include "Log.h"
 
 #include "HashableDimensionKey.h"
-#include "dimension.h"
+#include "FieldValue.h"
 
 namespace android {
 namespace os {
 namespace statsd {
+using std::vector;
 
-android::hash_t hashDimensionsValue(int64_t seed, const DimensionsValue& value) {
-    android::hash_t hash = seed;
-    hash = android::JenkinsHashMix(hash, android::hash_type(value.field()));
-
-    hash = android::JenkinsHashMix(hash, android::hash_type((int)value.value_case()));
-    switch (value.value_case()) {
-        case DimensionsValue::ValueCase::kValueStr:
-            hash = android::JenkinsHashMix(
-                    hash,
-                    static_cast<uint32_t>(std::hash<std::string>()(value.value_str())));
-            break;
-        case DimensionsValue::ValueCase::kValueInt:
-            hash = android::JenkinsHashMix(hash, android::hash_type(value.value_int()));
-            break;
-        case DimensionsValue::ValueCase::kValueLong:
-            hash = android::JenkinsHashMix(
-                    hash, android::hash_type(static_cast<int64_t>(value.value_long())));
-            break;
-        case DimensionsValue::ValueCase::kValueBool:
-            hash = android::JenkinsHashMix(hash, android::hash_type(value.value_bool()));
-            break;
-        case DimensionsValue::ValueCase::kValueFloat: {
-            float floatVal = value.value_float();
-            hash = android::JenkinsHashMixBytes(hash, (uint8_t*)&floatVal, sizeof(float));
-            break;
-        }
-        case DimensionsValue::ValueCase::kValueTuple: {
-            hash = android::JenkinsHashMix(hash, android::hash_type(
-                value.value_tuple().dimensions_value_size()));
-            for (int i = 0; i < value.value_tuple().dimensions_value_size(); ++i) {
-                hash = android::JenkinsHashMix(
-                    hash,
-                    hashDimensionsValue(value.value_tuple().dimensions_value(i)));
+android::hash_t hashDimension(const HashableDimensionKey& value) {
+    android::hash_t hash = 0;
+    for (const auto& fieldValue : value.getValues()) {
+        hash = android::JenkinsHashMix(hash, android::hash_type((int)fieldValue.mField.getField()));
+        hash = android::JenkinsHashMix(hash, android::hash_type((int)fieldValue.mField.getTag()));
+        hash = android::JenkinsHashMix(hash, android::hash_type((int)fieldValue.mValue.getType()));
+        switch (fieldValue.mValue.getType()) {
+            case INT:
+                hash = android::JenkinsHashMix(hash,
+                                               android::hash_type(fieldValue.mValue.int_value));
+                break;
+            case LONG:
+                hash = android::JenkinsHashMix(hash,
+                                               android::hash_type(fieldValue.mValue.long_value));
+                break;
+            case STRING:
+                hash = android::JenkinsHashMix(hash, static_cast<uint32_t>(std::hash<std::string>()(
+                                                             fieldValue.mValue.str_value)));
+                break;
+            case FLOAT: {
+                float floatVal = fieldValue.mValue.float_value;
+                hash = android::JenkinsHashMixBytes(hash, (uint8_t*)&floatVal, sizeof(float));
+                break;
             }
-            break;
         }
-        case DimensionsValue::ValueCase::VALUE_NOT_SET:
-            break;
     }
     return JenkinsHashWhiten(hash);
 }
 
-android::hash_t hashDimensionsValue(const DimensionsValue& value) {
-    return hashDimensionsValue(0, value);
-}
-
-android::hash_t hashMetricDimensionKey(int64_t seed, const MetricDimensionKey& dimensionKey) {
-    android::hash_t hash = seed;
-    hash = android::JenkinsHashMix(hash, std::hash<MetricDimensionKey>{}(dimensionKey));
-    return JenkinsHashWhiten(hash);
-}
-
-using std::string;
-
-string HashableDimensionKey::toString() const {
-    return DimensionsValueToString(getDimensionsValue());
-}
-
-bool EqualsTo(const DimensionsValue& s1, const DimensionsValue& s2) {
-    if (s1.field() != s2.field()) {
-        return false;
-    }
-    if (s1.value_case() != s2.value_case()) {
-        return false;
-    }
-    switch (s1.value_case()) {
-        case DimensionsValue::ValueCase::kValueStr:
-            return (s1.value_str() == s2.value_str());
-        case DimensionsValue::ValueCase::kValueInt:
-            return s1.value_int() == s2.value_int();
-        case DimensionsValue::ValueCase::kValueLong:
-            return s1.value_long() == s2.value_long();
-        case DimensionsValue::ValueCase::kValueBool:
-            return s1.value_bool() == s2.value_bool();
-        case DimensionsValue::ValueCase::kValueFloat:
-            return s1.value_float() == s2.value_float();
-        case DimensionsValue::ValueCase::kValueTuple:
-            {
-                if (s1.value_tuple().dimensions_value_size() !=
-                        s2.value_tuple().dimensions_value_size()) {
-                    return false;
-                }
-                bool allMatched = true;
-                for (int i = 0; allMatched && i < s1.value_tuple().dimensions_value_size(); ++i) {
-                    allMatched &= EqualsTo(s1.value_tuple().dimensions_value(i),
-                                           s2.value_tuple().dimensions_value(i));
-                }
-                return allMatched;
+// 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.
+    for (const auto& matcher : matcherFields) {
+        vector<FieldValue> matchedResults;
+        for (const auto& value : values) {
+            // TODO: potential optimization here to break early because all fields are naturally
+            // sorted.
+            int32_t filteredField;
+            if (value.mField.matches(matcher)) {
+                matchedResults.push_back(FieldValue(
+                        Field(value.mField.getTag(), (value.mField.getField() & matcher.mMask)),
+                        value.mValue));
             }
-        case DimensionsValue::ValueCase::VALUE_NOT_SET:
-        default:
-            return true;
-    }
-}
+        }
 
-bool LessThan(const DimensionsValue& s1, const DimensionsValue& s2) {
-    if (s1.field() != s2.field()) {
-        return s1.field() < s2.field();
-    }
-    if (s1.value_case() != s2.value_case()) {
-        return s1.value_case() < s2.value_case();
-    }
-    switch (s1.value_case()) {
-        case DimensionsValue::ValueCase::kValueStr:
-            return s1.value_str() < s2.value_str();
-        case DimensionsValue::ValueCase::kValueInt:
-            return s1.value_int() < s2.value_int();
-        case DimensionsValue::ValueCase::kValueLong:
-            return s1.value_long() < s2.value_long();
-        case DimensionsValue::ValueCase::kValueBool:
-            return (int)s1.value_bool() < (int)s2.value_bool();
-        case DimensionsValue::ValueCase::kValueFloat:
-            return s1.value_float() < s2.value_float();
-        case DimensionsValue::ValueCase::kValueTuple:
-            {
-                if (s1.value_tuple().dimensions_value_size() !=
-                        s2.value_tuple().dimensions_value_size()) {
-                    return s1.value_tuple().dimensions_value_size() <
-                        s2.value_tuple().dimensions_value_size();
-                }
-                for (int i = 0;  i < s1.value_tuple().dimensions_value_size(); ++i) {
-                    if (EqualsTo(s1.value_tuple().dimensions_value(i),
-                                 s2.value_tuple().dimensions_value(i))) {
-                        continue;
-                    } else {
-                        return LessThan(s1.value_tuple().dimensions_value(i),
-                                        s2.value_tuple().dimensions_value(i));
-                    }
-                }
+        if (matchedResults.size() == 0) {
+            VLOG("We can't find a dimension value for matcher (%d)%#x.", matcher.mMatcher.getTag(),
+                   matcher.mMatcher.getField());
+            continue;
+        }
+
+        if (matchedResults.size() == 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 < matchedResults.size(); i++) {
+                output->insert(output->end(), output->begin(), output->begin() + oldSize);
+            }
+            prevPrevFanout = oldSize;
+            prevFanout = matchedResults.size();
+        } else {
+            // If we should not create fanout, e.g., uid tag from same position should be remain
+            // together.
+            oldSize = prevPrevFanout;
+            if (prevFanout != matchedResults.size()) {
+                // sanity check.
+                ALOGE("2 Any matcher result in different output");
                 return false;
             }
-        case DimensionsValue::ValueCase::VALUE_NOT_SET:
-        default:
-            return false;
+        }
+        // now add the matched field value to output
+        for (size_t i = 0; i < matchedResults.size(); i++) {
+            for (int j = 0; j < oldSize; j++) {
+                (*output)[i * oldSize + j].addValue(matchedResults[i]);
+            }
+        }
     }
+
+    return output->size() > 0 && (*output)[0].getValues().size() > 0;
+}
+
+void filterGaugeValues(const std::vector<Matcher>& matcherFields,
+                       const std::vector<FieldValue>& values, std::vector<FieldValue>* output) {
+    for (const auto& field : matcherFields) {
+        for (const auto& value : values) {
+            int filteredField;
+            if (value.mField.matches(field)) {
+                output->push_back(value);
+            }
+        }
+    }
+}
+
+void getDimensionForCondition(const LogEvent& event, Metric2Condition links,
+                              vector<HashableDimensionKey>* conditionDimension) {
+    // Get the dimension first by using dimension from what.
+    filterValues(links.metricFields, event.getValues(), conditionDimension);
+
+    // Then replace the field with the dimension from condition.
+    for (auto& dim : *conditionDimension) {
+        size_t count = dim.getValues().size();
+        if (count != links.conditionFields.size()) {
+            // ALOGE("WTF condition link is bad");
+            return;
+        }
+
+        for (size_t i = 0; i < count; i++) {
+            dim.mutableValue(i)->mField.setField(links.conditionFields[i].mMatcher.getField());
+            dim.mutableValue(i)->mField.setTag(links.conditionFields[i].mMatcher.getTag());
+        }
+    }
+}
+
+bool LessThan(const vector<FieldValue>& s1, const vector<FieldValue>& s2) {
+    if (s1.size() != s2.size()) {
+        return s1.size() < s2.size();
+    }
+
+    size_t count = s1.size();
+    for (size_t i = 0; i < count; i++) {
+        if (s1[i] != s2[i]) {
+            return s1[i] < s2[i];
+        }
+    }
+    return false;
 }
 
 bool HashableDimensionKey::operator==(const HashableDimensionKey& that) const {
-    return EqualsTo(getDimensionsValue(), that.getDimensionsValue());
+    if (mValues.size() != that.getValues().size()) {
+        return false;
+    }
+    size_t count = mValues.size();
+    for (size_t i = 0; i < count; i++) {
+        if (mValues[i] != (that.getValues())[i]) {
+            return false;
+        }
+    }
+    return true;
 };
 
 bool HashableDimensionKey::operator<(const HashableDimensionKey& that) const {
-    return LessThan(getDimensionsValue(), that.getDimensionsValue());
+    return LessThan(getValues(), that.getValues());
 };
 
-string MetricDimensionKey::toString() const {
-    string flattened = mDimensionKeyInWhat.toString();
-    flattened += mDimensionKeyInCondition.toString();
-    return flattened;
+bool HashableDimensionKey::contains(const HashableDimensionKey& that) const {
+    if (mValues.size() < that.getValues().size()) {
+        return false;
+    }
+
+    if (mValues.size() == that.getValues().size()) {
+        return (*this) == that;
+    }
+
+    for (const auto& value : that.getValues()) {
+        bool found = false;
+        for (const auto& myValue : mValues) {
+            if (value.mField == myValue.mField && value.mValue == myValue.mValue) {
+                found = true;
+                break;
+            }
+        }
+        if (!found) {
+            return false;
+        }
+    }
+
+    return true;
+}
+
+string HashableDimensionKey::toString() const {
+    std::string output;
+    for (const auto& value : mValues) {
+        output += StringPrintf("(%d)%#x->%s ", value.mField.getTag(), value.mField.getField(),
+                               value.mValue.toString().c_str());
+    }
+    return output;
 }
 
 bool MetricDimensionKey::operator==(const MetricDimensionKey& that) const {
     return mDimensionKeyInWhat == that.getDimensionKeyInWhat() &&
-        mDimensionKeyInCondition == that.getDimensionKeyInCondition();
+           mDimensionKeyInCondition == that.getDimensionKeyInCondition();
 };
 
+string MetricDimensionKey::toString() const {
+    return mDimensionKeyInWhat.toString() + mDimensionKeyInCondition.toString();
+}
+
 bool MetricDimensionKey::operator<(const MetricDimensionKey& that) const {
-    return toString().compare(that.toString()) < 0;
-};
+    if (mDimensionKeyInWhat < that.getDimensionKeyInWhat()) {
+        return true;
+    } else if (that.getDimensionKeyInWhat() < mDimensionKeyInWhat) {
+        return false;
+    }
 
-bool compareDimensionsValue(const DimensionsValue& s1, const DimensionsValue& s2) {
-    return EqualsTo(s1, s2);
+    return mDimensionKeyInCondition < that.getDimensionKeyInCondition();
 }
+
 }  // namespace statsd
 }  // namespace os
 }  // namespace android
\ No newline at end of file
diff --git a/cmds/statsd/src/HashableDimensionKey.h b/cmds/statsd/src/HashableDimensionKey.h
index a31d7a6..89fe317 100644
--- a/cmds/statsd/src/HashableDimensionKey.h
+++ b/cmds/statsd/src/HashableDimensionKey.h
@@ -17,44 +17,66 @@
 #pragma once
 
 #include <utils/JenkinsHash.h>
-#include "frameworks/base/cmds/statsd/src/stats_log.pb.h"
+#include <vector>
+#include "FieldValue.h"
+#include "android-base/stringprintf.h"
+#include "logd/LogEvent.h"
 
 namespace android {
 namespace os {
 namespace statsd {
 
+using android::base::StringPrintf;
+
+struct Metric2Condition {
+    int64_t conditionId;
+    std::vector<Matcher> metricFields;
+    std::vector<Matcher> conditionFields;
+};
+
 class HashableDimensionKey {
 public:
-    explicit HashableDimensionKey(const DimensionsValue& dimensionsValue)
-        : mDimensionsValue(dimensionsValue){};
+    explicit HashableDimensionKey(const std::vector<FieldValue>& values) {
+        mValues = values;
+    }
 
     HashableDimensionKey(){};
 
-    HashableDimensionKey(const HashableDimensionKey& that)
-        : mDimensionsValue(that.getDimensionsValue()){};
+    HashableDimensionKey(const HashableDimensionKey& that) : mValues(that.getValues()){};
 
-    HashableDimensionKey& operator=(const HashableDimensionKey& from) = default;
+    inline void addValue(const FieldValue& value) {
+        mValues.push_back(value);
+    }
+
+    inline const std::vector<FieldValue>& getValues() const {
+        return mValues;
+    }
+
+    inline std::vector<FieldValue>* mutableValues() {
+        return &mValues;
+    }
+
+    inline FieldValue* mutableValue(size_t i) {
+        if (i >= 0 && i < mValues.size()) {
+            return &(mValues[i]);
+        }
+        return nullptr;
+    }
 
     std::string toString() const;
 
-    inline const DimensionsValue& getDimensionsValue() const {
-        return mDimensionsValue;
-    }
-
-    inline DimensionsValue* getMutableDimensionsValue() {
-        return &mDimensionsValue;
+    inline const char* c_str() const {
+        return toString().c_str();
     }
 
     bool operator==(const HashableDimensionKey& that) const;
 
     bool operator<(const HashableDimensionKey& that) const;
 
-    inline const char* c_str() const {
-        return toString().c_str();
-    }
+    bool contains(const HashableDimensionKey& that) const;
 
 private:
-    DimensionsValue mDimensionsValue;
+    std::vector<FieldValue> mValues;
 };
 
 class MetricDimensionKey {
@@ -83,7 +105,7 @@
     }
 
     bool hasDimensionKeyInCondition() const {
-        return mDimensionKeyInCondition.getDimensionsValue().has_field();
+        return mDimensionKeyInCondition.getValues().size() > 0;
     }
 
     bool operator==(const MetricDimensionKey& that) const;
@@ -98,11 +120,32 @@
       HashableDimensionKey mDimensionKeyInCondition;
 };
 
-bool compareDimensionsValue(const DimensionsValue& s1, const DimensionsValue& s2);
+android::hash_t hashDimension(const HashableDimensionKey& key);
 
-android::hash_t hashDimensionsValue(int64_t seed, const DimensionsValue& value);
-android::hash_t hashDimensionsValue(const DimensionsValue& value);
-android::hash_t hashMetricDimensionKey(int64_t see, const MetricDimensionKey& dimensionKey);
+/**
+ * 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,
+ * 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);
+
+/**
+ * Filter the values from FieldValues using the matchers.
+ *
+ * In contrast to the above function, this function will not do any modification to the original
+ * data. Considering it as taking a snapshot on the atom event.
+ */
+void filterGaugeValues(const std::vector<Matcher>& matchers, const std::vector<FieldValue>& values,
+                       std::vector<FieldValue>* output);
+
+void getDimensionForCondition(const LogEvent& event, Metric2Condition links,
+                              std::vector<HashableDimensionKey>* conditionDimension);
 
 }  // namespace statsd
 }  // namespace os
@@ -116,17 +159,15 @@
 template <>
 struct hash<HashableDimensionKey> {
     std::size_t operator()(const HashableDimensionKey& key) const {
-        return hashDimensionsValue(key.getDimensionsValue());
+        return hashDimension(key);
     }
 };
 
 template <>
 struct hash<MetricDimensionKey> {
     std::size_t operator()(const MetricDimensionKey& key) const {
-        android::hash_t hash = hashDimensionsValue(
-            key.getDimensionKeyInWhat().getDimensionsValue());
-        hash = android::JenkinsHashMix(hash,
-                    hashDimensionsValue(key.getDimensionKeyInCondition().getDimensionsValue()));
+        android::hash_t hash = hashDimension(key.getDimensionKeyInWhat());
+        hash = android::JenkinsHashMix(hash, hashDimension(key.getDimensionKeyInCondition()));
         return android::JenkinsHashWhiten(hash);
     }
 };
diff --git a/cmds/statsd/src/StatsLogProcessor.cpp b/cmds/statsd/src/StatsLogProcessor.cpp
index 7662c40..3a20b12 100644
--- a/cmds/statsd/src/StatsLogProcessor.cpp
+++ b/cmds/statsd/src/StatsLogProcessor.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#define DEBUG false  // STOPSHIP if true
+#define DEBUG true  // STOPSHIP if true
 #include "Log.h"
 #include "statslog.h"
 
@@ -25,8 +25,6 @@
 #include "guardrail/StatsdStats.h"
 #include "metrics/CountMetricProducer.h"
 #include "external/StatsPullerManager.h"
-#include "dimension.h"
-#include "field_util.h"
 #include "stats_util.h"
 #include "storage/StorageManager.h"
 
@@ -74,9 +72,6 @@
       mAnomalyMonitor(anomalyMonitor),
       mSendBroadcast(sendBroadcast),
       mTimeBaseSec(timeBaseSec) {
-    // On each initialization of StatsLogProcessor, check stats-data directory to see if there is
-    // any left over data to be read.
-    StorageManager::sendBroadcast(STATS_DATA_DIR, mSendBroadcast);
     StatsPullerManager statsPullerManager;
     statsPullerManager.SetTimeBaseSec(mTimeBaseSec);
 }
@@ -93,27 +88,31 @@
     }
 }
 
+void updateUid(Value* value, int hostUid) {
+    int uid = value->int_value;
+    if (uid != hostUid) {
+        value->setInt(hostUid);
+    }
+}
+
 void StatsLogProcessor::mapIsolatedUidToHostUidIfNecessaryLocked(LogEvent* event) const {
-    std::set<Field, FieldCmp> uidFields;
     if (android::util::kAtomsWithAttributionChain.find(event->GetTagId()) !=
         android::util::kAtomsWithAttributionChain.end()) {
-        FieldMatcher matcher;
-        buildAttributionUidFieldMatcher(event->GetTagId(), Position::ANY, &matcher);
-        findFields(event->getFieldValueMap(), matcher, &uidFields);
-    } else if (android::util::kAtomsWithUidField.find(event->GetTagId()) !=
-               android::util::kAtomsWithUidField.end()) {
-        FieldMatcher matcher;
-        buildSimpleAtomFieldMatcher(
-            event->GetTagId(), 1 /* uid is always the 1st field. */, &matcher);
-        findFields(event->getFieldValueMap(), matcher, &uidFields);
-    }
-
-    for (const auto& uidField : uidFields) {
-        DimensionsValue* value = event->findFieldValueOrNull(uidField);
-        if (value != nullptr && value->value_case() == DimensionsValue::ValueCase::kValueInt) {
-            const int uid = mUidMap->getHostUidOrSelf(value->value_int());
-            value->set_value_int(uid);
+        for (auto& value : *(event->getMutableValues())) {
+            if (value.mField.getPosAtDepth(0) > kAttributionField) {
+                break;
+            }
+            if (isAttributionUidField(value)) {
+                const int hostUid = mUidMap->getHostUidOrSelf(value.mValue.int_value);
+                updateUid(&value.mValue, hostUid);
+            }
         }
+    } else if (android::util::kAtomsWithUidField.find(event->GetTagId()) !=
+                       android::util::kAtomsWithUidField.end() &&
+               event->getValues().size() > 0 && (event->getValues())[0].mValue.getType() == INT) {
+        Value& value = (*event->getMutableValues())[0].mValue;
+        const int hostUid = mUidMap->getHostUidOrSelf(value.int_value);
+        updateUid(&value, hostUid);
     }
 }
 
@@ -212,27 +211,14 @@
     }
 }
 
-void StatsLogProcessor::onDumpReport(const ConfigKey& key, const uint64_t& dumpTimeStampNs,
-                                     ConfigMetricsReportList* report) {
+void StatsLogProcessor::onDumpReport(const ConfigKey& key, const uint64_t dumpTimeStampNs,
+                                     vector<uint8_t>* outData) {
     std::lock_guard<std::mutex> lock(mMetricsMutex);
-    auto it = mMetricsManagers.find(key);
-    if (it == mMetricsManagers.end()) {
-        ALOGW("Config source %s does not exist", key.ToString().c_str());
-        return;
-    }
-    report->mutable_config_key()->set_uid(key.GetUid());
-    report->mutable_config_key()->set_id(key.GetId());
-    ConfigMetricsReport* configMetricsReport = report->add_reports();
-    it->second->onDumpReport(dumpTimeStampNs, configMetricsReport);
-    // TODO: dump uid mapping.
+    onDumpReportLocked(key, dumpTimeStampNs, outData);
 }
 
-void StatsLogProcessor::onDumpReport(const ConfigKey& key, vector<uint8_t>* outData) {
-    std::lock_guard<std::mutex> lock(mMetricsMutex);
-    onDumpReportLocked(key, outData);
-}
-
-void StatsLogProcessor::onDumpReportLocked(const ConfigKey& key, vector<uint8_t>* outData) {
+void StatsLogProcessor::onDumpReportLocked(const ConfigKey& key, const uint64_t dumpTimeStampNs,
+                                           vector<uint8_t>* outData) {
     auto it = mMetricsManagers.find(key);
     if (it == mMetricsManagers.end()) {
         ALOGW("Config source %s does not exist", key.ToString().c_str());
@@ -258,7 +244,7 @@
 
     // First, fill in ConfigMetricsReport using current data on memory, which
     // starts from filling in StatsLogReport's.
-    it->second->onDumpReport(&proto);
+    it->second->onDumpReport(dumpTimeStampNs, &proto);
 
     // Fill in UidMap.
     auto uidMap = mUidMap->getOutput(key);
@@ -292,6 +278,7 @@
             iter.rp()->move(toRead);
         }
     }
+
     StatsdStats::getInstance().noteMetricsReportSent(key);
 }
 
@@ -327,7 +314,7 @@
         StatsdStats::kMaxMetricsBytesPerConfig) {  // Too late. We need to start clearing data.
         // TODO(b/70571383): By 12/15/2017 add API to drop data directly
         ProtoOutputStream proto;
-        metricsManager.onDumpReport(&proto);
+        metricsManager.onDumpReport(time(nullptr) * NS_PER_SEC, &proto);
         StatsdStats::getInstance().noteDataDropped(key);
         VLOG("StatsD had to toss out metrics for %s", key.ToString().c_str());
     } else if (totalBytes > .9 * StatsdStats::kMaxMetricsBytesPerConfig) {
@@ -351,7 +338,7 @@
     for (auto& pair : mMetricsManagers) {
         const ConfigKey& key = pair.first;
         vector<uint8_t> data;
-        onDumpReportLocked(key, &data);
+        onDumpReportLocked(key, time(nullptr) * NS_PER_SEC, &data);
         // TODO: Add a guardrail to prevent accumulation of file on disk.
         string file_name = StringPrintf("%s/%ld_%d_%lld", STATS_DATA_DIR, time(nullptr),
                                         key.GetUid(), (long long)key.GetId());
diff --git a/cmds/statsd/src/StatsLogProcessor.h b/cmds/statsd/src/StatsLogProcessor.h
index 8bbcd75..1444306 100644
--- a/cmds/statsd/src/StatsLogProcessor.h
+++ b/cmds/statsd/src/StatsLogProcessor.h
@@ -46,9 +46,7 @@
 
     size_t GetMetricsSize(const ConfigKey& key) const;
 
-    void onDumpReport(const ConfigKey& key, vector<uint8_t>* outData);
-    void onDumpReport(const ConfigKey& key, const uint64_t& dumpTimeStampNs,
-                      ConfigMetricsReportList* report);
+    void onDumpReport(const ConfigKey& key, const uint64_t dumpTimeNs, vector<uint8_t>* outData);
 
     /* Tells MetricsManager that the alarms in anomalySet have fired. Modifies anomalySet. */
     void onAnomalyAlarmFired(
@@ -80,7 +78,8 @@
 
     sp<AnomalyMonitor> mAnomalyMonitor;
 
-    void onDumpReportLocked(const ConfigKey& key, vector<uint8_t>* outData);
+    void onDumpReportLocked(const ConfigKey& key, const uint64_t dumpTimeNs,
+                            vector<uint8_t>* outData);
 
     /* Check if we should send a broadcast if approaching memory limits and if we're over, we
      * actually delete the data. */
@@ -105,9 +104,14 @@
     FRIEND_TEST(StatsLogProcessorTest, TestRateLimitBroadcast);
     FRIEND_TEST(StatsLogProcessorTest, TestDropWhenByteSizeTooLarge);
     FRIEND_TEST(StatsLogProcessorTest, TestDropWhenByteSizeTooLarge);
-    FRIEND_TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForSumDuration);
-    FRIEND_TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForMaxDuration);
-    FRIEND_TEST(MetricConditionLinkE2eTest, TestMultiplePredicatesAndLinks);
+    FRIEND_TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForSumDuration1);
+    FRIEND_TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForSumDuration2);
+    FRIEND_TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForSumDuration3);
+    FRIEND_TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForMaxDuration1);
+    FRIEND_TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForMaxDuration2);
+    FRIEND_TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForMaxDuration3);
+    FRIEND_TEST(MetricConditionLinkE2eTest, TestMultiplePredicatesAndLinks1);
+    FRIEND_TEST(MetricConditionLinkE2eTest, TestMultiplePredicatesAndLinks2);
     FRIEND_TEST(AttributionE2eTest, TestAttributionMatchAndSlice);
     FRIEND_TEST(GaugeMetricE2eTest, TestMultipleFieldsForPushedEvent);
     FRIEND_TEST(DimensionInConditionE2eTest, TestCountMetricNoLink);
diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp
index c24efec..ee38667 100644
--- a/cmds/statsd/src/StatsService.cpp
+++ b/cmds/statsd/src/StatsService.cpp
@@ -492,7 +492,8 @@
         }
         if (good) {
             vector<uint8_t> data;
-            mProcessor->onDumpReport(ConfigKey(uid, StrToInt64(name)), &data);
+            mProcessor->onDumpReport(ConfigKey(uid, StrToInt64(name)), time(nullptr) * NS_PER_SEC,
+                                     &data);
             // TODO: print the returned StatsLogReport to file instead of printing to logcat.
             if (proto) {
                 for (size_t i = 0; i < data.size(); i ++) {
@@ -668,11 +669,18 @@
                                          "Only system uid can call informAnomalyAlarmFired");
     }
 
-    VLOG("StatsService::informAnomalyAlarmFired succeeded");
+    // TODO: This may be a bug. time(nullptr) can be off (wrt AlarmManager's time) and cause us to
+    //       miss the alarm! Eventually we will switch to using elapsedRealTime everywhere,
+    //       which may hopefully fix the problem, so we'll leave this alone for now.
     uint64_t currentTimeSec = time(nullptr);
     std::unordered_set<sp<const AnomalyAlarm>, SpHash<AnomalyAlarm>> anomalySet =
             mAnomalyMonitor->popSoonerThan(static_cast<uint32_t>(currentTimeSec));
-    mProcessor->onAnomalyAlarmFired(currentTimeSec * NS_PER_SEC, anomalySet);
+    if (anomalySet.size() > 0) {
+        VLOG("Found an anomaly alarm that fired.");
+        mProcessor->onAnomalyAlarmFired(currentTimeSec * NS_PER_SEC, anomalySet);
+    } else {
+        VLOG("Cannot find an anomaly alarm that fired. Perhaps it was recently cancelled.");
+    }
     return Status::ok();
 }
 
@@ -780,7 +788,7 @@
     VLOG("StatsService::getData with Pid %i, Uid %i", ipc->getCallingPid(), ipc->getCallingUid());
     if (checkCallingPermission(String16(kPermissionDump))) {
         ConfigKey configKey(ipc->getCallingUid(), key);
-        mProcessor->onDumpReport(configKey, output);
+        mProcessor->onDumpReport(configKey, time(nullptr) * NS_PER_SEC, output);
         return Status::ok();
     } else {
         return Status::fromExceptionCode(binder::Status::EX_SECURITY);
diff --git a/cmds/statsd/src/anomaly/AnomalyMonitor.cpp b/cmds/statsd/src/anomaly/AnomalyMonitor.cpp
index 72d29d0..ca34dc6 100644
--- a/cmds/statsd/src/anomaly/AnomalyMonitor.cpp
+++ b/cmds/statsd/src/anomaly/AnomalyMonitor.cpp
@@ -96,7 +96,7 @@
     std::lock_guard<std::mutex> lock(mLock);
 
     for (sp<const AnomalyAlarm> t = mPq.top(); t != nullptr && t->timestampSec <= timestampSec;
-         t = mPq.top()) {
+        t = mPq.top()) {
         oldAlarms.insert(t);
         mPq.pop();  // remove t
     }
diff --git a/cmds/statsd/src/anomaly/AnomalyTracker.cpp b/cmds/statsd/src/anomaly/AnomalyTracker.cpp
index 63f6e2a..443d33d 100644
--- a/cmds/statsd/src/anomaly/AnomalyTracker.cpp
+++ b/cmds/statsd/src/anomaly/AnomalyTracker.cpp
@@ -19,7 +19,6 @@
 
 #include "AnomalyTracker.h"
 #include "external/Perfetto.h"
-#include "frameworks/base/libs/incident/proto/android/os/header.pb.h"
 #include "guardrail/StatsdStats.h"
 #include "subscriber/IncidentdReporter.h"
 #include "subscriber/SubscriberReporter.h"
@@ -93,6 +92,9 @@
 
 void AnomalyTracker::addPastBucket(const MetricDimensionKey& key, const int64_t& bucketValue,
                                    const int64_t& bucketNum) {
+    if (mNumOfPastBuckets == 0) {
+        return;
+    }
     flushPastBuckets(bucketNum);
 
     auto& bucket = mPastBuckets[index(bucketNum)];
@@ -107,6 +109,9 @@
 void AnomalyTracker::addPastBucket(std::shared_ptr<DimToValMap> bucketValues,
                                    const int64_t& bucketNum) {
     VLOG("addPastBucket() called.");
+    if (mNumOfPastBuckets == 0) {
+        return;
+    }
     flushPastBuckets(bucketNum);
     // Replace the oldest bucket with the new bucket we are adding.
     mPastBuckets[index(bucketNum)] = bucketValues;
diff --git a/cmds/statsd/src/anomaly/DurationAnomalyTracker.cpp b/cmds/statsd/src/anomaly/DurationAnomalyTracker.cpp
index fa0bc0c..3ba943c 100644
--- a/cmds/statsd/src/anomaly/DurationAnomalyTracker.cpp
+++ b/cmds/statsd/src/anomaly/DurationAnomalyTracker.cpp
@@ -53,10 +53,11 @@
 
 void DurationAnomalyTracker::startAlarm(const MetricDimensionKey& dimensionKey,
                                         const uint64_t& timestampNs) {
-    uint32_t timestampSec = static_cast<uint32_t>(timestampNs / NS_PER_SEC);
+    // Alarms are stored in secs. Must round up, since if it fires early, it is ignored completely.
+    uint32_t timestampSec = static_cast<uint32_t>((timestampNs -1)/ NS_PER_SEC) + 1; // round up
     if (isInRefractoryPeriod(timestampNs, dimensionKey)) {
-        VLOG("Skipping setting anomaly alarm since it'd fall in the refractory period");
-        return;
+        VLOG("Setting a delayed anomaly alarm lest it fall in the refractory period");
+        timestampSec = getRefractoryPeriodEndsSec(dimensionKey) + 1;
     }
     sp<const AnomalyAlarm> alarm = new AnomalyAlarm{timestampSec};
     mAlarms.insert({dimensionKey, alarm});
diff --git a/cmds/statsd/src/condition/CombinationConditionTracker.cpp b/cmds/statsd/src/condition/CombinationConditionTracker.cpp
index 4c20ccb..13a2b7b 100644
--- a/cmds/statsd/src/condition/CombinationConditionTracker.cpp
+++ b/cmds/statsd/src/condition/CombinationConditionTracker.cpp
@@ -106,11 +106,9 @@
 }
 
 void CombinationConditionTracker::isConditionMet(
-        const ConditionKey& conditionParameters,
-        const vector<sp<ConditionTracker>>& allConditions,
-        const FieldMatcher& dimensionFields,
-        vector<ConditionState>& conditionCache,
-        std::unordered_set<HashableDimensionKey> &dimensionsKeySet) const {
+        const ConditionKey& conditionParameters, const vector<sp<ConditionTracker>>& allConditions,
+        const std::vector<Matcher>& dimensionFields, vector<ConditionState>& conditionCache,
+        std::unordered_set<HashableDimensionKey>& dimensionsKeySet) const {
     // So far, this is fine as there is at most one child having sliced output.
     for (const int childIndex : mChildren) {
         if (conditionCache[childIndex] == ConditionState::kNotEvaluated) {
@@ -169,8 +167,8 @@
 
 ConditionState CombinationConditionTracker::getMetConditionDimension(
         const std::vector<sp<ConditionTracker>>& allConditions,
-        const FieldMatcher& dimensionFields,
-        std::unordered_set<HashableDimensionKey> &dimensionsKeySet) const {
+        const std::vector<Matcher>& dimensionFields,
+        std::unordered_set<HashableDimensionKey>& dimensionsKeySet) const {
     vector<ConditionState> conditionCache(allConditions.size(), ConditionState::kNotEvaluated);
     // So far, this is fine as there is at most one child having sliced output.
     for (const int childIndex : mChildren) {
diff --git a/cmds/statsd/src/condition/CombinationConditionTracker.h b/cmds/statsd/src/condition/CombinationConditionTracker.h
index 0b7f949..ba185f6 100644
--- a/cmds/statsd/src/condition/CombinationConditionTracker.h
+++ b/cmds/statsd/src/condition/CombinationConditionTracker.h
@@ -41,17 +41,17 @@
                            std::vector<ConditionState>& conditionCache,
                            std::vector<bool>& changedCache) override;
 
-    void isConditionMet(
-        const ConditionKey& conditionParameters,
-        const std::vector<sp<ConditionTracker>>& allConditions,
-        const FieldMatcher& dimensionFields,
-        std::vector<ConditionState>& conditionCache,
-        std::unordered_set<HashableDimensionKey> &dimensionsKeySet) const override;
+    void isConditionMet(const ConditionKey& conditionParameters,
+                        const std::vector<sp<ConditionTracker>>& allConditions,
+                        const vector<Matcher>& dimensionFields,
+                        std::vector<ConditionState>& conditionCache,
+                        std::unordered_set<HashableDimensionKey>& dimensionsKeySet) const override;
 
     ConditionState getMetConditionDimension(
             const std::vector<sp<ConditionTracker>>& allConditions,
-            const FieldMatcher& dimensionFields,
-            std::unordered_set<HashableDimensionKey> &dimensionsKeySet) const override;
+            const vector<Matcher>& dimensionFields,
+            std::unordered_set<HashableDimensionKey>& dimensionsKeySet) const override;
+
 private:
     LogicalOperation mLogicalOperation;
 
diff --git a/cmds/statsd/src/condition/ConditionTracker.h b/cmds/statsd/src/condition/ConditionTracker.h
index 81abbdb..2612a9a 100644
--- a/cmds/statsd/src/condition/ConditionTracker.h
+++ b/cmds/statsd/src/condition/ConditionTracker.h
@@ -90,14 +90,13 @@
     virtual void isConditionMet(
             const ConditionKey& conditionParameters,
             const std::vector<sp<ConditionTracker>>& allConditions,
-            const FieldMatcher& dimensionFields,
-            std::vector<ConditionState>& conditionCache,
-            std::unordered_set<HashableDimensionKey> &dimensionsKeySet) const = 0;
+            const vector<Matcher>& dimensionFields, std::vector<ConditionState>& conditionCache,
+            std::unordered_set<HashableDimensionKey>& dimensionsKeySet) const = 0;
 
     virtual ConditionState getMetConditionDimension(
             const std::vector<sp<ConditionTracker>>& allConditions,
-            const FieldMatcher& dimensionFields,
-            std::unordered_set<HashableDimensionKey> &dimensionsKeySet) const = 0;
+            const vector<Matcher>& dimensionFields,
+            std::unordered_set<HashableDimensionKey>& dimensionsKeySet) const = 0;
 
     // return the list of LogMatchingTracker index that this ConditionTracker uses.
     virtual const std::set<int>& getLogTrackerIndex() const {
diff --git a/cmds/statsd/src/condition/ConditionWizard.cpp b/cmds/statsd/src/condition/ConditionWizard.cpp
index 0427700..c8722c3 100644
--- a/cmds/statsd/src/condition/ConditionWizard.cpp
+++ b/cmds/statsd/src/condition/ConditionWizard.cpp
@@ -24,11 +24,9 @@
 using std::string;
 using std::vector;
 
-ConditionState ConditionWizard::query(
-    const int index, const ConditionKey& parameters,
-    const FieldMatcher& dimensionFields,
-    std::unordered_set<HashableDimensionKey> *dimensionKeySet) {
-
+ConditionState ConditionWizard::query(const int index, const ConditionKey& parameters,
+                                      const vector<Matcher>& dimensionFields,
+                                      std::unordered_set<HashableDimensionKey>* dimensionKeySet) {
     vector<ConditionState> cache(mAllConditions.size(), ConditionState::kNotEvaluated);
 
     mAllConditions[index]->isConditionMet(
@@ -37,9 +35,8 @@
 }
 
 ConditionState ConditionWizard::getMetConditionDimension(
-    const int index, const FieldMatcher& dimensionFields,
-    std::unordered_set<HashableDimensionKey> *dimensionsKeySet) const {
-
+        const int index, const vector<Matcher>& dimensionFields,
+        std::unordered_set<HashableDimensionKey>* dimensionsKeySet) const {
     return mAllConditions[index]->getMetConditionDimension(mAllConditions, dimensionFields,
                                  *dimensionsKeySet);
 }
diff --git a/cmds/statsd/src/condition/ConditionWizard.h b/cmds/statsd/src/condition/ConditionWizard.h
index b38b59f..4831d56 100644
--- a/cmds/statsd/src/condition/ConditionWizard.h
+++ b/cmds/statsd/src/condition/ConditionWizard.h
@@ -39,16 +39,13 @@
     //                       condition.
     // The ConditionTracker at [conditionIndex] can be a CombinationConditionTracker. In this case,
     // the conditionParameters contains the parameters for it's children SimpleConditionTrackers.
-    virtual ConditionState query(
-            const int conditionIndex,
-            const ConditionKey& conditionParameters,
-            const FieldMatcher& dimensionFields,
-            std::unordered_set<HashableDimensionKey> *dimensionKeySet);
+    virtual ConditionState query(const int conditionIndex, const ConditionKey& conditionParameters,
+                                 const vector<Matcher>& dimensionFields,
+                                 std::unordered_set<HashableDimensionKey>* dimensionKeySet);
 
     virtual ConditionState getMetConditionDimension(
-            const int index,
-            const FieldMatcher& dimensionFields,
-            std::unordered_set<HashableDimensionKey> *dimensionsKeySet) const;
+            const int index, const vector<Matcher>& dimensionFields,
+            std::unordered_set<HashableDimensionKey>* dimensionsKeySet) const;
 
 private:
     std::vector<sp<ConditionTracker>> mAllConditions;
diff --git a/cmds/statsd/src/condition/SimpleConditionTracker.cpp b/cmds/statsd/src/condition/SimpleConditionTracker.cpp
index 25265d5..624119f3 100644
--- a/cmds/statsd/src/condition/SimpleConditionTracker.cpp
+++ b/cmds/statsd/src/condition/SimpleConditionTracker.cpp
@@ -19,7 +19,6 @@
 
 #include "SimpleConditionTracker.h"
 #include "guardrail/StatsdStats.h"
-#include "dimension.h"
 
 #include <log/logprint.h>
 
@@ -77,10 +76,12 @@
         mStopAllLogMatcherIndex = -1;
     }
 
-    mOutputDimensions = simplePredicate.dimensions();
-
-    if (mOutputDimensions.child_size() > 0) {
-        mSliced = true;
+    if (simplePredicate.has_dimensions()) {
+        translateFieldMatcher(simplePredicate.dimensions(), &mOutputDimensions);
+        if (mOutputDimensions.size() > 0) {
+            mSliced = true;
+            mDimensionTag = mOutputDimensions[0].mMatcher.getTag();
+        }
     }
 
     if (simplePredicate.initial_value() == SimplePredicate_InitialValue_FALSE) {
@@ -104,13 +105,10 @@
                                   vector<bool>& stack) {
     // SimpleConditionTracker does not have dependency on other conditions, thus we just return
     // if the initialization was successful.
-    if (mOutputDimensions.has_field() || mOutputDimensions.child_size() > 0) {
-        setSliced(true);
-    }
     return mInitialized;
 }
 
-void print(map<HashableDimensionKey, int>& conditions, const int64_t& id) {
+void print(const map<HashableDimensionKey, int>& conditions, const int64_t& id) {
     VLOG("%lld DUMP:", (long long)id);
     for (const auto& pair : conditions) {
         VLOG("\t%s : %d", pair.first.c_str(), pair.second);
@@ -151,24 +149,15 @@
 }
 
 void SimpleConditionTracker::handleConditionEvent(const HashableDimensionKey& outputKey,
-                                                  bool matchStart,
-                                                  std::vector<ConditionState>& conditionCache,
-                                                  std::vector<bool>& conditionChangedCache) {
-    if ((int)conditionChangedCache.size() <= mIndex) {
-        ALOGE("handleConditionEvent: param conditionChangedCache not initialized.");
-        return;
-    }
-    if ((int)conditionCache.size() <= mIndex) {
-        ALOGE("handleConditionEvent: param conditionCache not initialized.");
-        return;
-    }
+                                                  bool matchStart, ConditionState* conditionCache,
+                                                  bool* conditionChangedCache) {
     bool changed = false;
     auto outputIt = mSlicedConditionState.find(outputKey);
     ConditionState newCondition;
     if (hitGuardRail(outputKey)) {
-        conditionChangedCache[mIndex] = false;
+        (*conditionChangedCache) = false;
         // Tells the caller it's evaluated.
-        conditionCache[mIndex] = ConditionState::kUnknown;
+        (*conditionCache) = ConditionState::kUnknown;
         return;
     }
     if (outputIt == mSlicedConditionState.end()) {
@@ -230,9 +219,8 @@
         print(mSlicedConditionState, mConditionId);
     }
 
-    conditionChangedCache[mIndex] = changed;
-    conditionCache[mIndex] = newCondition;
-
+    (*conditionChangedCache) = changed;
+    (*conditionCache) = newCondition;
     VLOG("SimplePredicate %lld nonSlicedChange? %d", (long long)mConditionId,
          conditionChangedCache[mIndex] == true);
 }
@@ -292,42 +280,42 @@
         return;
     }
 
-    // outputKey is the output values. e.g, uid:1234
-    std::vector<DimensionsValue> outputValues;
-    getDimensionKeys(event, mOutputDimensions, &outputValues);
-    if (outputValues.size() == 0) {
-        // The original implementation would generate an empty string dimension hash when condition
-        // is not sliced.
-        handleConditionEvent(
-            DEFAULT_DIMENSION_KEY, matchedState == 1, conditionCache, conditionChangedCache);
-    } else if (outputValues.size() == 1) {
-        handleConditionEvent(HashableDimensionKey(outputValues[0]), matchedState == 1,
-            conditionCache, conditionChangedCache);
+    ConditionState overallState = mInitialValue;
+    bool overallChanged = false;
+
+    if (mOutputDimensions.size() == 0) {
+        handleConditionEvent(DEFAULT_DIMENSION_KEY, 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 DimensionsValue& outputValue : outputValues) {
-            vector<ConditionState> dimensionalConditionCache(conditionCache.size(),
-                                                             ConditionState::kNotEvaluated);
-            vector<bool> dimensionalConditionChangedCache(conditionChangedCache.size(), false);
-            handleConditionEvent(HashableDimensionKey(outputValue), matchedState == 1,
-                dimensionalConditionCache, dimensionalConditionChangedCache);
-            OrConditionState(dimensionalConditionCache, &conditionCache);
-            OrBooleanVector(dimensionalConditionChangedCache, &conditionChangedCache);
+        for (const HashableDimensionKey& outputValue : outputValues) {
+            // For sliced conditions, the value in the cache is not used. We don't need to update
+            // the overall condition state.
+            ConditionState tempState = ConditionState::kUnknown;
+            bool tempChanged = false;
+            handleConditionEvent(outputValue, matchedState == 1, &tempState, &tempChanged);
+            if (tempChanged) {
+                overallChanged = true;
+            }
         }
     }
+    conditionCache[mIndex] = overallState;
+    conditionChangedCache[mIndex] = overallChanged;
 }
 
 void SimpleConditionTracker::isConditionMet(
-        const ConditionKey& conditionParameters,
-        const vector<sp<ConditionTracker>>& allConditions,
-        const FieldMatcher& dimensionFields,
-        vector<ConditionState>& conditionCache,
-        std::unordered_set<HashableDimensionKey> &dimensionsKeySet) const {
+        const ConditionKey& conditionParameters, const vector<sp<ConditionTracker>>& allConditions,
+        const vector<Matcher>& dimensionFields, vector<ConditionState>& conditionCache,
+        std::unordered_set<HashableDimensionKey>& dimensionsKeySet) const {
+
     if (conditionCache[mIndex] != ConditionState::kNotEvaluated) {
         // it has been evaluated.
         VLOG("Yes, already evaluated, %lld %d",
@@ -338,8 +326,7 @@
 
     if (pair == conditionParameters.end()) {
         ConditionState conditionState = ConditionState::kNotEvaluated;
-        if (dimensionFields.has_field() && dimensionFields.child_size() > 0 &&
-            dimensionFields.field() == mOutputDimensions.field()) {
+        if (dimensionFields.size() > 0 && dimensionFields[0].mMatcher.getTag() == mDimensionTag) {
             conditionState = conditionState | getMetConditionDimension(
                 allConditions, dimensionFields, dimensionsKeySet);
         } else {
@@ -368,12 +355,10 @@
             ConditionState sliceState =
                 startedCountIt->second > 0 ? ConditionState::kTrue : ConditionState::kFalse;
             conditionState = conditionState | sliceState;
-            if (sliceState == ConditionState::kTrue && dimensionFields.has_field()) {
-                HashableDimensionKey dimensionKey;
-                if (getSubDimension(startedCountIt->first.getDimensionsValue(), dimensionFields,
-                                    dimensionKey.getMutableDimensionsValue())) {
-                    dimensionsKeySet.insert(dimensionKey);
-                }
+            if (sliceState == ConditionState::kTrue && dimensionFields.size() > 0) {
+                vector<HashableDimensionKey> dimensionKeys;
+                filterValues(dimensionFields, startedCountIt->first.getValues(), &dimensionKeys);
+                dimensionsKeySet.insert(dimensionKeys.begin(), dimensionKeys.end());
             }
         } else {
             // For unseen key, check whether the require dimensions are subset of sliced condition
@@ -382,31 +367,29 @@
             for (const auto& slice : mSlicedConditionState) {
                 ConditionState sliceState =
                     slice.second > 0 ? ConditionState::kTrue : ConditionState::kFalse;
-                if (IsSubDimension(slice.first.getDimensionsValue(), key.getDimensionsValue())) {
+                if (slice.first.contains(key)) {
                     conditionState = conditionState | sliceState;
-                    if (sliceState == ConditionState::kTrue && dimensionFields.has_field()) {
-                        HashableDimensionKey dimensionKey;
-                        if (getSubDimension(slice.first.getDimensionsValue(),
-                                            dimensionFields, dimensionKey.getMutableDimensionsValue())) {
-                            dimensionsKeySet.insert(dimensionKey);
-                        }
+                    if (sliceState == ConditionState::kTrue && dimensionFields.size() > 0) {
+                        vector<HashableDimensionKey> dimensionKeys;
+                        filterValues(dimensionFields, slice.first.getValues(), &dimensionKeys);
+
+                        dimensionsKeySet.insert(dimensionKeys.begin(), dimensionKeys.end());
+                    }
                     }
                 }
             }
         }
-    }
     conditionCache[mIndex] = conditionState;
     VLOG("Predicate %lld return %d", (long long)mConditionId, conditionCache[mIndex]);
 }
 
 ConditionState SimpleConditionTracker::getMetConditionDimension(
         const std::vector<sp<ConditionTracker>>& allConditions,
-        const FieldMatcher& dimensionFields,
-        std::unordered_set<HashableDimensionKey> &dimensionsKeySet) const {
+        const vector<Matcher>& dimensionFields,
+        std::unordered_set<HashableDimensionKey>& dimensionsKeySet) const {
     ConditionState conditionState = mInitialValue;
-    if (!dimensionFields.has_field() ||
-        !mOutputDimensions.has_field() ||
-        dimensionFields.field() != mOutputDimensions.field()) {
+    if (dimensionFields.size() == 0 || mOutputDimensions.size() == 0 ||
+        dimensionFields[0].mMatcher.getTag() != mOutputDimensions[0].mMatcher.getTag()) {
         const auto& itr = mSlicedConditionState.find(DEFAULT_DIMENSION_KEY);
         if (itr != mSlicedConditionState.end()) {
             ConditionState sliceState =
@@ -419,13 +402,13 @@
     for (const auto& slice : mSlicedConditionState) {
         ConditionState sliceState =
             slice.second > 0 ? ConditionState::kTrue : ConditionState::kFalse;
-        DimensionsValue dimensionsValue;
         conditionState = conditionState | sliceState;
-        HashableDimensionKey dimensionKey;
-        if (sliceState == ConditionState::kTrue &&
-            getSubDimension(slice.first.getDimensionsValue(), dimensionFields,
-                            dimensionKey.getMutableDimensionsValue())) {
-            dimensionsKeySet.insert(dimensionKey);
+
+        if (sliceState == ConditionState::kTrue && dimensionFields.size() > 0) {
+            vector<HashableDimensionKey> dimensionKeys;
+            filterValues(dimensionFields, slice.first.getValues(), &dimensionKeys);
+
+            dimensionsKeySet.insert(dimensionKeys.begin(), dimensionKeys.end());
         }
     }
     return conditionState;
diff --git a/cmds/statsd/src/condition/SimpleConditionTracker.h b/cmds/statsd/src/condition/SimpleConditionTracker.h
index ce9a02d..c565129 100644
--- a/cmds/statsd/src/condition/SimpleConditionTracker.h
+++ b/cmds/statsd/src/condition/SimpleConditionTracker.h
@@ -48,14 +48,14 @@
 
     void isConditionMet(const ConditionKey& conditionParameters,
                         const std::vector<sp<ConditionTracker>>& allConditions,
-                        const FieldMatcher& dimensionFields,
+                        const vector<Matcher>& dimensionFields,
                         std::vector<ConditionState>& conditionCache,
-                        std::unordered_set<HashableDimensionKey> &dimensionsKeySet) const override;
+                        std::unordered_set<HashableDimensionKey>& dimensionsKeySet) const override;
 
     ConditionState getMetConditionDimension(
             const std::vector<sp<ConditionTracker>>& allConditions,
-            const FieldMatcher& dimensionFields,
-            std::unordered_set<HashableDimensionKey> &dimensionsKeySet) const override;
+            const vector<Matcher>& dimensionFields,
+            std::unordered_set<HashableDimensionKey>& dimensionsKeySet) const override;
 
 private:
     const ConfigKey mConfigKey;
@@ -73,17 +73,17 @@
 
     ConditionState mInitialValue;
 
-    FieldMatcher mOutputDimensions;
+    std::vector<Matcher> mOutputDimensions;
+
+    int mDimensionTag;
 
     std::map<HashableDimensionKey, int> mSlicedConditionState;
 
     void handleStopAll(std::vector<ConditionState>& conditionCache,
                        std::vector<bool>& changedCache);
 
-    void handleConditionEvent(const HashableDimensionKey& outputKey,
-                              bool matchStart,
-                              std::vector<ConditionState>& conditionCache,
-                              std::vector<bool>& changedCache);
+    void handleConditionEvent(const HashableDimensionKey& outputKey, bool matchStart,
+                              ConditionState* conditionCache, bool* changedCache);
 
     bool hitGuardRail(const HashableDimensionKey& newKey);
 
diff --git a/cmds/statsd/src/condition/condition_util.cpp b/cmds/statsd/src/condition/condition_util.cpp
index 0ab33cf..691356b 100644
--- a/cmds/statsd/src/condition/condition_util.cpp
+++ b/cmds/statsd/src/condition/condition_util.cpp
@@ -27,7 +27,6 @@
 #include "ConditionTracker.h"
 #include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
 #include "stats_util.h"
-#include "dimension.h"
 
 namespace android {
 namespace os {
@@ -97,109 +96,6 @@
 ConditionState operator|(ConditionState l, ConditionState r) {
     return l >= r ? l : r;
 }
-
-void OrConditionState(const std::vector<ConditionState>& ref, vector<ConditionState> * ored) {
-    if (ref.size() != ored->size()) {
-        return;
-    }
-    for (size_t i = 0; i < ored->size(); ++i) {
-        ored->at(i) = ored->at(i) | ref.at(i);
-    }
-}
-
-void OrBooleanVector(const std::vector<bool>& ref, vector<bool> * ored) {
-    if (ref.size() != ored->size()) {
-        return;
-    }
-    for (size_t i = 0; i < ored->size(); ++i) {
-        ored->at(i) = ored->at(i) | ref.at(i);
-    }
-}
-
-void getFieldsFromFieldMatcher(const FieldMatcher& matcher, Field* rootField, Field* leafField,
-                               std::vector<Field> *allFields) {
-    if (matcher.has_position()) {
-        leafField->set_position_index(0);
-    }
-    if (matcher.child_size() == 0) {
-        allFields->push_back(*rootField);
-        return;
-    }
-    for (int i = 0; i < matcher.child_size(); ++i) {
-        Field* newLeafField = leafField->add_child();
-        newLeafField->set_field(matcher.child(i).field());
-        getFieldsFromFieldMatcher(matcher.child(i), rootField, newLeafField, allFields);
-    }
-}
-
-void getFieldsFromFieldMatcher(const FieldMatcher& matcher, std::vector<Field> *allFields) {
-    if (!matcher.has_field()) {
-        return;
-    }
-    Field rootField;
-    rootField.set_field(matcher.field());
-    getFieldsFromFieldMatcher(matcher, &rootField, &rootField, allFields);
-}
-
-void flattenValueLeaves(const DimensionsValue& value,
-                        std::vector<const DimensionsValue*> *allLaves) {
-    switch (value.value_case()) {
-        case DimensionsValue::ValueCase::kValueStr:
-        case DimensionsValue::ValueCase::kValueInt:
-        case DimensionsValue::ValueCase::kValueLong:
-        case DimensionsValue::ValueCase::kValueBool:
-        case DimensionsValue::ValueCase::kValueFloat:
-        case DimensionsValue::ValueCase::VALUE_NOT_SET:
-            allLaves->push_back(&value);
-            break;
-        case DimensionsValue::ValueCase::kValueTuple:
-            for (int i = 0; i < value.value_tuple().dimensions_value_size(); ++i) {
-                flattenValueLeaves(value.value_tuple().dimensions_value(i), allLaves);
-            }
-            break;
-    }
-}
-
-void getDimensionKeysForCondition(
-    const LogEvent& event, const MetricConditionLink& link,
-    std::vector<HashableDimensionKey> *hashableDimensionKeys) {
-    std::vector<Field> whatFields;
-    getFieldsFromFieldMatcher(link.fields_in_what(), &whatFields);
-    std::vector<Field> conditionFields;
-    getFieldsFromFieldMatcher(link.fields_in_condition(), &conditionFields);
-
-    // TODO(yanglu): here we could simplify the logic to get the leaf value node in what and
-    // directly construct the full condition value tree.
-    std::vector<DimensionsValue> whatValues;
-    getDimensionKeys(event, link.fields_in_what(), &whatValues);
-
-    for (size_t i = 0; i < whatValues.size(); ++i) {
-        std::vector<const DimensionsValue*> whatLeaves;
-        flattenValueLeaves(whatValues[i], &whatLeaves);
-        if (whatLeaves.size() != whatFields.size() ||
-            whatLeaves.size() != conditionFields.size()) {
-            ALOGE("Dimensions between what and condition not equal.");
-            return;
-        }
-        FieldValueMap conditionValueMap;
-        for (size_t j = 0; j < whatLeaves.size(); ++j) {
-            DimensionsValue* conditionValue = &conditionValueMap[conditionFields[j]];
-            *conditionValue = *whatLeaves[i];
-            if (!setFieldInLeafValueProto(conditionFields[j], conditionValue)) {
-                ALOGE("Not able to reset the field for condition leaf value.");
-                return;
-            }
-        }
-        std::vector<DimensionsValue> conditionValueTrees;
-        findDimensionsValues(conditionValueMap, link.fields_in_condition(), &conditionValueTrees);
-        if (conditionValueTrees.size() != 1) {
-            ALOGE("Not able to find unambiguous field value in condition atom.");
-            continue;
-        }
-        hashableDimensionKeys->push_back(HashableDimensionKey(conditionValueTrees[0]));
-    }
-}
-
 }  // namespace statsd
 }  // namespace os
 }  // namespace android
diff --git a/cmds/statsd/src/condition/condition_util.h b/cmds/statsd/src/condition/condition_util.h
index a7288be..fed90ec 100644
--- a/cmds/statsd/src/condition/condition_util.h
+++ b/cmds/statsd/src/condition/condition_util.h
@@ -33,16 +33,10 @@
 };
 
 ConditionState operator|(ConditionState l, ConditionState r);
-void OrConditionState(const std::vector<ConditionState>& ref, vector<ConditionState> * ored);
-void OrBooleanVector(const std::vector<bool>& ref, vector<bool> * ored);
 
 ConditionState evaluateCombinationCondition(const std::vector<int>& children,
                                             const LogicalOperation& operation,
                                             const std::vector<ConditionState>& conditionCache);
-
-void getDimensionKeysForCondition(
-        const LogEvent& event, const MetricConditionLink& link,
-        std::vector<HashableDimensionKey> *dimensionKeys);
 }  // namespace statsd
 }  // namespace os
 }  // namespace android
diff --git a/cmds/statsd/src/dimension.cpp b/cmds/statsd/src/dimension.cpp
deleted file mode 100644
index 8a2e871..0000000
--- a/cmds/statsd/src/dimension.cpp
+++ /dev/null
@@ -1,400 +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 "Log.h"
-
-#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
-#include "frameworks/base/cmds/statsd/src/statsd_internal.pb.h"
-#include "dimension.h"
-
-
-namespace android {
-namespace os {
-namespace statsd {
-
-const DimensionsValue* getSingleLeafValue(const DimensionsValue* value) {
-    if (value->value_case() == DimensionsValue::ValueCase::kValueTuple) {
-        return getSingleLeafValue(&value->value_tuple().dimensions_value(0));
-    } else {
-        return value;
-    }
-}
-
-DimensionsValue getSingleLeafValue(const DimensionsValue& value) {
-    const DimensionsValue* leafValue = getSingleLeafValue(&value);
-    return *leafValue;
-}
-
-void appendLeafNodeToTree(const Field& field,
-                            const DimensionsValue& value,
-                            DimensionsValue* parentValue) {
-    if (field.child_size() <= 0) {
-        *parentValue = value;
-        parentValue->set_field(field.field());
-        return;
-    }
-    parentValue->set_field(field.field());
-    int idx = -1;
-    for (int i = 0; i < parentValue->mutable_value_tuple()->dimensions_value_size(); ++i) {
-        if (parentValue->mutable_value_tuple()->dimensions_value(i).field() ==
-                field.child(0).field()) {
-            idx = i;
-        }
-    }
-    if (idx < 0) {
-        parentValue->mutable_value_tuple()->add_dimensions_value();
-        idx = parentValue->mutable_value_tuple()->dimensions_value_size() - 1;
-    }
-    appendLeafNodeToTree(
-        field.child(0), value,
-        parentValue->mutable_value_tuple()->mutable_dimensions_value(idx));
-}
-
-void appendLeafNodeToTrees(const Field& field,
-                           const DimensionsValue& node,
-                           std::vector<DimensionsValue>* rootTrees) {
-    if (rootTrees == nullptr) {
-        return;
-    }
-    if (rootTrees->empty()) {
-        DimensionsValue tree;
-        appendLeafNodeToTree(field, node, &tree);
-        rootTrees->push_back(tree);
-    } else {
-        for (size_t i = 0; i < rootTrees->size(); ++i) {
-            appendLeafNodeToTree(field, node, &rootTrees->at(i));
-        }
-    }
-}
-
-namespace {
-
-void findDimensionsValues(
-       const FieldValueMap& fieldValueMap,
-       const FieldMatcher& matcher,
-       Field* rootField,
-       Field* leafField,
-       std::vector<DimensionsValue>* rootDimensionsValues);
-
-void findNonRepeatedDimensionsValues(
-       const FieldValueMap& fieldValueMap,
-       const FieldMatcher& matcher,
-       Field* rootField,
-       Field* leafField,
-       std::vector<DimensionsValue>* rootValues) {
-    if (matcher.child_size() > 0) {
-        Field* newLeafField = leafField->add_child();
-        for (const auto& childMatcher : matcher.child()) {
-          newLeafField->set_field(childMatcher.field());
-          findDimensionsValues(fieldValueMap, childMatcher, rootField, newLeafField, rootValues);
-        }
-        leafField->clear_child();
-    } else {
-        auto ret = fieldValueMap.equal_range(*rootField);
-        int found = 0;
-        for (auto it = ret.first; it != ret.second; ++it) {
-            found++;
-        }
-        // Not found.
-        if (found <= 0) {
-            return;
-        }
-        if (found > 1) {
-            ALOGE("Found multiple values for optional field.");
-            return;
-        }
-        appendLeafNodeToTrees(*rootField, ret.first->second, rootValues);
-    }
-}
-
-void findRepeatedDimensionsValues(const FieldValueMap& fieldValueMap,
-                                  const FieldMatcher& matcher,
-                                  Field* rootField,
-                                  Field* leafField,
-                                  std::vector<DimensionsValue>* rootValues) {
-    if (matcher.position() == Position::FIRST) {
-        leafField->set_position_index(0);
-        findNonRepeatedDimensionsValues(fieldValueMap, matcher, rootField, leafField, rootValues);
-        leafField->clear_position_index();
-    } else {
-        auto itLower = fieldValueMap.lower_bound(*rootField);
-        if (itLower == fieldValueMap.end()) {
-            return;
-        }
-        const int leafFieldNum = leafField->field();
-        leafField->set_field(leafFieldNum + 1);
-        auto itUpper = fieldValueMap.lower_bound(*rootField);
-        // Resets the field number.
-        leafField->set_field(leafFieldNum);
-
-        switch (matcher.position()) {
-             case Position::LAST:
-                 {
-                     itUpper--;
-                     if (itUpper != fieldValueMap.end()) {
-                         int last_index = getPositionByReferenceField(*rootField, itUpper->first);
-                         if (last_index < 0) {
-                            return;
-                         }
-                         leafField->set_position_index(last_index);
-                         findNonRepeatedDimensionsValues(
-                            fieldValueMap, matcher, rootField, leafField, rootValues);
-                         leafField->clear_position_index();
-                     }
-                 }
-                 break;
-             case Position::ANY:
-                 {
-                    std::set<int> indexes;
-                    for (auto it = itLower; it != itUpper; ++it) {
-                        int index = getPositionByReferenceField(*rootField, it->first);
-                        if (index >= 0) {
-                            indexes.insert(index);
-                        }
-                    }
-                    if (!indexes.empty()) {
-                        std::vector<DimensionsValue> allValues;
-                        for (const int index : indexes) {
-                             leafField->set_position_index(index);
-                             std::vector<DimensionsValue> newValues = *rootValues;
-                             findNonRepeatedDimensionsValues(
-                                fieldValueMap, matcher, rootField, leafField, &newValues);
-                             allValues.insert(allValues.end(), newValues.begin(), newValues.end());
-                             leafField->clear_position_index();
-                        }
-                        rootValues->clear();
-                        rootValues->insert(rootValues->end(), allValues.begin(), allValues.end());
-                    }
-                 }
-                 break;
-             default:
-                break;
-         }
-    }
-}
-
-void findDimensionsValues(
-       const FieldValueMap& fieldValueMap,
-       const FieldMatcher& matcher,
-       Field* rootField,
-       Field* leafField,
-       std::vector<DimensionsValue>* rootDimensionsValues) {
-    if (!matcher.has_position()) {
-        findNonRepeatedDimensionsValues(fieldValueMap, matcher, rootField, leafField,
-                                        rootDimensionsValues);
-    } else {
-        findRepeatedDimensionsValues(fieldValueMap, matcher, rootField, leafField,
-                                     rootDimensionsValues);
-    }
-}
-
-} // namespace
-
-void findDimensionsValues(
-       const FieldValueMap& fieldValueMap,
-       const FieldMatcher& matcher,
-       std::vector<DimensionsValue>* rootDimensionsValues) {
-    Field rootField;
-    buildSimpleAtomField(matcher.field(), &rootField);
-    findDimensionsValues(fieldValueMap, matcher, &rootField, &rootField, rootDimensionsValues);
-}
-
-void buildSimpleAtomFieldMatcher(const int tagId, FieldMatcher* matcher) {
-    matcher->set_field(tagId);
-}
-
-void buildSimpleAtomFieldMatcher(const int tagId, const int fieldNum, FieldMatcher* matcher) {
-    matcher->set_field(tagId);
-    matcher->add_child()->set_field(fieldNum);
-}
-
-constexpr int ATTRIBUTION_FIELD_NUM_IN_ATOM_PROTO = 1;
-constexpr int UID_FIELD_NUM_IN_ATTRIBUTION_NODE_PROTO = 1;
-constexpr int TAG_FIELD_NUM_IN_ATTRIBUTION_NODE_PROTO = 2;
-
-void buildAttributionUidFieldMatcher(const int tagId, const Position position,
-                                     FieldMatcher* matcher) {
-    matcher->set_field(tagId);
-    auto child = matcher->add_child();
-    child->set_field(ATTRIBUTION_FIELD_NUM_IN_ATOM_PROTO);
-    child->set_position(position);
-    child->add_child()->set_field(UID_FIELD_NUM_IN_ATTRIBUTION_NODE_PROTO);
-}
-
-void buildAttributionTagFieldMatcher(const int tagId, const Position position,
-                                     FieldMatcher* matcher) {
-    matcher->set_field(tagId);
-    FieldMatcher* child = matcher->add_child();
-    child->set_field(ATTRIBUTION_FIELD_NUM_IN_ATOM_PROTO);
-    child->set_position(position);
-    child->add_child()->set_field(TAG_FIELD_NUM_IN_ATTRIBUTION_NODE_PROTO);
-}
-
-void buildAttributionFieldMatcher(const int tagId, const Position position, FieldMatcher* matcher) {
-    matcher->set_field(tagId);
-    FieldMatcher* child = matcher->add_child();
-    child->set_field(ATTRIBUTION_FIELD_NUM_IN_ATOM_PROTO);
-    child->set_position(position);
-    child->add_child()->set_field(UID_FIELD_NUM_IN_ATTRIBUTION_NODE_PROTO);
-    child->add_child()->set_field(TAG_FIELD_NUM_IN_ATTRIBUTION_NODE_PROTO);
-}
-
-void DimensionsValueToString(const DimensionsValue& value, std::string *flattened) {
-    if (!value.has_field()) {
-        return;
-    }
-    *flattened += std::to_string(value.field());
-    *flattened += ":";
-    switch (value.value_case()) {
-        case DimensionsValue::ValueCase::kValueStr:
-            *flattened += value.value_str();
-            break;
-        case DimensionsValue::ValueCase::kValueInt:
-            *flattened += std::to_string(value.value_int());
-            break;
-        case DimensionsValue::ValueCase::kValueLong:
-            *flattened += std::to_string(value.value_long());
-            break;
-        case DimensionsValue::ValueCase::kValueBool:
-            *flattened += std::to_string(value.value_bool());
-            break;
-        case DimensionsValue::ValueCase::kValueFloat:
-            *flattened += std::to_string(value.value_float());
-            break;
-        case DimensionsValue::ValueCase::kValueTuple:
-            {
-                *flattened += "{";
-                for (int i = 0; i < value.value_tuple().dimensions_value_size(); ++i) {
-                    DimensionsValueToString(value.value_tuple().dimensions_value(i), flattened);
-                    *flattened += "|";
-                }
-                *flattened += "}";
-            }
-            break;
-        case DimensionsValue::ValueCase::VALUE_NOT_SET:
-            break;
-    }
-}
-
-std::string DimensionsValueToString(const DimensionsValue& value) {
-    std::string flatten;
-    DimensionsValueToString(value, &flatten);
-    return flatten;
-}
-
-bool IsSubDimension(const DimensionsValue& dimension, const DimensionsValue& sub) {
-    if (dimension.field() != sub.field()) {
-        return false;
-    }
-    if (dimension.value_case() != sub.value_case()) {
-        return false;
-    }
-    switch (dimension.value_case()) {
-        case DimensionsValue::ValueCase::kValueStr:
-            return dimension.value_str() == sub.value_str();
-        case DimensionsValue::ValueCase::kValueInt:
-            return dimension.value_int() == sub.value_int();
-        case DimensionsValue::ValueCase::kValueLong:
-            return dimension.value_long() == sub.value_long();
-        case DimensionsValue::ValueCase::kValueBool:
-            return dimension.value_bool() == sub.value_bool();
-        case DimensionsValue::ValueCase::kValueFloat:
-            return dimension.value_float() == sub.value_float();
-        case DimensionsValue::ValueCase::kValueTuple: {
-            if (dimension.value_tuple().dimensions_value_size() <
-                sub.value_tuple().dimensions_value_size()) {
-                return false;
-            }
-            bool allSub = true;
-            for (int i = 0; allSub && i < sub.value_tuple().dimensions_value_size(); ++i) {
-                bool isSub = false;
-                for (int j = 0; !isSub &&
-                        j < dimension.value_tuple().dimensions_value_size(); ++j) {
-                    isSub |= IsSubDimension(dimension.value_tuple().dimensions_value(j),
-                                            sub.value_tuple().dimensions_value(i));
-                }
-                allSub &= isSub;
-            }
-            return allSub;
-        }
-        break;
-        case DimensionsValue::ValueCase::VALUE_NOT_SET:
-            return false;
-        default:
-            return false;
-    }
-}
-
-long getLongFromDimenValue(const DimensionsValue& dimensionValue) {
-    switch (dimensionValue.value_case()) {
-        case DimensionsValue::ValueCase::kValueInt:
-            return dimensionValue.value_int();
-        case DimensionsValue::ValueCase::kValueLong:
-            return dimensionValue.value_long();
-        case DimensionsValue::ValueCase::kValueBool:
-            return dimensionValue.value_bool() ? 1 : 0;
-        case DimensionsValue::ValueCase::kValueFloat:
-            return (int64_t)dimensionValue.value_float();
-        case DimensionsValue::ValueCase::kValueTuple:
-        case DimensionsValue::ValueCase::kValueStr:
-        case DimensionsValue::ValueCase::VALUE_NOT_SET:
-            return 0;
-    }
-}
-
-bool getSubDimension(const DimensionsValue& dimension, const FieldMatcher& matcher,
-                     DimensionsValue* subDimension) {
-    if (!matcher.has_field()) {
-        return false;
-    }
-    if (matcher.field() != dimension.field()) {
-        return false;
-    }
-    if (matcher.child_size() <= 0) {
-        if (dimension.value_case() == DimensionsValue::ValueCase::kValueTuple ||
-            dimension.value_case() == DimensionsValue::ValueCase::VALUE_NOT_SET) {
-            return false;
-        }
-        *subDimension = dimension;
-        return true;
-    } else {
-        if (dimension.value_case() != DimensionsValue::ValueCase::kValueTuple) {
-            return false;
-        }
-        bool found_value = true;
-        auto value_tuple = dimension.value_tuple();
-        subDimension->set_field(dimension.field());
-        for (int i = 0; found_value && i < matcher.child_size(); ++i) {
-            int j = 0;
-            for (; j < value_tuple.dimensions_value_size(); ++j) {
-                if (value_tuple.dimensions_value(j).field() == matcher.child(i).field()) {
-                    break;
-                }
-            }
-            if (j < value_tuple.dimensions_value_size()) {
-                found_value &= getSubDimension(value_tuple.dimensions_value(j), matcher.child(i),
-                    subDimension->mutable_value_tuple()->add_dimensions_value());
-            } else {
-                found_value = false;
-            }
-        }
-        return found_value;
-    }
-}
-
-}  // namespace statsd
-}  // namespace os
-}  // namespace android
diff --git a/cmds/statsd/src/dimension.h b/cmds/statsd/src/dimension.h
deleted file mode 100644
index 138c6e9..0000000
--- a/cmds/statsd/src/dimension.h
+++ /dev/null
@@ -1,71 +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.
- */
-
-#pragma once
-
-#include <log/logprint.h>
-#include <set>
-#include <vector>
-#include "frameworks/base/cmds/statsd/src/stats_log.pb.h"
-#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
-#include "field_util.h"
-
-namespace android {
-namespace os {
-namespace statsd {
-
-// Returns the leaf node from the DimensionsValue proto. It assume that the input has only one
-// leaf node at most.
-const DimensionsValue* getSingleLeafValue(const DimensionsValue* value);
-DimensionsValue getSingleLeafValue(const DimensionsValue& value);
-
-// Appends the leaf node to the parent tree.
-void appendLeafNodeToTree(const Field& field, const DimensionsValue& value, DimensionsValue* tree);
-
-// Constructs the DimensionsValue protos from the FieldMatcher. Each DimensionsValue proto
-// represents a tree. When the input proto has repeated fields and the input "dimensions" wants
-// "ANY" locations, it will return multiple trees.
-void findDimensionsValues(
-       const FieldValueMap& fieldValueMap,
-       const FieldMatcher& matcher,
-       std::vector<DimensionsValue>* rootDimensionsValues);
-
-// Utils to build FieldMatcher proto for simple one-depth atoms.
-void buildSimpleAtomFieldMatcher(const int tagId, const int atomFieldNum, FieldMatcher* matcher);
-void buildSimpleAtomFieldMatcher(const int tagId, FieldMatcher* matcher);
-
-// Utils to build FieldMatcher proto for attribution nodes.
-void buildAttributionUidFieldMatcher(const int tagId, const Position position,
-                                     FieldMatcher* matcher);
-void buildAttributionTagFieldMatcher(const int tagId, const Position position,
-                                     FieldMatcher* matcher);
-void buildAttributionFieldMatcher(const int tagId, const Position position,
-                                  FieldMatcher* matcher);
-
-// Utils to print pretty string for DimensionsValue proto.
-std::string DimensionsValueToString(const DimensionsValue& value);
-void DimensionsValueToString(const DimensionsValue& value, std::string *flattened);
-
-bool IsSubDimension(const DimensionsValue& dimension, const DimensionsValue& sub);
-
-// Helper function to get long value from the DimensionsValue proto.
-long getLongFromDimenValue(const DimensionsValue& dimensionValue);
-
-bool getSubDimension(const DimensionsValue& dimension, const FieldMatcher& matcher,
-                    DimensionsValue* subDimension);
-}  // namespace statsd
-}  // namespace os
-}  // namespace android
diff --git a/cmds/statsd/src/external/puller_util.cpp b/cmds/statsd/src/external/puller_util.cpp
index 7cfc1d48..0b0c5c4 100644
--- a/cmds/statsd/src/external/puller_util.cpp
+++ b/cmds/statsd/src/external/puller_util.cpp
@@ -18,7 +18,6 @@
 #include "Log.h"
 
 #include "StatsPullerManagerImpl.h"
-#include "field_util.h"
 #include "puller_util.h"
 #include "statslog.h"
 
@@ -30,125 +29,136 @@
 using std::shared_ptr;
 using std::vector;
 
-DimensionsValue* getFieldValue(shared_ptr<LogEvent> event, int tagId, int fieldNum) {
-  Field field;
-  buildSimpleAtomField(tagId, fieldNum, &field);
-  return event->findFieldValueOrNull(field);
-}
-
+namespace {
 bool shouldMerge(shared_ptr<LogEvent>& lhs, shared_ptr<LogEvent>& rhs,
-                 const vector<int>& nonAdditiveFields, int tagId) {
-  for (int f : nonAdditiveFields) {
-    DimensionsValue* lValue = getFieldValue(lhs, tagId, f);
-    DimensionsValue* rValue = getFieldValue(rhs, tagId, f);
-    if (!compareDimensionsValue(*lValue, *rValue)) {
-      return false;
+                 const vector<int>& nonAdditiveFields) {
+    const auto& l_values = lhs->getValues();
+    const auto& r_values = rhs->getValues();
+
+    for (size_t i : nonAdditiveFields) {
+        // We store everything starting from index 0, so we need to use i-1
+        if (!(l_values.size() > i - 1 && r_values.size() > i - 1 &&
+              l_values[i - 1].mValue == r_values[i - 1].mValue)) {
+            return false;
+        }
     }
-  }
-  return true;
+    return true;
 }
 
 // merge rhs to lhs
-void mergeEvent(shared_ptr<LogEvent>& lhs, shared_ptr<LogEvent>& rhs,
-                const vector<int>& additiveFields, int tagId) {
-  for (int f : additiveFields) {
-    DimensionsValue* lValue = getFieldValue(lhs, tagId, f);
-    DimensionsValue* rValue = getFieldValue(rhs, tagId, f);
-    if (lValue->has_value_int()) {
-      lValue->set_value_int(lValue->value_int() + rValue->value_int());
-    } else if (lValue->has_value_long()) {
-      lValue->set_value_long(lValue->value_long() + rValue->value_long());
+// when calling this function, all sanity check should be done already.
+// e.g., index boundary, nonAdditiveFields matching etc.
+bool mergeEvent(shared_ptr<LogEvent>& lhs, shared_ptr<LogEvent>& rhs,
+                const vector<int>& additiveFields) {
+    vector<FieldValue>* host_values = lhs->getMutableValues();
+    const auto& child_values = rhs->getValues();
+    for (int i : additiveFields) {
+        Value& host = (*host_values)[i - 1].mValue;
+        const Value& child = (child_values[i - 1]).mValue;
+        if (child.getType() != host.getType()) {
+            return false;
+        }
+        switch (child.getType()) {
+            case INT:
+                host.setInt(host.int_value + child.int_value);
+                break;
+            case LONG:
+                host.setLong(host.long_value + child.long_value);
+                break;
+            default:
+                ALOGE("Tried to merge 2 fields with unsupported type");
+                return false;
+        }
     }
-  }
+    return true;
 }
 
-// process all data and merge isolated with host if necessary
-void mergeIsolatedUidsToHostUid(vector<shared_ptr<LogEvent>>& data,
-                                const sp<UidMap>& uidMap, int tagId) {
-  if (StatsPullerManagerImpl::kAllPullAtomInfo.find(tagId) ==
-      StatsPullerManagerImpl::kAllPullAtomInfo.end()) {
-    VLOG("Unknown pull atom id %d", tagId);
-    return;
-  }
-  if (android::util::kAtomsWithUidField.find(tagId) ==
-      android::util::kAtomsWithUidField.end()) {
-    VLOG("No uid to merge for atom %d", tagId);
-    return;
-  }
-  const vector<int>& additiveFields =
-      StatsPullerManagerImpl::kAllPullAtomInfo.find(tagId)
-          ->second.additiveFields;
-  const vector<int>& nonAdditiveFields =
-      StatsPullerManagerImpl::kAllPullAtomInfo.find(tagId)
-          ->second.nonAdditiveFields;
-
-  // map of host uid to isolated uid data index in the original vector.
-  // because of non additive fields, there could be multiple of them that can't
-  // be merged into one
-  map<int, vector<int>> hostToIsolated;
-  // map of host uid to their position in the original vector
-  map<int, vector<int>> hostPosition;
-  vector<int> isolatedUidPos;
-  // all uids in the original vector
-  vector<int> allUids;
-  for (size_t i = 0; i < data.size(); i++) {
-    // uid field is always first primitive filed, if present
-    DimensionsValue* uidField = getFieldValue(data[i], tagId, 1);
-    if (!uidField) {
-      VLOG("Bad data for %d, %s", tagId, data[i]->ToString().c_str());
-      return;
-    }
-    int uid = uidField->value_int();
-    allUids.push_back(uid);
-    const int hostUid = uidMap->getHostUidOrSelf(uid);
-    if (hostUid != uid) {
-      uidField->set_value_int(hostUid);
-      hostToIsolated[hostUid].push_back(i);
-      isolatedUidPos.push_back(i);
-    }
-  }
-  vector<shared_ptr<LogEvent>> mergedData;
-  for (size_t i = 0; i < allUids.size(); i++) {
-    if (hostToIsolated.find(allUids[i]) != hostToIsolated.end()) {
-      hostPosition[allUids[i]].push_back(i);
-    } else if (std::find(isolatedUidPos.begin(), isolatedUidPos.end(), i) != isolatedUidPos.end()) {
-      continue;
-    } else {
-      mergedData.push_back(data[i]);
-    }
-  }
-  for (auto iter = hostToIsolated.begin(); iter != hostToIsolated.end();
-       iter++) {
-    int uid = iter->first;
-    vector<int>& isolated = hostToIsolated[uid];
-    vector<int> toBeMerged;
-    toBeMerged.insert(toBeMerged.begin(), isolated.begin(), isolated.end());
-    if (hostPosition.find(uid) != hostPosition.end()) {
-      vector<int>& host = hostPosition[uid];
-      toBeMerged.insert(toBeMerged.end(), host.begin(), host.end());
-    }
-    vector<bool> used(toBeMerged.size());
-    for (size_t i = 0; i < toBeMerged.size(); i++) {
-      if (used[i] == true) {
-        continue;
-      }
-      for (size_t j = i + 1; j < toBeMerged.size(); j++) {
-        shared_ptr<LogEvent>& lhs = data[toBeMerged[i]];
-        shared_ptr<LogEvent>& rhs = data[toBeMerged[j]];
-        if (shouldMerge(lhs, rhs, nonAdditiveFields, tagId)) {
-          mergeEvent(lhs, rhs, additiveFields, tagId);
-          used[j] = true;
+bool tryMerge(vector<shared_ptr<LogEvent>>& data, int child_pos, const vector<int>& host_pos,
+              const vector<int>& nonAdditiveFields, const vector<int>& additiveFields) {
+    for (const auto& pos : host_pos) {
+        if (shouldMerge(data[pos], data[child_pos], nonAdditiveFields) &&
+            mergeEvent(data[pos], data[child_pos], additiveFields)) {
+            return true;
         }
-      }
     }
-    for (size_t i = 0; i < toBeMerged.size(); i++) {
-      if (used[i] == false) {
-      mergedData.push_back(data[i]);
+    return false;
+}
+
+}  // namespace
+
+/**
+ * Process all data and merge isolated with host if necessary.
+ * For example:
+ *   NetworkBytesAtom {
+ *       int uid = 1;
+ *       State process_state = 2;
+ *       int byte_send = 3;
+ *       int byte_recv = 4;
+ *   }
+ *   additive fields are {3, 4}, non-additive field is {2}
+ * If we pulled the following events (uid1_child is an isolated uid which maps to uid1):
+ * [uid1, fg, 100, 200]
+ * [uid1_child, fg, 100, 200]
+ * [uid1, bg, 100, 200]
+ *
+ * We want to merge them and results should be:
+ * [uid1, fg, 200, 400]
+ * [uid1, bg, 100, 200]
+ */
+void mergeIsolatedUidsToHostUid(vector<shared_ptr<LogEvent>>& data, const sp<UidMap>& uidMap,
+                                int tagId) {
+    if (StatsPullerManagerImpl::kAllPullAtomInfo.find(tagId) ==
+        StatsPullerManagerImpl::kAllPullAtomInfo.end()) {
+        VLOG("Unknown pull atom id %d", tagId);
+        return;
     }
+    if (android::util::kAtomsWithUidField.find(tagId) == android::util::kAtomsWithUidField.end()) {
+        VLOG("No uid to merge for atom %d", tagId);
+        return;
     }
-  }
-  data.clear();
-  data = mergedData;
+    const vector<int>& additiveFields =
+            StatsPullerManagerImpl::kAllPullAtomInfo.find(tagId)->second.additiveFields;
+    const vector<int>& nonAdditiveFields =
+            StatsPullerManagerImpl::kAllPullAtomInfo.find(tagId)->second.nonAdditiveFields;
+
+    // map of host uid to their position in the original vector
+    map<int, vector<int>> hostPosition;
+    vector<bool> toRemove = vector<bool>(data.size(), false);
+
+    for (size_t i = 0; i < data.size(); i++) {
+        vector<FieldValue>* valueList = data[i]->getMutableValues();
+
+        int err = 0;
+        int uid = data[i]->GetInt(1, &err);
+        if (err != 0) {
+            VLOG("Bad uid field for %s", data[i]->ToString().c_str());
+            return;
+        }
+
+        const int hostUid = uidMap->getHostUidOrSelf(uid);
+
+        if (hostUid != uid) {
+            (*valueList)[0].mValue.setInt(hostUid);
+        }
+        if (hostPosition.find(hostUid) == hostPosition.end()) {
+            hostPosition[hostUid].push_back(i);
+        } else {
+            if (tryMerge(data, i, hostPosition[hostUid], nonAdditiveFields, additiveFields)) {
+                toRemove[i] = true;
+            } else {
+                hostPosition[hostUid].push_back(i);
+            }
+        }
+    }
+
+    vector<shared_ptr<LogEvent>> mergedData;
+    for (size_t i = 0; i < toRemove.size(); i++) {
+        if (!toRemove[i]) {
+            mergedData.push_back(data[i]);
+        }
+    }
+    data.clear();
+    data = mergedData;
 }
 
 }  // namespace statsd
diff --git a/cmds/statsd/src/external/puller_util.h b/cmds/statsd/src/external/puller_util.h
index 70d5321..fd4a4a2 100644
--- a/cmds/statsd/src/external/puller_util.h
+++ b/cmds/statsd/src/external/puller_util.h
@@ -17,7 +17,6 @@
 #pragma once
 
 #include <vector>
-#include "HashableDimensionKey.h"
 #include "StatsPuller.h"
 #include "logd/LogEvent.h"
 #include "packages/UidMap.h"
diff --git a/cmds/statsd/src/field_util.cpp b/cmds/statsd/src/field_util.cpp
deleted file mode 100644
index acf64fe..0000000
--- a/cmds/statsd/src/field_util.cpp
+++ /dev/null
@@ -1,318 +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 "Log.h"
-#include "field_util.h"
-
-#include <set>
-#include <vector>
-
-namespace android {
-namespace os {
-namespace statsd {
-
-// This function is to compare two Field trees where each node has at most one child.
-bool CompareField(const Field& a, const Field& b) {
-    if (a.field() < b.field()) {
-        return true;
-    }
-    if (a.field() > b.field()) {
-        return false;
-    }
-    if (a.position_index() < b.position_index()) {
-        return true;
-    }
-    if (a.position_index() > b.position_index()) {
-        return false;
-    }
-    if (a.child_size() < b.child_size()) {
-        return true;
-    }
-    if (a.child_size() > b.child_size()) {
-        return false;
-    }
-    if (a.child_size() == 0 && b.child_size() == 0) {
-       return false;
-    }
-    return CompareField(a.child(0), b.child(0));
-}
-
-const Field* getSingleLeaf(const Field* field) {
-    if (field->child_size() <= 0) {
-        return field;
-    } else {
-        return getSingleLeaf(&field->child(0));
-    }
-}
-
-Field* getSingleLeaf(Field* field) {
-    if (field->child_size() <= 0) {
-        return field;
-    } else {
-        return getSingleLeaf(field->mutable_child(0));
-    }
-}
-
-void FieldToString(const Field& field, std::string *flattened) {
-    *flattened += std::to_string(field.field());
-    if (field.has_position_index()) {
-        *flattened += "[";
-        *flattened += std::to_string(field.position_index());
-        *flattened += "]";
-    }
-    if (field.child_size() <= 0) {
-        return;
-    }
-    *flattened += ".";
-    *flattened += "{";
-    for (int i = 0 ; i < field.child_size(); ++i) {
-        *flattened += FieldToString(field.child(i));
-    }
-    *flattened += "},";
-}
-
-std::string FieldToString(const Field& field) {
-    std::string flatten;
-    FieldToString(field, &flatten);
-    return flatten;
-}
-
-bool setFieldInLeafValueProto(const Field &field, DimensionsValue* leafValue) {
-    if (field.child_size() <= 0) {
-        leafValue->set_field(field.field());
-        return true;
-    } else if (field.child_size() == 1)  {
-        return setFieldInLeafValueProto(field.child(0), leafValue);
-    } else {
-        ALOGE("Not able to set the 'field' in leaf value for multiple children.");
-        return false;
-    }
-}
-
-void buildSimpleAtomField(const int tagId, const int atomFieldNum, Field *field) {
-    field->set_field(tagId);
-    field->add_child()->set_field(atomFieldNum);
-}
-
-void buildSimpleAtomField(const int tagId, Field *field) {
-    field->set_field(tagId);
-}
-
-void appendLeaf(Field *parent, int node_field_num) {
-    if (!parent->has_field()) {
-        parent->set_field(node_field_num);
-    } else if (parent->child_size() <= 0) {
-        parent->add_child()->set_field(node_field_num);
-    } else {
-        appendLeaf(parent->mutable_child(0), node_field_num);
-    }
-}
-
-void appendLeaf(Field *parent, int node_field_num, int position) {
-    if (!parent->has_field()) {
-        parent->set_field(node_field_num);
-        parent->set_position_index(position);
-    } else if (parent->child_size() <= 0) {
-        auto child = parent->add_child();
-        child->set_field(node_field_num);
-        child->set_position_index(position);
-    } else {
-        appendLeaf(parent->mutable_child(0), node_field_num, position);
-    }
-}
-
-void increasePosition(Field *field) {
-    if (!field->has_position_index()) {
-        field->set_position_index(0);
-    } else {
-        field->set_position_index(field->position_index() + 1);
-    }
-}
-
-int getPositionByReferenceField(const Field& ref, const Field& field_with_index) {
-    if (ref.child_size() <= 0) {
-        return field_with_index.position_index();
-    }
-    if (ref.child_size() != 1 ||
-        field_with_index.child_size() != 1) {
-        return -1;
-    }
-    return getPositionByReferenceField(ref.child(0), field_with_index.child(0));
-}
-
-namespace {
-
-void findFields(
-       const FieldValueMap& fieldValueMap,
-       const FieldMatcher& matcher,
-       Field* rootField,
-       Field* leafField,
-       std::set<Field, FieldCmp>* rootFields);
-
-void findNonRepeatedFields(
-       const FieldValueMap& fieldValueMap,
-       const FieldMatcher& matcher,
-       Field* rootField,
-       Field* leafField,
-       std::set<Field, FieldCmp>* rootFields) {
-    if (matcher.child_size() > 0) {
-        Field* newLeafField = leafField->add_child();
-        for (const auto& childMatcher : matcher.child()) {
-            newLeafField->set_field(childMatcher.field());
-            findFields(fieldValueMap, childMatcher, rootField, newLeafField, rootFields);
-        }
-        leafField->clear_child();
-    } else {
-        auto ret = fieldValueMap.equal_range(*rootField);
-        int found = 0;
-        for (auto it = ret.first; it != ret.second; ++it) {
-            found++;
-        }
-        // Not found.
-        if (found <= 0) {
-            return;
-        }
-        if (found > 1) {
-            ALOGE("Found multiple values for optional field.");
-            return;
-        }
-        rootFields->insert(ret.first->first);
-    }
-}
-
-void findRepeatedFields(const FieldValueMap& fieldValueMap, const FieldMatcher& matcher,
-                        Field* rootField, Field* leafField,
-                        std::set<Field, FieldCmp>* rootFields) {
-    if (matcher.position() == Position::FIRST) {
-        leafField->set_position_index(0);
-        findNonRepeatedFields(fieldValueMap, matcher, rootField, leafField, rootFields);
-        leafField->clear_position_index();
-    } else {
-        auto itLower = fieldValueMap.lower_bound(*rootField);
-        if (itLower == fieldValueMap.end()) {
-            return;
-        }
-
-        const int leafFieldNum = leafField->field();
-        leafField->set_field(leafFieldNum + 1);
-        auto itUpper = fieldValueMap.lower_bound(*rootField);
-        // Resets the field number.
-        leafField->set_field(leafFieldNum);
-
-        switch (matcher.position()) {
-             case Position::LAST:
-                 {
-                     itUpper--;
-                     if (itUpper != fieldValueMap.end()) {
-                         int last_index = getPositionByReferenceField(*rootField, itUpper->first);
-                         if (last_index < 0) {
-                            return;
-                         }
-                         leafField->set_position_index(last_index);
-                         findNonRepeatedFields(
-                            fieldValueMap, matcher, rootField, leafField, rootFields);
-                         leafField->clear_position_index();
-                     }
-                 }
-                 break;
-             case Position::ANY:
-                 {
-                    std::set<int> indexes;
-                    for (auto it = itLower; it != itUpper; ++it) {
-                        int index = getPositionByReferenceField(*rootField, it->first);
-                        if (index >= 0) {
-                            indexes.insert(index);
-                        }
-                    }
-                    if (!indexes.empty()) {
-                        for (const int index : indexes) {
-                             leafField->set_position_index(index);
-                             findNonRepeatedFields(
-                                fieldValueMap, matcher, rootField, leafField, rootFields);
-                             leafField->clear_position_index();
-                        }
-                    }
-                 }
-                 break;
-             default:
-                break;
-         }
-    }
-}
-
-void findFields(
-       const FieldValueMap& fieldValueMap,
-       const FieldMatcher& matcher,
-       Field* rootField,
-       Field* leafField,
-       std::set<Field, FieldCmp>* rootFields) {
-    if (!matcher.has_position()) {
-        findNonRepeatedFields(fieldValueMap, matcher, rootField, leafField, rootFields);
-    } else {
-        findRepeatedFields(fieldValueMap, matcher, rootField, leafField, rootFields);
-    }
-}
-
-}  // namespace
-
-void findFields(
-       const FieldValueMap& fieldValueMap,
-       const FieldMatcher& matcher,
-       std::set<Field, FieldCmp>* rootFields) {
-    if (!matcher.has_field() || fieldValueMap.empty()) {
-        return;
-    }
-    Field rootField;
-    buildSimpleAtomField(matcher.field(), &rootField);
-    return findFields(fieldValueMap, matcher, &rootField, &rootField, rootFields);
-}
-
-void filterFields(const FieldMatcher& matcher, FieldValueMap* fieldValueMap) {
-    if (!matcher.has_field()) {
-        return;
-    }
-    std::set<Field, FieldCmp> rootFields;
-    findFields(*fieldValueMap, matcher, &rootFields);
-    auto it = fieldValueMap->begin();
-    while (it != fieldValueMap->end()) {
-        if (rootFields.find(it->first) == rootFields.end()) {
-            it = fieldValueMap->erase(it);
-        } else {
-            it++;
-        }
-    }
-}
-
-bool hasLeafNode(const FieldMatcher& matcher) {
-    if (!matcher.has_field()) {
-        return false;
-    }
-    for (int i = 0; i < matcher.child_size(); ++i) {
-        if (hasLeafNode(matcher.child(i))) {
-            return true;
-        }
-    }
-    return true;
-}
-
-bool IsAttributionUidField(const Field& field) {
-    return field.child_size() == 1 && field.child(0).field() == 1
-        && field.child(0).child_size() == 1 && field.child(0).child(0).field() == 1;
-}
-
-}  // namespace statsd
-}  // namespace os
-}  // namespace android
diff --git a/cmds/statsd/src/field_util.h b/cmds/statsd/src/field_util.h
deleted file mode 100644
index b04465d..0000000
--- a/cmds/statsd/src/field_util.h
+++ /dev/null
@@ -1,86 +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.
- */
-
-#pragma once
-
-#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
-#include "frameworks/base/cmds/statsd/src/statsd_internal.pb.h"
-#include "frameworks/base/cmds/statsd/src/stats_log.pb.h"
-
-#include <map>
-#include <set>
-
-namespace android {
-namespace os {
-namespace statsd {
-
-// Function to sort the Field protos.
-bool CompareField(const Field& a, const Field& b);
-struct FieldCmp {
-    bool operator()(const Field& a, const Field& b) const {
-        return CompareField(a, b);
-    }
-};
-
-// Flattened dimensions value map. To save space, usually the key contains the tree structure info
-// and value field is only leaf node.
-typedef std::map<Field, DimensionsValue, FieldCmp> FieldValueMap;
-
-// Util function to print the Field proto.
-std::string FieldToString(const Field& field);
-
-// Util function to find the leaf node from the input Field proto and set it in the corresponding
-// value proto.
-bool setFieldInLeafValueProto(const Field &field, DimensionsValue* leafValue);
-
-// Returns the leaf node from the Field proto. It assume that the input has only one
-// leaf node at most.
-const Field* getSingleLeaf(const Field* field);
-Field* getSingleLeaf(Field* field);
-
-// Append a node to the current leaf. It assumes that the input "parent" has one leaf node at most.
-void appendLeaf(Field *parent, int node_field_num);
-void appendLeaf(Field *parent, int node_field_num, int position);
-
-// Increase the position index for the node. If the "position_index" is not set, set it as 0.
-void increasePosition(Field *field);
-
-// Returns true if the matcher has specified at least one leaf node.
-bool hasLeafNode(const FieldMatcher& matcher);
-
-// The two input Field proto are describing the same tree structure. Both contain one leaf node at
-// most. This is find the position index info for the leaf node at "reference" stored in the
-// "field_with_index" tree.
-int getPositionByReferenceField(const Field& reference, const Field& field_with_index);
-
-// Utils to build the Field proto for simple atom fields.
-void buildSimpleAtomField(const int tagId, const int atomFieldNum, Field* field);
-void buildSimpleAtomField(const int tagId, Field* field);
-
-// Find out all the fields specified by the matcher.
-void findFields(
-       const FieldValueMap& fieldValueMap, const FieldMatcher& matcher,
-       std::set<Field, FieldCmp>* rootFields);
-
-// Filter out the fields not in the field matcher.
-void filterFields(const FieldMatcher& matcher, FieldValueMap* fieldValueMap);
-
-// Returns if the field is attribution node uid field.
-bool IsAttributionUidField(const Field& field);
-
-}  // namespace statsd
-}  // namespace os
-}  // namespace android
diff --git a/cmds/statsd/src/logd/LogEvent.cpp b/cmds/statsd/src/logd/LogEvent.cpp
index e1ab5d5..ce3a4b9 100644
--- a/cmds/statsd/src/logd/LogEvent.cpp
+++ b/cmds/statsd/src/logd/LogEvent.cpp
@@ -17,13 +17,8 @@
 #define DEBUG false  // STOPSHIP if true
 #include "logd/LogEvent.h"
 
-#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
-
-#include <set>
 #include <sstream>
 
-#include "field_util.h"
-#include "dimension.h"
 #include "stats_log_util.h"
 
 namespace android {
@@ -152,9 +147,6 @@
          if (android_log_write_string8(mContext, node.tag().c_str()) < 0) {
             return false;
          }
-         if (android_log_write_int32(mContext, node.uid()) < 0) {
-            return false;
-         }
          if (android_log_write_list_end(mContext) < 0) {
             return false;
          }
@@ -163,47 +155,23 @@
     return false;
 }
 
-namespace {
-
-void increaseField(Field *field, bool is_child) {
-    if (is_child) {
-        if (field->child_size() <= 0) {
-            field->add_child();
-        }
-    } else {
-        field->clear_child();
-    }
-    Field* curr = is_child ? field->mutable_child(0) : field;
-    if (!curr->has_field()) {
-        curr->set_field(1);
-    } else {
-        curr->set_field(curr->field() + 1);
-    }
-}
-
-}  // namespace
-
 /**
  * The elements of each log event are stored as a vector of android_log_list_elements.
  * The goal is to do as little preprocessing as possible, because we read a tiny fraction
  * of the elements that are written to the log.
+ *
+ * The idea here is to read through the log items once, we get as much information we need for
+ * matching as possible. Because this log will be matched against lots of matchers.
  */
 void LogEvent::init(android_log_context context) {
-    if (!context) {
-        return;
-    }
     android_log_list_element elem;
-    // TODO: The log is actually structured inside one list.  This is convenient
-    // because we'll be able to use it to put the attribution (WorkSource) block first
-    // without doing our own tagging scheme.  Until that change is in, just drop the
-    // list-related log elements and the order we get there is our index-keyed data
-    // structure.
     int i = 0;
 
     int seenListStart = 0;
 
-    Field fieldTree;
-    Field* atomField = fieldTree.add_child();
+    int32_t field = 0;
+    int depth = -1;
+    int pos[] = {1, 1, 1};
     do {
         elem = android_log_read_next(context);
         switch ((int)elem.type) {
@@ -211,55 +179,81 @@
                 // elem at [0] is EVENT_TYPE_LIST, [1] is the tag id.
                 if (i == 1) {
                     mTagId = elem.data.int32;
-                    fieldTree.set_field(mTagId);
                 } else {
-                    increaseField(atomField, seenListStart > 0/* is_child */);
-                    mFieldValueMap[fieldTree].set_value_int(elem.data.int32);
-                }
-                break;
-            case EVENT_TYPE_FLOAT:
-                {
-                    increaseField(atomField, seenListStart > 0/* is_child */);
-                    mFieldValueMap[fieldTree].set_value_float(elem.data.float32);
-                }
-                break;
-            case EVENT_TYPE_STRING:
-                {
-                    increaseField(atomField, seenListStart > 0/* is_child */);
-                    mFieldValueMap[fieldTree].set_value_str(
-                        string(elem.data.string, elem.len).c_str());
-                }
-                break;
-            case EVENT_TYPE_LONG:
-                {
-                    increaseField(atomField, seenListStart > 0 /* is_child */);
-                    mFieldValueMap[fieldTree].set_value_long(elem.data.int64);
-                }
-                break;
-            case EVENT_TYPE_LIST:
-                if (i >= 1) {
-                    if (seenListStart > 0) {
-                       increasePosition(atomField);
-                    } else {
-                        increaseField(atomField, false /* is_child */);
-                    }
-                    seenListStart++;
-                    if (seenListStart >= 3) {
-                        ALOGE("Depth > 2. Not supported!");
+                    if (depth < 0 || depth > 2) {
                         return;
                     }
+
+                    mValues.push_back(
+                            FieldValue(Field(mTagId, pos, depth), Value((int32_t)elem.data.int32)));
+
+                    pos[depth]++;
                 }
                 break;
-            case EVENT_TYPE_LIST_STOP:
-                seenListStart--;
-                if (seenListStart == 0) {
-                    atomField->clear_position_index();
-                } else {
-                    if (atomField->child_size() > 0) {
-                       atomField->mutable_child(0)->clear_field();
+            case EVENT_TYPE_FLOAT: {
+                if (depth < 0 || depth > 2) {
+                    ALOGE("Depth > 2. Not supported!");
+                    return;
+                }
+
+                mValues.push_back(FieldValue(Field(mTagId, pos, depth), Value(elem.data.float32)));
+
+                pos[depth]++;
+
+            } break;
+            case EVENT_TYPE_STRING: {
+                if (depth < 0 || depth > 2) {
+                    ALOGE("Depth > 2. Not supported!");
+                    return;
+                }
+
+                mValues.push_back(FieldValue(Field(mTagId, pos, depth),
+                                             Value(string(elem.data.string, elem.len))));
+
+                pos[depth]++;
+
+            } break;
+            case EVENT_TYPE_LONG: {
+                if (depth < 0 || depth > 2) {
+                    ALOGE("Depth > 2. Not supported!");
+                    return;
+                }
+                mValues.push_back(
+                        FieldValue(Field(mTagId, pos, depth), Value((int64_t)elem.data.int64)));
+
+                pos[depth]++;
+
+            } break;
+            case EVENT_TYPE_LIST:
+                depth++;
+                if (depth > 2) {
+                    ALOGE("Depth > 2. Not supported!");
+                    return;
+                }
+                pos[depth] = 1;
+
+                break;
+            case EVENT_TYPE_LIST_STOP: {
+                int prevDepth = depth;
+                depth--;
+                if (depth >= 0 && depth < 2) {
+                    // Now go back to decorate the previous items that are last at prevDepth.
+                    // So that we can later easily match them with Position=Last matchers.
+                    pos[prevDepth]--;
+                    int path = getEncodedField(pos, prevDepth, false);
+                    for (auto it = mValues.rbegin(); it != mValues.rend(); ++it) {
+                        if (it->mField.getDepth() >= prevDepth &&
+                            it->mField.getPath(prevDepth) == path) {
+                            it->mField.decorateLastPos(prevDepth);
+                        } else {
+                            // Safe to break, because the items are in DFS order.
+                            break;
+                        }
                     }
+                    pos[depth]++;
                 }
                 break;
+            }
             case EVENT_TYPE_UNKNOWN:
                 break;
             default:
@@ -270,162 +264,115 @@
 }
 
 int64_t LogEvent::GetLong(size_t key, status_t* err) const {
-    DimensionsValue value;
-    if (!GetSimpleAtomDimensionsValueProto(key, &value)) {
-        *err = BAD_INDEX;
-        return 0;
-    }
-    const DimensionsValue* leafValue = getSingleLeafValue(&value);
-    switch (leafValue->value_case()) {
-        case DimensionsValue::ValueCase::kValueInt:
-            return (int64_t)leafValue->value_int();
-        case DimensionsValue::ValueCase::kValueLong:
-            return leafValue->value_long();
-        case DimensionsValue::ValueCase::kValueBool:
-            return leafValue->value_bool() ? 1 : 0;
-        case DimensionsValue::ValueCase::kValueFloat:
-            return (int64_t)leafValue->value_float();
-        case DimensionsValue::ValueCase::kValueTuple:
-        case DimensionsValue::ValueCase::kValueStr:
-        case DimensionsValue::ValueCase::VALUE_NOT_SET: {
-            *err = BAD_TYPE;
-            return 0;
+    // TODO: encapsulate the magical operations all in Field struct as a static function.
+    int field = getSimpleField(key);
+    for (const auto& value : mValues) {
+        if (value.mField.getField() == field) {
+            if (value.mValue.getType() == INT) {
+                return value.mValue.int_value;
+            } else {
+                *err = BAD_TYPE;
+                return 0;
+            }
+        }
+        if ((size_t)value.mField.getPosAtDepth(0) > key) {
+            break;
         }
     }
+
+    *err = BAD_INDEX;
+    return 0;
 }
 
 int LogEvent::GetInt(size_t key, status_t* err) const {
-  DimensionsValue value;
-  if (!GetSimpleAtomDimensionsValueProto(key, &value)) {
+    int field = getSimpleField(key);
+    for (const auto& value : mValues) {
+        if (value.mField.getField() == field) {
+            if (value.mValue.getType() == INT) {
+                return value.mValue.int_value;
+            } else {
+                *err = BAD_TYPE;
+                return 0;
+            }
+        }
+        if ((size_t)value.mField.getPosAtDepth(0) > key) {
+            break;
+        }
+    }
+
     *err = BAD_INDEX;
     return 0;
-  }
-  const DimensionsValue* leafValue = getSingleLeafValue(&value);
-  switch (leafValue->value_case()) {
-    case DimensionsValue::ValueCase::kValueInt:
-      return leafValue->value_int();
-    case DimensionsValue::ValueCase::kValueLong:
-    case DimensionsValue::ValueCase::kValueBool:
-    case DimensionsValue::ValueCase::kValueFloat:
-    case DimensionsValue::ValueCase::kValueTuple:
-    case DimensionsValue::ValueCase::kValueStr:
-    case DimensionsValue::ValueCase::VALUE_NOT_SET: {
-      *err = BAD_TYPE;
-      return 0;
-    }
-  }
 }
 
 const char* LogEvent::GetString(size_t key, status_t* err) const {
-    DimensionsValue value;
-    if (!GetSimpleAtomDimensionsValueProto(key, &value)) {
-        *err = BAD_INDEX;
-        return 0;
-    }
-    const DimensionsValue* leafValue = getSingleLeafValue(&value);
-    switch (leafValue->value_case()) {
-        case DimensionsValue::ValueCase::kValueStr:
-            return leafValue->value_str().c_str();
-        case DimensionsValue::ValueCase::kValueInt:
-        case DimensionsValue::ValueCase::kValueLong:
-        case DimensionsValue::ValueCase::kValueBool:
-        case DimensionsValue::ValueCase::kValueFloat:
-        case DimensionsValue::ValueCase::kValueTuple:
-        case DimensionsValue::ValueCase::VALUE_NOT_SET: {
-            *err = BAD_TYPE;
-            return 0;
+    int field = getSimpleField(key);
+    for (const auto& value : mValues) {
+        if (value.mField.getField() == field) {
+            if (value.mValue.getType() == STRING) {
+                return value.mValue.str_value.c_str();
+            } else {
+                *err = BAD_TYPE;
+                return 0;
+            }
+        }
+        if ((size_t)value.mField.getPosAtDepth(0) > key) {
+            break;
         }
     }
+
+    *err = BAD_INDEX;
+    return NULL;
 }
 
 bool LogEvent::GetBool(size_t key, status_t* err) const {
-    DimensionsValue value;
-    if (!GetSimpleAtomDimensionsValueProto(key, &value)) {
-        *err = BAD_INDEX;
-        return 0;
-    }
-    const DimensionsValue* leafValue = getSingleLeafValue(&value);
-    switch (leafValue->value_case()) {
-        case DimensionsValue::ValueCase::kValueInt:
-            return leafValue->value_int() != 0;
-        case DimensionsValue::ValueCase::kValueLong:
-            return leafValue->value_long() != 0;
-        case DimensionsValue::ValueCase::kValueBool:
-            return leafValue->value_bool();
-        case DimensionsValue::ValueCase::kValueFloat:
-            return leafValue->value_float() != 0;
-        case DimensionsValue::ValueCase::kValueTuple:
-        case DimensionsValue::ValueCase::kValueStr:
-        case DimensionsValue::ValueCase::VALUE_NOT_SET: {
-            *err = BAD_TYPE;
-            return 0;
+    int field = getSimpleField(key);
+    for (const auto& value : mValues) {
+        if (value.mField.getField() == field) {
+            if (value.mValue.getType() == INT) {
+                return value.mValue.int_value != 0;
+            } else if (value.mValue.getType() == LONG) {
+                return value.mValue.long_value != 0;
+            } else {
+                *err = BAD_TYPE;
+                return false;
+            }
+        }
+        if ((size_t)value.mField.getPosAtDepth(0) > key) {
+            break;
         }
     }
+
+    *err = BAD_INDEX;
+    return false;
 }
 
 float LogEvent::GetFloat(size_t key, status_t* err) const {
-    DimensionsValue value;
-    if (!GetSimpleAtomDimensionsValueProto(key, &value)) {
-        *err = BAD_INDEX;
-        return 0;
-    }
-    const DimensionsValue* leafValue = getSingleLeafValue(&value);
-    switch (leafValue->value_case()) {
-        case DimensionsValue::ValueCase::kValueInt:
-            return (float)leafValue->value_int();
-        case DimensionsValue::ValueCase::kValueLong:
-            return (float)leafValue->value_long();
-        case DimensionsValue::ValueCase::kValueBool:
-            return leafValue->value_bool() ? 1.0f : 0.0f;
-        case DimensionsValue::ValueCase::kValueFloat:
-            return leafValue->value_float();
-        case DimensionsValue::ValueCase::kValueTuple:
-        case DimensionsValue::ValueCase::kValueStr:
-        case DimensionsValue::ValueCase::VALUE_NOT_SET: {
-            *err = BAD_TYPE;
-            return 0;
+    int field = getSimpleField(key);
+    for (const auto& value : mValues) {
+        if (value.mField.getField() == field) {
+            if (value.mValue.getType() == FLOAT) {
+                return value.mValue.float_value;
+            } else {
+                *err = BAD_TYPE;
+                return 0.0;
+            }
+        }
+        if ((size_t)value.mField.getPosAtDepth(0) > key) {
+            break;
         }
     }
-}
 
-void LogEvent::GetAtomDimensionsValueProtos(const FieldMatcher& matcher,
-                                            std::vector<DimensionsValue> *dimensionsValues) const {
-    findDimensionsValues(mFieldValueMap, matcher, dimensionsValues);
-}
-
-bool LogEvent::GetAtomDimensionsValueProto(const FieldMatcher& matcher,
-                                           DimensionsValue* dimensionsValue) const {
-    std::vector<DimensionsValue> rootDimensionsValues;
-    findDimensionsValues(mFieldValueMap, matcher, &rootDimensionsValues);
-    if (rootDimensionsValues.size() != 1) {
-        return false;
-    }
-    *dimensionsValue = rootDimensionsValues.front();
-    return true;
-}
-
-bool LogEvent::GetSimpleAtomDimensionsValueProto(size_t atomField,
-                                                 DimensionsValue* dimensionsValue) const {
-    FieldMatcher matcher;
-    buildSimpleAtomFieldMatcher(mTagId, atomField, &matcher);
-    return GetAtomDimensionsValueProto(matcher, dimensionsValue);
-}
-
-DimensionsValue* LogEvent::findFieldValueOrNull(const Field& field) {
-    auto it = mFieldValueMap.find(field);
-    if (it == mFieldValueMap.end()) {
-        return nullptr;
-    }
-    return &it->second;
+    *err = BAD_INDEX;
+    return 0.0;
 }
 
 string LogEvent::ToString() const {
     ostringstream result;
     result << "{ " << mTimestampNs << " (" << mTagId << ")";
-    for (const auto& itr : mFieldValueMap) {
-        result << FieldToString(itr.first);
+    for (const auto& value : mValues) {
+        result << StringPrintf("%#x", value.mField.getField());
         result << "->";
-        result << DimensionsValueToString(itr.second);
+        result << value.mValue.toString();
         result << " ";
     }
     result << " }";
@@ -433,7 +380,7 @@
 }
 
 void LogEvent::ToProto(ProtoOutputStream& protoOutput) const {
-    writeFieldValueTreeToStream(getFieldValueMap(), &protoOutput);
+    writeFieldValueTreeToStream(mTagId, getValues(), &protoOutput);
 }
 
 }  // namespace statsd
diff --git a/cmds/statsd/src/logd/LogEvent.h b/cmds/statsd/src/logd/LogEvent.h
index d521e09..0895daa 100644
--- a/cmds/statsd/src/logd/LogEvent.h
+++ b/cmds/statsd/src/logd/LogEvent.h
@@ -16,7 +16,7 @@
 
 #pragma once
 
-#include "field_util.h"
+#include "FieldValue.h"
 #include "frameworks/base/cmds/statsd/src/stats_log.pb.h"
 
 #include <android/util/ProtoOutputStream.h>
@@ -24,11 +24,8 @@
 #include <log/log_read.h>
 #include <private/android_logger.h>
 #include <utils/Errors.h>
-#include <utils/JenkinsHash.h>
 
-#include <memory>
 #include <string>
-#include <map>
 #include <vector>
 
 namespace android {
@@ -37,7 +34,6 @@
 
 using std::string;
 using std::vector;
-
 /**
  * Wrapper for the log_msg structure.
  */
@@ -81,19 +77,6 @@
     bool GetBool(size_t key, status_t* err) const;
     float GetFloat(size_t key, status_t* err) const;
 
-    /*
-     * Get DimensionsValue proto objects from FieldMatcher.
-     */
-    void GetAtomDimensionsValueProtos(
-        const FieldMatcher& matcher, std::vector<DimensionsValue> *dimensionsValues) const;
-    bool GetAtomDimensionsValueProto(
-        const FieldMatcher& matcher, DimensionsValue* dimensionsValue) const;
-
-    /*
-     * Get a DimensionsValue proto objects from Field.
-     */
-    bool GetSimpleAtomDimensionsValueProto(size_t field, DimensionsValue* dimensionsValue) const;
-
     /**
      * Write test data to the LogEvent. This can only be used when the LogEvent is constructed
      * using LogEvent(tagId, timestampNs). You need to call init() before you can read from it.
@@ -129,15 +112,16 @@
     void setTimestampNs(uint64_t timestampNs) {mTimestampNs = timestampNs;}
 
     inline int size() const {
-        return mFieldValueMap.size();
+        return mValues.size();
     }
 
-    /**
-     * Returns the mutable DimensionsValue proto for the specific the field.
-     */
-    DimensionsValue* findFieldValueOrNull(const Field& field);
+    const std::vector<FieldValue>& getValues() const {
+        return mValues;
+    }
 
-    inline const FieldValueMap& getFieldValueMap() const { return mFieldValueMap; }
+    std::vector<FieldValue>* getMutableValues() {
+        return &mValues;
+    }
 
 private:
     /**
@@ -151,7 +135,9 @@
      */
     void init(android_log_context context);
 
-    FieldValueMap mFieldValueMap;
+    // The items are naturally sorted in DFS order as we read them. this allows us to do fast
+    // matching.
+    std::vector<FieldValue> mValues;
 
     // This field is used when statsD wants to create log event object and write fields to it. After
     // calling init() function, this object would be destroyed to save memory usage.
diff --git a/cmds/statsd/src/matchers/matcher_util.cpp b/cmds/statsd/src/matchers/matcher_util.cpp
index fae9172..944764b 100644
--- a/cmds/statsd/src/matchers/matcher_util.cpp
+++ b/cmds/statsd/src/matchers/matcher_util.cpp
@@ -13,23 +13,13 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
+#define DEBUG false  // STOPSHIP if true
 #include "Log.h"
 
 #include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
 #include "matchers/LogMatchingTracker.h"
 #include "matchers/matcher_util.h"
-#include "dimension.h"
 #include "stats_util.h"
-#include "field_util.h"
-
-#include <log/event_tag_map.h>
-#include <log/log_event_list.h>
-#include <log/logprint.h>
-#include <utils/Errors.h>
-
-#include <sstream>
-#include <unordered_map>
 
 using std::ostringstream;
 using std::set;
@@ -93,198 +83,224 @@
     return matched;
 }
 
-namespace {
-
-bool matchFieldSimple(const UidMap& uidMap, const FieldValueMap& fieldMap,
-                      const FieldValueMatcher&matcher, Field* rootField, Field* leafField);
-
-bool matchesNonRepeatedField(const UidMap& uidMap, const FieldValueMap& fieldMap,
-                             const FieldValueMatcher&matcher, Field* rootField, Field* leafField) {
-    if (matcher.value_matcher_case() ==
-            FieldValueMatcher::ValueMatcherCase::VALUE_MATCHER_NOT_SET) {
-        return !fieldMap.empty() && fieldMap.begin()->first.field() == matcher.field();
-    } else if (matcher.value_matcher_case() == FieldValueMatcher::ValueMatcherCase::kMatchesTuple) {
-        bool allMatched = true;
-        Field* newLeafField = leafField->add_child();
-        for (int i = 0; allMatched && i <  matcher.matches_tuple().field_value_matcher_size(); ++i) {
-            const auto& childMatcher = matcher.matches_tuple().field_value_matcher(i);
-            newLeafField->set_field(childMatcher.field());
-            allMatched &= matchFieldSimple(uidMap, fieldMap, childMatcher, rootField, newLeafField);
-        }
-        leafField->clear_child();
-        return allMatched;
-    } else {
-        auto ret = fieldMap.equal_range(*rootField);
-        int found = 0;
-        for (auto it = ret.first; it != ret.second; ++it) {
-            found++;
-        }
-        // Not found.
-        if (found <= 0) {
-            return false;
-        }
-        if (found > 1) {
-            ALOGE("Found multiple values for optional field.");
-            return false;
-        }
-        bool matched = false;
-        switch (matcher.value_matcher_case()) {
-            case FieldValueMatcher::ValueMatcherCase::kEqBool: {
-                // Logd does not support bool, it is int instead.
-                matched = ((ret.first->second.value_int() > 0) == matcher.eq_bool());
-                break;
-            }
-            case FieldValueMatcher::ValueMatcherCase::kEqString: {
-                if (IsAttributionUidField(*rootField)) {
-                    const int uid = ret.first->second.value_int();
-                    std::set<string> packageNames =
-                            uidMap.getAppNamesFromUid(uid, true /* normalize*/);
-                    matched = packageNames.find(matcher.eq_string()) != packageNames.end();
-                } else {
-                    matched = (ret.first->second.value_str() == matcher.eq_string());
-                }
-                break;
-            }
-            case FieldValueMatcher::ValueMatcherCase::kEqInt: {
-                    int64_t val = ret.first->second.has_value_int() ?
-                                  ret.first->second.value_int() : ret.first->second.value_long();
-                    matched = (val == matcher.eq_int());
-                break;
-            }
-            case FieldValueMatcher::ValueMatcherCase::kLtInt: {
-                int64_t val = ret.first->second.has_value_int() ?
-                              ret.first->second.value_int() : ret.first->second.value_long();
-                matched = (val < matcher.lt_int());
-                break;
-            }
-            case FieldValueMatcher::ValueMatcherCase::kGtInt: {
-                int64_t val = ret.first->second.has_value_int() ?
-                              ret.first->second.value_int() : ret.first->second.value_long();
-                matched = (val > matcher.gt_int());
-                break;
-            }
-            case FieldValueMatcher::ValueMatcherCase::kLtFloat: {
-                matched = (ret.first->second.value_float() < matcher.lt_float());
-                break;
-            }
-            case FieldValueMatcher::ValueMatcherCase::kGtFloat: {
-                matched = (ret.first->second.value_float() > matcher.gt_float());
-                break;
-            }
-            case FieldValueMatcher::ValueMatcherCase::kLteInt: {
-                int64_t val = ret.first->second.has_value_int() ?
-                              ret.first->second.value_int() : ret.first->second.value_long();
-                matched = (val <= matcher.lte_int());
-                break;
-            }
-            case FieldValueMatcher::ValueMatcherCase::kGteInt: {
-                int64_t val = ret.first->second.has_value_int() ?
-                              ret.first->second.value_int() : ret.first->second.value_long();
-                matched = (val >= matcher.gte_int());
-                break;
-            }
-            default:
-                break;
-        }
-        return matched;
+bool tryMatchString(const UidMap& uidMap, const Field& field, const Value& value,
+                    const string& str_match) {
+    if (isAttributionUidField(field, value)) {
+        int uid = value.int_value;
+        std::set<string> packageNames = uidMap.getAppNamesFromUid(uid, true /* normalize*/);
+        return packageNames.find(str_match) != packageNames.end();
+    } else if (value.getType() == STRING) {
+        return value.str_value == str_match;
     }
+    return false;
 }
 
-bool matchesRepeatedField(const UidMap& uidMap, const FieldValueMap& fieldMap,
-                          const FieldValueMatcher&matcher,
-                          Field* rootField, Field* leafField) {
-    if (matcher.position() == Position::FIRST) {
-        leafField->set_position_index(0);
-        bool res = matchesNonRepeatedField(uidMap, fieldMap, matcher, rootField, leafField);
-        leafField->clear_position_index();
-        return res;
-    } else {
-        auto itLower = fieldMap.lower_bound(*rootField);
-        if (itLower == fieldMap.end()) {
+bool matchesSimple(const UidMap& uidMap, const FieldValueMatcher& matcher,
+                   const vector<FieldValue>& values, int start, int end, int depth) {
+    if (depth > 2) {
+        ALOGE("Depth > 3 not supported");
+        return false;
+    }
+
+    if (start >= end) {
+        return false;
+    }
+
+    // Filter by entry field first
+    int newStart = -1;
+    int newEnd = end;
+    // because the fields are naturally sorted in the DFS order. we can safely
+    // break when pos is larger than the one we are searching for.
+    for (int i = start; i < end; i++) {
+        int pos = values[i].mField.getPosAtDepth(depth);
+        if (pos == matcher.field()) {
+            if (newStart == -1) {
+                newStart = i;
+            }
+            newEnd = i + 1;
+        } else if (pos > matcher.field()) {
+            break;
+        }
+    }
+
+    // Now we have zoomed in to a new range
+    start = newStart;
+    end = newEnd;
+
+    if (start == -1) {
+        // No such field found.
+        return false;
+    }
+
+    vector<pair<int, int>> ranges; // the ranges are for matching ANY position
+    if (matcher.has_position()) {
+        // Repeated fields position is stored as a node in the path.
+        depth++;
+        if (depth > 2) {
             return false;
         }
-
-        const int leafFieldNum = leafField->field();
-        leafField->set_field(leafFieldNum + 1);
-        auto itUpper = fieldMap.lower_bound(*rootField);
-        // Resets the field number.
-        leafField->set_field(leafFieldNum);
-
         switch (matcher.position()) {
-             case Position::LAST:
-                 {
-                     itUpper--;
-                     if (itUpper == fieldMap.end()) {
-                        return false;
-                     } else {
-                         int last_index = getPositionByReferenceField(*rootField, itUpper->first);
-                         if (last_index < 0) {
-                            return false;
-                         }
-                         leafField->set_position_index(last_index);
-                         bool res = matchesNonRepeatedField(uidMap, fieldMap, matcher, rootField, leafField);
-                         leafField->clear_position_index();
-                         return res;
-                     }
-                 }
-                 break;
-             case Position::ANY:
-                 {
-                    bool matched = false;
-                    for (auto it = itLower; it != itUpper; ++it) {
-                        int index = getPositionByReferenceField(*rootField, it->first);
-                        if (index >= 0) {
-                             leafField->set_position_index(index);
-                             matched |= matchesNonRepeatedField(uidMap, fieldMap, matcher, rootField, leafField);
-                             leafField->clear_position_index();
-                             if (matched) {
-                                break;
-                             }
-                        }
+            case Position::FIRST: {
+                for (int i = start; i < end; i++) {
+                    int pos = values[i].mField.getPosAtDepth(depth);
+                    if (pos != 1) {
+                        // Again, the log elements are stored in sorted order. so
+                        // once the position is > 1, we break;
+                        end = i;
+                        break;
                     }
-                    return matched;
-                 }
-             default:
-                return false;
-         }
-    }
-
-}
-
-bool matchFieldSimple(const UidMap& uidMap, const FieldValueMap& fieldMap,
-                      const FieldValueMatcher&matcher, Field* rootField, Field* leafField) {
-    if (!matcher.has_position()) {
-        return matchesNonRepeatedField(uidMap, fieldMap, matcher, rootField, leafField);
+                }
+                ranges.push_back(std::make_pair(start, end));
+                break;
+            }
+            case Position::LAST: {
+                // move the starting index to the first LAST field at the depth.
+                for (int i = start; i < end; i++) {
+                    if (values[i].mField.isLastPos(depth)) {
+                        start = i;
+                        break;
+                    }
+                }
+                ranges.push_back(std::make_pair(start, end));
+                break;
+            }
+            case Position::ANY: {
+                // ANY means all the children matchers match in any of the sub trees, it's a match
+                newStart = start;
+                newEnd = end;
+                // Here start is guaranteed to be a valid index.
+                int currentPos = values[start].mField.getPosAtDepth(depth);
+                // Now find all sub trees ranges.
+                for (int i = start; i < end; i++) {
+                    int newPos = values[i].mField.getPosAtDepth(depth);
+                    if (newPos != currentPos) {
+                        ranges.push_back(std::make_pair(newStart, i));
+                        newStart = i;
+                        currentPos = newPos;
+                    }
+                }
+                ranges.push_back(std::make_pair(newStart, end));
+                break;
+            }
+            case Position::POSITION_UNKNOWN:
+                break;
+        }
     } else {
-        return matchesRepeatedField(uidMap, fieldMap, matcher, rootField, leafField);
+        // No position
+        ranges.push_back(std::make_pair(start, end));
+    }
+    // start and end are still pointing to the matched range.
+    switch (matcher.value_matcher_case()) {
+        case FieldValueMatcher::kMatchesTuple: {
+            ++depth;
+            // If any range matches all matchers, good.
+            for (const auto& range : ranges) {
+                bool matched = true;
+                for (const auto& subMatcher : matcher.matches_tuple().field_value_matcher()) {
+                    if (!matchesSimple(uidMap, subMatcher, values, range.first, range.second,
+                                       depth)) {
+                        matched = false;
+                        break;
+                    }
+                }
+                if (matched) return true;
+            }
+            return false;
+        }
+        case FieldValueMatcher::ValueMatcherCase::kEqBool: {
+            for (int i = start; i < end; i++) {
+                if ((values[i].mValue.getType() == INT &&
+                     (values[i].mValue.int_value != 0) == matcher.eq_bool()) ||
+                    (values[i].mValue.getType() == LONG &&
+                     (values[i].mValue.long_value != 0) == matcher.eq_bool())) {
+                    return true;
+                }
+            }
+            return false;
+        }
+        case FieldValueMatcher::ValueMatcherCase::kEqString: {
+            for (int i = start; i < end; i++) {
+                if (tryMatchString(uidMap, values[i].mField, values[i].mValue,
+                                   matcher.eq_string())) {
+                    return true;
+                }
+            }
+        }
+            return false;
+        case FieldValueMatcher::ValueMatcherCase::kEqInt:
+            for (int i = start; i < end; i++) {
+                if (values[i].mValue.getType() == INT &&
+                    (matcher.eq_int() == values[i].mValue.int_value)) {
+                    return true;
+                }
+            }
+            return false;
+        case FieldValueMatcher::ValueMatcherCase::kLtInt:
+            for (int i = start; i < end; i++) {
+                if (values[i].mValue.getType() == INT &&
+                    (values[i].mValue.int_value < matcher.lt_int())) {
+                    return true;
+                }
+            }
+            return false;
+        case FieldValueMatcher::ValueMatcherCase::kGtInt:
+            for (int i = start; i < end; i++) {
+                if (values[i].mValue.getType() == INT &&
+                    (values[i].mValue.int_value > matcher.gt_int())) {
+                    return true;
+                }
+            }
+            return false;
+        case FieldValueMatcher::ValueMatcherCase::kLtFloat:
+            for (int i = start; i < end; i++) {
+                if (values[i].mValue.getType() == FLOAT &&
+                    (values[i].mValue.float_value < matcher.lt_float())) {
+                    return true;
+                }
+            }
+            return false;
+        case FieldValueMatcher::ValueMatcherCase::kGtFloat:
+            for (int i = start; i < end; i++) {
+                if (values[i].mValue.getType() == FLOAT &&
+                    (values[i].mValue.float_value > matcher.gt_float())) {
+                    return true;
+                }
+            }
+            return false;
+        case FieldValueMatcher::ValueMatcherCase::kLteInt:
+            for (int i = start; i < end; i++) {
+                if (values[i].mValue.getType() == INT &&
+                    (values[i].mValue.int_value <= matcher.lte_int())) {
+                    return true;
+                }
+            }
+            return false;
+        case FieldValueMatcher::ValueMatcherCase::kGteInt:
+            for (int i = start; i < end; i++) {
+                if (values[i].mValue.getType() == INT &&
+                    (values[i].mValue.int_value >= matcher.gte_int())) {
+                    return true;
+                }
+            }
+            return false;
+        default:
+            return false;
     }
 }
 
-}  // namespace
-
 bool matchesSimple(const UidMap& uidMap, const SimpleAtomMatcher& simpleMatcher,
                    const LogEvent& event) {
     if (simpleMatcher.field_value_matcher_size() <= 0) {
         return event.GetTagId() == simpleMatcher.atom_id();
     }
-    Field root_field;
-    root_field.set_field(simpleMatcher.atom_id());
-    FieldValueMatcher root_field_matcher;
-    root_field_matcher.set_field(simpleMatcher.atom_id());
-    for (int i = 0; i < simpleMatcher.field_value_matcher_size(); i++) {
-        *root_field_matcher.mutable_matches_tuple()->add_field_value_matcher() =
-            simpleMatcher.field_value_matcher(i);
+    for (const auto& matcher : simpleMatcher.field_value_matcher()) {
+        if (!matchesSimple(uidMap, matcher, event.getValues(), 0, event.getValues().size(), 0)) {
+            return false;
+        }
     }
-    return matchFieldSimple(
-        uidMap, event.getFieldValueMap(), root_field_matcher, &root_field, &root_field);
+    return true;
 }
 
-void getDimensionKeys(const LogEvent& event, const FieldMatcher& matcher,
-                      std::vector<DimensionsValue> *dimensionKeys) {
-    if (matcher.has_field()) {
-        findDimensionsValues(event.getFieldValueMap(), matcher, dimensionKeys);
-    }
-}
 }  // namespace statsd
 }  // namespace os
 }  // namespace android
diff --git a/cmds/statsd/src/matchers/matcher_util.h b/cmds/statsd/src/matchers/matcher_util.h
index a45a9fb..872cd8e 100644
--- a/cmds/statsd/src/matchers/matcher_util.h
+++ b/cmds/statsd/src/matchers/matcher_util.h
@@ -45,9 +45,6 @@
 bool matchesSimple(const UidMap& uidMap,
     const SimpleAtomMatcher& simpleMatcher, const LogEvent& wrapper);
 
-void getDimensionKeys(const LogEvent& event, const FieldMatcher& matcher,
-                      std::vector<DimensionsValue> *dimensionKeys);
-
 }  // namespace statsd
 }  // namespace os
 }  // namespace android
diff --git a/cmds/statsd/src/metrics/CountMetricProducer.cpp b/cmds/statsd/src/metrics/CountMetricProducer.cpp
index 5a042b6..bd2674b 100644
--- a/cmds/statsd/src/metrics/CountMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/CountMetricProducer.cpp
@@ -21,7 +21,6 @@
 #include "guardrail/StatsdStats.h"
 #include "stats_util.h"
 #include "stats_log_util.h"
-#include "dimension.h"
 
 #include <limits.h>
 #include <stdlib.h>
@@ -69,16 +68,26 @@
         mBucketSizeNs = LLONG_MAX;
     }
 
-    // TODO: use UidMap if uid->pkg_name is required
-    mDimensionsInWhat = metric.dimensions_in_what();
-    mDimensionsInCondition = metric.dimensions_in_condition();
+    if (metric.has_dimensions_in_what()) {
+        translateFieldMatcher(metric.dimensions_in_what(), &mDimensionsInWhat);
+    }
+
+    if (metric.has_dimensions_in_condition()) {
+        translateFieldMatcher(metric.dimensions_in_condition(), &mDimensionsInCondition);
+    }
 
     if (metric.links().size() > 0) {
-        mConditionLinks.insert(mConditionLinks.begin(), metric.links().begin(),
-                               metric.links().end());
+        for (const auto& link : metric.links()) {
+            Metric2Condition mc;
+            mc.conditionId = link.condition();
+            translateFieldMatcher(link.fields_in_what(), &mc.metricFields);
+            translateFieldMatcher(link.fields_in_condition(), &mc.conditionFields);
+            mMetric2ConditionLinks.push_back(mc);
+        }
+        mConditionSliced = true;
     }
-    mConditionSliced = (metric.links().size() > 0)||
-        (mDimensionsInCondition.has_field() && mDimensionsInCondition.child_size() > 0);
+
+    mConditionSliced = (metric.links().size() > 0) || (mDimensionsInCondition.size() > 0);
 
     VLOG("metric %lld created. bucket size %lld start_time: %lld", (long long)metric.id(),
          (long long)mBucketSizeNs, (long long)mStartTimeNs);
@@ -92,26 +101,6 @@
     VLOG("Metric %lld onSlicedConditionMayChange", (long long)mMetricId);
 }
 
-void CountMetricProducer::onDumpReportLocked(const uint64_t dumpTimeNs, StatsLogReport* report) {
-    flushIfNeededLocked(dumpTimeNs);
-    report->set_metric_id(mMetricId);
-
-    auto count_metrics = report->mutable_count_metrics();
-    for (const auto& counter : mPastBuckets) {
-        CountMetricData* metricData = count_metrics->add_data();
-        *metricData->mutable_dimensions_in_what() =
-            counter.first.getDimensionKeyInWhat().getDimensionsValue();
-        *metricData->mutable_dimensions_in_condition() =
-            counter.first.getDimensionKeyInCondition().getDimensionsValue();
-        for (const auto& bucket : counter.second) {
-            CountBucketInfo* bucketInfo = metricData->add_bucket_info();
-            bucketInfo->set_start_bucket_nanos(bucket.mBucketStartNs);
-            bucketInfo->set_end_bucket_nanos(bucket.mBucketEndNs);
-            bucketInfo->set_count(bucket.mCount);
-        }
-    }
-}
-
 void CountMetricProducer::onDumpReportLocked(const uint64_t dumpTimeNs,
                                              ProtoOutputStream* protoOutput) {
     flushIfNeededLocked(dumpTimeNs);
@@ -122,8 +111,6 @@
     protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_ID, (long long)mMetricId);
     long long protoToken = protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_ID_COUNT_METRICS);
 
-    VLOG("metric %lld dump report now...",(long long)mMetricId);
-
     for (const auto& counter : mPastBuckets) {
         const MetricDimensionKey& dimensionKey = counter.first;
         VLOG("  dimension key %s", dimensionKey.c_str());
@@ -134,15 +121,13 @@
         // First fill dimension.
         long long dimensionInWhatToken = protoOutput->start(
                 FIELD_TYPE_MESSAGE | FIELD_ID_DIMENSION_IN_WHAT);
-        writeDimensionsValueProtoToStream(
-            dimensionKey.getDimensionKeyInWhat().getDimensionsValue(), protoOutput);
+        writeDimensionToProto(dimensionKey.getDimensionKeyInWhat(), protoOutput);
         protoOutput->end(dimensionInWhatToken);
 
         if (dimensionKey.hasDimensionKeyInCondition()) {
             long long dimensionInConditionToken = protoOutput->start(
                     FIELD_TYPE_MESSAGE | FIELD_ID_DIMENSION_IN_CONDITION);
-            writeDimensionsValueProtoToStream(
-                dimensionKey.getDimensionKeyInCondition().getDimensionsValue(), protoOutput);
+            writeDimensionToProto(dimensionKey.getDimensionKeyInCondition(), protoOutput);
             protoOutput->end(dimensionInConditionToken);
         }
 
@@ -200,7 +185,6 @@
         const ConditionKey& conditionKey, bool condition,
         const LogEvent& event) {
     uint64_t eventTimeNs = event.GetTimestampNs();
-
     flushIfNeededLocked(eventTimeNs);
 
     if (condition == false) {
diff --git a/cmds/statsd/src/metrics/CountMetricProducer.h b/cmds/statsd/src/metrics/CountMetricProducer.h
index b06c77b..0c4291d 100644
--- a/cmds/statsd/src/metrics/CountMetricProducer.h
+++ b/cmds/statsd/src/metrics/CountMetricProducer.h
@@ -57,7 +57,6 @@
 private:
     void onDumpReportLocked(const uint64_t dumpTimeNs,
                             android::util::ProtoOutputStream* protoOutput) override;
-    void onDumpReportLocked(const uint64_t dumpTimeNs, StatsLogReport* report) override;
 
     // Internal interface to handle condition change.
     void onConditionChangedLocked(const bool conditionMet, const uint64_t eventTime) override;
diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.cpp b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
index 65cbc4a..6b321e1 100644
--- a/cmds/statsd/src/metrics/DurationMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
@@ -21,7 +21,6 @@
 #include "guardrail/StatsdStats.h"
 #include "stats_util.h"
 #include "stats_log_util.h"
-#include "dimension.h"
 
 #include <limits.h>
 #include <stdlib.h>
@@ -68,8 +67,7 @@
       mStartIndex(startIndex),
       mStopIndex(stopIndex),
       mStopAllIndex(stopAllIndex),
-      mNested(nesting),
-      mInternalDimensions(internalDimensions) {
+      mNested(nesting) {
     // TODO: The following boiler plate code appears in all MetricProducers, but we can't abstract
     // them in the base class, because the proto generated CountMetric, and DurationMetric are
     // not related. Maybe we should add a template in the future??
@@ -79,16 +77,28 @@
         mBucketSizeNs = LLONG_MAX;
     }
 
-    // TODO: use UidMap if uid->pkg_name is required
-    mDimensionsInWhat = metric.dimensions_in_what();
-    mDimensionsInCondition = metric.dimensions_in_condition();
+    if (metric.has_dimensions_in_what()) {
+        translateFieldMatcher(metric.dimensions_in_what(), &mDimensionsInWhat);
+    }
+
+    if (internalDimensions.has_field()) {
+        translateFieldMatcher(internalDimensions, &mInternalDimensions);
+    }
+
+    if (metric.has_dimensions_in_condition()) {
+        translateFieldMatcher(metric.dimensions_in_condition(), &mDimensionsInCondition);
+    }
 
     if (metric.links().size() > 0) {
-        mConditionLinks.insert(mConditionLinks.begin(), metric.links().begin(),
-                               metric.links().end());
+        for (const auto& link : metric.links()) {
+            Metric2Condition mc;
+            mc.conditionId = link.condition();
+            translateFieldMatcher(link.fields_in_what(), &mc.metricFields);
+            translateFieldMatcher(link.fields_in_condition(), &mc.conditionFields);
+            mMetric2ConditionLinks.push_back(mc);
+        }
     }
-    mConditionSliced = (metric.links().size() > 0)||
-        (mDimensionsInCondition.has_field() && mDimensionsInCondition.child_size() > 0);
+    mConditionSliced = (metric.links().size() > 0) || (mDimensionsInCondition.size() > 0);
 
     VLOG("metric %lld created. bucket size %lld start_time: %lld", (long long)metric.id(),
          (long long)mBucketSizeNs, (long long)mStartTimeNs);
@@ -174,37 +184,18 @@
     }
 }
 
-void DurationMetricProducer::onDumpReportLocked(const uint64_t dumpTimeNs, StatsLogReport* report) {
-    flushIfNeededLocked(dumpTimeNs);
-    report->set_metric_id(mMetricId);
-
-    auto duration_metrics = report->mutable_duration_metrics();
-    for (const auto& pair : mPastBuckets) {
-        DurationMetricData* metricData = duration_metrics->add_data();
-        *metricData->mutable_dimensions_in_what() =
-            pair.first.getDimensionKeyInWhat().getDimensionsValue();
-        *metricData->mutable_dimensions_in_condition() =
-            pair.first.getDimensionKeyInCondition().getDimensionsValue();
-        for (const auto& bucket : pair.second) {
-            auto bucketInfo = metricData->add_bucket_info();
-            bucketInfo->set_start_bucket_nanos(bucket.mBucketStartNs);
-            bucketInfo->set_end_bucket_nanos(bucket.mBucketEndNs);
-            bucketInfo->set_duration_nanos(bucket.mDuration);
-        }
-    }
-}
-
 void DurationMetricProducer::onDumpReportLocked(const uint64_t dumpTimeNs,
                                                 ProtoOutputStream* protoOutput) {
     flushIfNeededLocked(dumpTimeNs);
     if (mPastBuckets.empty()) {
+        VLOG(" Duration metric, empty return");
         return;
     }
 
     protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_ID, (long long)mMetricId);
     long long protoToken = protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_ID_DURATION_METRICS);
 
-    VLOG("metric %lld dump report now...", (long long)mMetricId);
+    VLOG("Duration metric %lld dump report now...", (long long)mMetricId);
 
     for (const auto& pair : mPastBuckets) {
         const MetricDimensionKey& dimensionKey = pair.first;
@@ -216,15 +207,13 @@
         // First fill dimension.
         long long dimensionToken = protoOutput->start(
                 FIELD_TYPE_MESSAGE | FIELD_ID_DIMENSION_IN_WHAT);
-        writeDimensionsValueProtoToStream(
-            dimensionKey.getDimensionKeyInWhat().getDimensionsValue(), protoOutput);
+        writeDimensionToProto(dimensionKey.getDimensionKeyInWhat(), protoOutput);
         protoOutput->end(dimensionToken);
 
         if (dimensionKey.hasDimensionKeyInCondition()) {
             long long dimensionInConditionToken = protoOutput->start(
                     FIELD_TYPE_MESSAGE | FIELD_ID_DIMENSION_IN_CONDITION);
-            writeDimensionsValueProtoToStream(
-                dimensionKey.getDimensionKeyInCondition().getDimensionsValue(), protoOutput);
+            writeDimensionToProto(dimensionKey.getDimensionKeyInCondition(), protoOutput);
             protoOutput->end(dimensionInConditionToken);
         }
 
@@ -339,8 +328,8 @@
 
     auto it = mCurrentSlicedDurationTrackerMap.find(eventKey);
 
-    std::vector<DimensionsValue> values;
-    getDimensionKeys(event, mInternalDimensions, &values);
+    std::vector<HashableDimensionKey> values;
+    filterValues(mInternalDimensions, event.getValues(), &values);
     if (values.empty()) {
         if (matcherIndex == mStartIndex) {
             it->second->noteStart(DEFAULT_DIMENSION_KEY, condition,
@@ -349,13 +338,11 @@
             it->second->noteStop(DEFAULT_DIMENSION_KEY, event.GetTimestampNs(), false);
         }
     } else {
-        for (const DimensionsValue& value : values) {
+        for (const auto& value : values) {
             if (matcherIndex == mStartIndex) {
-                it->second->noteStart(
-                    HashableDimensionKey(value), condition, event.GetTimestampNs(), conditionKeys);
+                it->second->noteStart(value, condition, event.GetTimestampNs(), conditionKeys);
             } else if (matcherIndex == mStopIndex) {
-                it->second->noteStop(
-                   HashableDimensionKey(value), event.GetTimestampNs(), false);
+                it->second->noteStop(value, event.GetTimestampNs(), false);
             }
         }
     }
diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.h b/cmds/statsd/src/metrics/DurationMetricProducer.h
index a496016..5f29281 100644
--- a/cmds/statsd/src/metrics/DurationMetricProducer.h
+++ b/cmds/statsd/src/metrics/DurationMetricProducer.h
@@ -57,7 +57,6 @@
 private:
     void onDumpReportLocked(const uint64_t dumpTimeNs,
                             android::util::ProtoOutputStream* protoOutput) override;
-    void onDumpReportLocked(const uint64_t dumpTimeNs, StatsLogReport* report) override;
 
     // Internal interface to handle condition change.
     void onConditionChangedLocked(const bool conditionMet, const uint64_t eventTime) override;
@@ -90,7 +89,7 @@
     const bool mNested;
 
     // The dimension from the atom predicate. e.g., uid, wakelock name.
-    const FieldMatcher mInternalDimensions;
+    vector<Matcher> mInternalDimensions;
 
     // Save the past buckets and we can clear when the StatsLogReport is dumped.
     // TODO: Add a lock to mPastBuckets.
diff --git a/cmds/statsd/src/metrics/EventMetricProducer.cpp b/cmds/statsd/src/metrics/EventMetricProducer.cpp
index 0578e06..ed7e44d 100644
--- a/cmds/statsd/src/metrics/EventMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/EventMetricProducer.cpp
@@ -55,13 +55,16 @@
                                          const uint64_t startTimeNs)
     : MetricProducer(metric.id(), key, startTimeNs, conditionIndex, wizard) {
     if (metric.links().size() > 0) {
-        mConditionLinks.insert(mConditionLinks.begin(), metric.links().begin(),
-                               metric.links().end());
+        for (const auto& link : metric.links()) {
+            Metric2Condition mc;
+            mc.conditionId = link.condition();
+            translateFieldMatcher(link.fields_in_what(), &mc.metricFields);
+            translateFieldMatcher(link.fields_in_condition(), &mc.conditionFields);
+            mMetric2ConditionLinks.push_back(mc);
+        }
         mConditionSliced = true;
     }
-
-    startNewProtoOutputStreamLocked();
-
+    mProto = std::make_unique<ProtoOutputStream>();
     VLOG("metric %lld created. bucket size %lld start_time: %lld", (long long)metric.id(),
          (long long)mBucketSizeNs, (long long)mStartTimeNs);
 }
@@ -70,10 +73,6 @@
     VLOG("~EventMetricProducer() called");
 }
 
-void EventMetricProducer::startNewProtoOutputStreamLocked() {
-    mProto = std::make_unique<ProtoOutputStream>();
-}
-
 void EventMetricProducer::onSlicedConditionMayChangeLocked(const uint64_t eventTime) {
 }
 
@@ -94,10 +93,6 @@
     return buffer;
 }
 
-void EventMetricProducer::onDumpReportLocked(const uint64_t dumpTimeNs, StatsLogReport* report) {
-
-}
-
 void EventMetricProducer::onDumpReportLocked(const uint64_t dumpTimeNs,
                                              ProtoOutputStream* protoOutput) {
     if (mProto->size() <= 0) {
@@ -113,7 +108,7 @@
     protoOutput->write(FIELD_TYPE_MESSAGE | FIELD_ID_EVENT_METRICS,
                        reinterpret_cast<char*>(buffer.get()->data()), buffer.get()->size());
 
-    startNewProtoOutputStreamLocked();
+    mProto->clear();
 }
 
 void EventMetricProducer::onConditionChangedLocked(const bool conditionMet,
diff --git a/cmds/statsd/src/metrics/EventMetricProducer.h b/cmds/statsd/src/metrics/EventMetricProducer.h
index 935f206..3f2c5a5 100644
--- a/cmds/statsd/src/metrics/EventMetricProducer.h
+++ b/cmds/statsd/src/metrics/EventMetricProducer.h
@@ -40,9 +40,6 @@
 
     virtual ~EventMetricProducer();
 
-protected:
-    void startNewProtoOutputStreamLocked();
-
 private:
     void onMatchedLogEventInternalLocked(
             const size_t matcherIndex, const MetricDimensionKey& eventKey,
@@ -51,7 +48,6 @@
 
     void onDumpReportLocked(const uint64_t dumpTimeNs,
                             android::util::ProtoOutputStream* protoOutput) override;
-    void onDumpReportLocked(const uint64_t dumpTimeNs, StatsLogReport* report) override;
 
     // Internal interface to handle condition change.
     void onConditionChangedLocked(const bool conditionMet, const uint64_t eventTime) override;
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
index 62ee6ef..da0cafe 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
@@ -19,7 +19,6 @@
 
 #include "GaugeMetricProducer.h"
 #include "guardrail/StatsdStats.h"
-#include "dimension.h"
 #include "stats_log_util.h"
 
 #include <cutils/log.h>
@@ -77,18 +76,29 @@
     mBucketSizeNs = bucketSizeMills * 1000000;
 
     mSamplingType = metric.sampling_type();
-    mFieldFilter = metric.gauge_fields_filter();
+    if (!metric.gauge_fields_filter().include_all()) {
+        translateFieldMatcher(metric.gauge_fields_filter().fields(), &mFieldMatchers);
+    }
 
     // TODO: use UidMap if uid->pkg_name is required
-    mDimensionsInWhat = metric.dimensions_in_what();
-    mDimensionsInCondition = metric.dimensions_in_condition();
+    if (metric.has_dimensions_in_what()) {
+        translateFieldMatcher(metric.dimensions_in_what(), &mDimensionsInWhat);
+    }
+
+    if (metric.has_dimensions_in_condition()) {
+        translateFieldMatcher(metric.dimensions_in_condition(), &mDimensionsInCondition);
+    }
 
     if (metric.links().size() > 0) {
-        mConditionLinks.insert(mConditionLinks.begin(), metric.links().begin(),
-                               metric.links().end());
+        for (const auto& link : metric.links()) {
+            Metric2Condition mc;
+            mc.conditionId = link.condition();
+            translateFieldMatcher(link.fields_in_what(), &mc.metricFields);
+            translateFieldMatcher(link.fields_in_condition(), &mc.conditionFields);
+            mMetric2ConditionLinks.push_back(mc);
+        }
     }
-    mConditionSliced = (metric.links().size() > 0)||
-        (mDimensionsInCondition.has_field() && mDimensionsInCondition.child_size() > 0);
+    mConditionSliced = (metric.links().size() > 0) || (mDimensionsInCondition.size() > 0);
 
     // Kicks off the puller immediately.
     if (mPullTagId != -1 && mSamplingType == GaugeMetric::RANDOM_ONE_SAMPLE) {
@@ -115,13 +125,6 @@
     }
 }
 
-void GaugeMetricProducer::onDumpReportLocked(const uint64_t dumpTimeNs, StatsLogReport* report) {
-    flushIfNeededLocked(dumpTimeNs);
-    ProtoOutputStream pbOutput;
-    onDumpReportLocked(dumpTimeNs, &pbOutput);
-    parseProtoOutputStream(pbOutput, report);
-}
-
 void GaugeMetricProducer::onDumpReportLocked(const uint64_t dumpTimeNs,
                                              ProtoOutputStream* protoOutput) {
     VLOG("gauge metric %lld report now...", (long long)mMetricId);
@@ -144,15 +147,13 @@
         // First fill dimension.
         long long dimensionToken = protoOutput->start(
                 FIELD_TYPE_MESSAGE | FIELD_ID_DIMENSION_IN_WHAT);
-        writeDimensionsValueProtoToStream(
-            dimensionKey.getDimensionKeyInWhat().getDimensionsValue(), protoOutput);
+        writeDimensionToProto(dimensionKey.getDimensionKeyInWhat(), protoOutput);
         protoOutput->end(dimensionToken);
 
         if (dimensionKey.hasDimensionKeyInCondition()) {
             long long dimensionInConditionToken = protoOutput->start(
                     FIELD_TYPE_MESSAGE | FIELD_ID_DIMENSION_IN_CONDITION);
-            writeDimensionsValueProtoToStream(
-                dimensionKey.getDimensionKeyInCondition().getDimensionsValue(), protoOutput);
+            writeDimensionToProto(dimensionKey.getDimensionKeyInCondition(), protoOutput);
             protoOutput->end(dimensionInConditionToken);
         }
 
@@ -169,7 +170,7 @@
                 long long atomsToken =
                     protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_ATOM);
                 for (const auto& atom : bucket.mGaugeAtoms) {
-                    writeFieldValueTreeToStream(*atom.mFields, protoOutput);
+                    writeFieldValueTreeToStream(mTagId, *(atom.mFields), protoOutput);
                 }
                 protoOutput->end(atomsToken);
 
@@ -246,13 +247,14 @@
     VLOG("Metric %lld onSlicedConditionMayChange", (long long)mMetricId);
 }
 
-std::shared_ptr<FieldValueMap> GaugeMetricProducer::getGaugeFields(const LogEvent& event) {
-    std::shared_ptr<FieldValueMap> gaugeFields =
-        std::make_shared<FieldValueMap>(event.getFieldValueMap());
-    if (!mFieldFilter.include_all()) {
-        filterFields(mFieldFilter.fields(), gaugeFields.get());
+std::shared_ptr<vector<FieldValue>> GaugeMetricProducer::getGaugeFields(const LogEvent& event) {
+    if (mFieldMatchers.size() > 0) {
+        std::shared_ptr<vector<FieldValue>> gaugeFields = std::make_shared<vector<FieldValue>>();
+        filterGaugeValues(mFieldMatchers, event.getValues(), gaugeFields.get());
+        return gaugeFields;
+    } else {
+        return std::make_shared<vector<FieldValue>>(event.getValues());
     }
-    return gaugeFields;
 }
 
 void GaugeMetricProducer::onDataPulled(const std::vector<std::shared_ptr<LogEvent>>& allData) {
@@ -292,6 +294,7 @@
         return;
     }
     uint64_t eventTimeNs = event.GetTimestampNs();
+    mTagId = event.GetTagId();
     if (eventTimeNs < mCurrentBucketStartTimeNs) {
         VLOG("Skip event due to late arrival: %lld vs %lld", (long long)eventTimeNs,
              (long long)mCurrentBucketStartTimeNs);
@@ -308,20 +311,18 @@
     if (hitGuardRailLocked(eventKey)) {
         return;
     }
-    GaugeAtom gaugeAtom;
-    gaugeAtom.mFields = getGaugeFields(event);
-    gaugeAtom.mTimestamps = eventTimeNs;
+    GaugeAtom gaugeAtom(getGaugeFields(event), eventTimeNs);
     (*mCurrentSlicedBucket)[eventKey].push_back(gaugeAtom);
     // Anomaly detection on gauge metric only works when there is one numeric
     // field specified.
     if (mAnomalyTrackers.size() > 0) {
         if (gaugeAtom.mFields->size() == 1) {
-            const DimensionsValue& dimensionsValue = gaugeAtom.mFields->begin()->second;
+            const Value& value = gaugeAtom.mFields->begin()->mValue;
             long gaugeVal = 0;
-            if (dimensionsValue.has_value_int()) {
-                gaugeVal = (long)dimensionsValue.value_int();
-            } else if (dimensionsValue.has_value_long()) {
-                gaugeVal = dimensionsValue.value_long();
+            if (value.getType() == INT) {
+                gaugeVal = (long)value.int_value;
+            } else if (value.getType() == LONG) {
+                gaugeVal = value.long_value;
             }
             for (auto& tracker : mAnomalyTrackers) {
                 tracker->detectAndDeclareAnomaly(eventTimeNs, mCurrentBucketNum, eventKey,
@@ -334,15 +335,15 @@
 void GaugeMetricProducer::updateCurrentSlicedBucketForAnomaly() {
     status_t err = NO_ERROR;
     for (const auto& slice : *mCurrentSlicedBucket) {
-        if (slice.second.empty() || slice.second.front().mFields->empty()) {
+        if (slice.second.empty()) {
             continue;
         }
-        const DimensionsValue& dimensionsValue = slice.second.front().mFields->begin()->second;
+        const Value& value = slice.second.front().mFields->front().mValue;
         long gaugeVal = 0;
-        if (dimensionsValue.has_value_int()) {
-            gaugeVal = (long)dimensionsValue.value_int();
-        } else if (dimensionsValue.has_value_long()) {
-            gaugeVal = dimensionsValue.value_long();
+        if (value.getType() == INT) {
+            gaugeVal = (long)value.int_value;
+        } else if (value.getType() == LONG) {
+            gaugeVal = value.long_value;
         }
         (*mCurrentSlicedBucketForAnomaly)[slice.first] = gaugeVal;
     }
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.h b/cmds/statsd/src/metrics/GaugeMetricProducer.h
index d5d34be..c3ae6ce 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.h
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.h
@@ -33,7 +33,10 @@
 namespace statsd {
 
 struct GaugeAtom {
-    std::shared_ptr<FieldValueMap> mFields;
+    GaugeAtom(std::shared_ptr<vector<FieldValue>> fields, int64_t timeNs)
+        : mFields(fields), mTimestamps(timeNs) {
+    }
+    std::shared_ptr<vector<FieldValue>> mFields;
     int64_t mTimestamps;
 };
 
@@ -87,7 +90,6 @@
 private:
     void onDumpReportLocked(const uint64_t dumpTimeNs,
                             android::util::ProtoOutputStream* protoOutput) override;
-    void onDumpReportLocked(const uint64_t dumpTimeNs, StatsLogReport* report) override;
 
     // for testing
     GaugeMetricProducer(const ConfigKey& key, const GaugeMetric& gaugeMetric,
@@ -113,6 +115,8 @@
 
     void pullLocked();
 
+    int mTagId;
+
     std::shared_ptr<StatsPullerManager> mStatsPullerManager;
     // tagId for pulled data. -1 if this is not pulled
     const int mPullTagId;
@@ -133,12 +137,12 @@
     void updateCurrentSlicedBucketForAnomaly();
 
     // Whitelist of fields to report. Empty means all are reported.
-    FieldFilter mFieldFilter;
+    std::vector<Matcher> mFieldMatchers;
 
     GaugeMetric::SamplingType mSamplingType;
 
     // apply a whitelist on the original input
-    std::shared_ptr<FieldValueMap> getGaugeFields(const LogEvent& event);
+    std::shared_ptr<vector<FieldValue>> getGaugeFields(const LogEvent& event);
 
     // Util function to check whether the specified dimension hits the guardrail.
     bool hitGuardRailLocked(const MetricDimensionKey& newKey);
diff --git a/cmds/statsd/src/metrics/MetricProducer.cpp b/cmds/statsd/src/metrics/MetricProducer.cpp
index 85e655b..beb9015 100644
--- a/cmds/statsd/src/metrics/MetricProducer.cpp
+++ b/cmds/statsd/src/metrics/MetricProducer.cpp
@@ -13,9 +13,10 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#include "MetricProducer.h"
 
-#include "dimension.h"
+#define DEBUG true  // STOPSHIP if true
+#include "Log.h"
+#include "MetricProducer.h"
 
 namespace android {
 namespace os {
@@ -35,9 +36,10 @@
 
     std::unordered_set<HashableDimensionKey> dimensionKeysInCondition;
     if (mConditionSliced) {
-        for (const auto& link : mConditionLinks) {
-            getDimensionKeysForCondition(event, link, &conditionKey[link.condition()]);
+        for (const auto& link : mMetric2ConditionLinks) {
+            getDimensionForCondition(event, link, &conditionKey[link.conditionId]);
         }
+
         auto conditionState =
             mWizard->query(mConditionTrackerIndex, conditionKey, mDimensionsInCondition,
                            &dimensionKeysInCondition);
@@ -46,20 +48,19 @@
         condition = mCondition;
     }
 
-    vector<DimensionsValue> dimensionInWhatValues;
-    if (mDimensionsInWhat.has_field() && mDimensionsInWhat.child_size() > 0) {
-        getDimensionKeys(event, mDimensionsInWhat, &dimensionInWhatValues);
+    vector<HashableDimensionKey> dimensionInWhatValues;
+    if (mDimensionsInWhat.size() > 0) {
+        filterValues(mDimensionsInWhat, event.getValues(), &dimensionInWhatValues);
     }
 
     if (dimensionInWhatValues.empty() && dimensionKeysInCondition.empty()) {
         onMatchedLogEventInternalLocked(
             matcherIndex, DEFAULT_METRIC_DIMENSION_KEY, conditionKey, condition, event);
     } else if (dimensionKeysInCondition.empty()) {
-        for (const DimensionsValue& whatValue : dimensionInWhatValues) {
-            onMatchedLogEventInternalLocked(
-                matcherIndex,
-                MetricDimensionKey(HashableDimensionKey(whatValue), DEFAULT_DIMENSION_KEY),
-                conditionKey, condition, event);
+        for (const HashableDimensionKey& whatValue : dimensionInWhatValues) {
+            onMatchedLogEventInternalLocked(matcherIndex,
+                                            MetricDimensionKey(whatValue, DEFAULT_DIMENSION_KEY),
+                                            conditionKey, condition, event);
         }
     } else if (dimensionInWhatValues.empty()) {
         for (const auto& conditionDimensionKey : dimensionKeysInCondition) {
@@ -69,12 +70,11 @@
                 conditionKey, condition, event);
         }
     } else {
-        for (const DimensionsValue& whatValue : dimensionInWhatValues) {
+        for (const auto& whatValue : dimensionInWhatValues) {
             for (const auto& conditionDimensionKey : dimensionKeysInCondition) {
                 onMatchedLogEventInternalLocked(
-                    matcherIndex,
-                    MetricDimensionKey(HashableDimensionKey(whatValue), conditionDimensionKey),
-                    conditionKey, condition, event);
+                        matcherIndex, MetricDimensionKey(whatValue, conditionDimensionKey),
+                        conditionKey, condition, event);
             }
         }
     }
diff --git a/cmds/statsd/src/metrics/MetricProducer.h b/cmds/statsd/src/metrics/MetricProducer.h
index 542dd8a..e8f8299 100644
--- a/cmds/statsd/src/metrics/MetricProducer.h
+++ b/cmds/statsd/src/metrics/MetricProducer.h
@@ -19,6 +19,7 @@
 
 #include <shared_mutex>
 
+#include "HashableDimensionKey.h"
 #include "anomaly/AnomalyTracker.h"
 #include "condition/ConditionWizard.h"
 #include "config/ConfigKey.h"
@@ -109,11 +110,6 @@
         std::lock_guard<std::mutex> lock(mMutex);
         return onDumpReportLocked(dumpTimeNs, protoOutput);
     }
-    // This method does not clear the past buckets.
-    void onDumpReport(const uint64_t dumpTimeNs, StatsLogReport* report) {
-        std::lock_guard<std::mutex> lock(mMutex);
-        return onDumpReportLocked(dumpTimeNs, report);
-    }
 
     void dumpStates(FILE* out, bool verbose) const {
         std::lock_guard<std::mutex> lock(mMutex);
@@ -150,7 +146,6 @@
     virtual void onSlicedConditionMayChangeLocked(const uint64_t eventTime) = 0;
     virtual void onDumpReportLocked(const uint64_t dumpTimeNs,
                                     android::util::ProtoOutputStream* protoOutput) = 0;
-    virtual void onDumpReportLocked(const uint64_t dumpTimeNs, StatsLogReport* report) = 0;
     virtual size_t byteSizeLocked() const = 0;
     virtual void dumpStatesLocked(FILE* out, bool verbose) const = 0;
 
@@ -203,10 +198,10 @@
 
     int mConditionTrackerIndex;
 
-    FieldMatcher mDimensionsInWhat;  // The dimensions_in_what defined in statsd_config
-    FieldMatcher mDimensionsInCondition;  // The dimensions_in_condition defined in statsd_config
+    vector<Matcher> mDimensionsInWhat;       // The dimensions_in_what defined in statsd_config
+    vector<Matcher> mDimensionsInCondition;  // The dimensions_in_condition defined in statsd_config
 
-    std::vector<MetricConditionLink> mConditionLinks;
+    std::vector<Metric2Condition> mMetric2ConditionLinks;
 
     std::vector<sp<AnomalyTracker>> mAnomalyTrackers;
 
diff --git a/cmds/statsd/src/metrics/MetricsManager.cpp b/cmds/statsd/src/metrics/MetricsManager.cpp
index 6c21b05..dd6735b 100644
--- a/cmds/statsd/src/metrics/MetricsManager.cpp
+++ b/cmds/statsd/src/metrics/MetricsManager.cpp
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#define DEBUG false  // STOPSHIP if true
+#define DEBUG true  // STOPSHIP if true
 #include "Log.h"
 #include "MetricsManager.h"
 #include "statslog.h"
@@ -151,14 +151,6 @@
     initLogSourceWhiteList();
 }
 
-void MetricsManager::onDumpReport(const uint64_t& dumpTimeStampNs, ConfigMetricsReport* report) {
-    for (const auto& producer : mAllMetricProducers) {
-        if (mNoReportMetricIds.find(producer->getMetricId()) == mNoReportMetricIds.end()) {
-            producer->onDumpReport(dumpTimeStampNs, report->add_metrics());
-        }
-    }
-}
-
 void MetricsManager::dumpStates(FILE* out, bool verbose) {
     fprintf(out, "ConfigKey %s, allowed source:", mConfigKey.ToString().c_str());
     {
@@ -173,9 +165,8 @@
     }
 }
 
-void MetricsManager::onDumpReport(ProtoOutputStream* protoOutput) {
+void MetricsManager::onDumpReport(const uint64_t dumpTimeStampNs, ProtoOutputStream* protoOutput) {
     VLOG("=========================Metric Reports Start==========================");
-    uint64_t dumpTimeStampNs = time(nullptr) * NS_PER_SEC;
     // one StatsLogReport per MetricProduer
     for (const auto& producer : mAllMetricProducers) {
         if (mNoReportMetricIds.find(producer->getMetricId()) == mNoReportMetricIds.end()) {
diff --git a/cmds/statsd/src/metrics/MetricsManager.h b/cmds/statsd/src/metrics/MetricsManager.h
index 2b30f44..d4f844f 100644
--- a/cmds/statsd/src/metrics/MetricsManager.h
+++ b/cmds/statsd/src/metrics/MetricsManager.h
@@ -70,8 +70,8 @@
     };
 
     // Config source owner can call onDumpReport() to get all the metrics collected.
-    virtual void onDumpReport(android::util::ProtoOutputStream* protoOutput);
-    virtual void onDumpReport(const uint64_t& dumpTimeStampNs, ConfigMetricsReport* report);
+    virtual void onDumpReport(const uint64_t dumpTimeNs,
+                              android::util::ProtoOutputStream* protoOutput);
 
     // Computes the total byte size of all metrics managed by a single config source.
     // Does not change the state.
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.cpp b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
index 7b1944c..45b4ac0 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
@@ -17,7 +17,6 @@
 #define DEBUG false  // STOPSHIP if true
 #include "Log.h"
 
-#include "dimension.h"
 #include "ValueMetricProducer.h"
 #include "guardrail/StatsdStats.h"
 #include "stats_log_util.h"
@@ -79,15 +78,28 @@
     }
 
     mBucketSizeNs = bucketSizeMills * 1000000;
-    mDimensionsInWhat = metric.dimensions_in_what();
-    mDimensionsInCondition = metric.dimensions_in_condition();
+    if (metric.has_dimensions_in_what()) {
+        translateFieldMatcher(metric.dimensions_in_what(), &mDimensionsInWhat);
+    }
+
+    if (metric.has_dimensions_in_condition()) {
+        translateFieldMatcher(metric.dimensions_in_condition(), &mDimensionsInCondition);
+    }
 
     if (metric.links().size() > 0) {
-        mConditionLinks.insert(mConditionLinks.begin(), metric.links().begin(),
-                               metric.links().end());
+        for (const auto& link : metric.links()) {
+            Metric2Condition mc;
+            mc.conditionId = link.condition();
+            translateFieldMatcher(link.fields_in_what(), &mc.metricFields);
+            translateFieldMatcher(link.fields_in_condition(), &mc.conditionFields);
+            mMetric2ConditionLinks.push_back(mc);
+        }
     }
-    mConditionSliced = (metric.links().size() > 0)||
-        (mDimensionsInCondition.has_field() && mDimensionsInCondition.child_size() > 0);
+
+    if (mValueField.child_size()) {
+        mField = mValueField.child(0).field();
+    }
+    mConditionSliced = (metric.links().size() > 0) || (mDimensionsInCondition.size() > 0);
 
     if (!metric.has_condition() && mPullTagId != -1) {
         VLOG("Setting up periodic pulling for %d", mPullTagId);
@@ -117,25 +129,6 @@
     VLOG("Metric %lld onSlicedConditionMayChange", (long long)mMetricId);
 }
 
-void ValueMetricProducer::onDumpReportLocked(const uint64_t dumpTimeNs, StatsLogReport* report) {
-    flushIfNeededLocked(dumpTimeNs);
-    report->set_metric_id(mMetricId);
-    auto value_metrics = report->mutable_value_metrics();
-    for (const auto& pair : mPastBuckets) {
-        ValueMetricData* metricData = value_metrics->add_data();
-        *metricData->mutable_dimensions_in_what() =
-            pair.first.getDimensionKeyInWhat().getDimensionsValue();
-        *metricData->mutable_dimensions_in_condition() =
-            pair.first.getDimensionKeyInCondition().getDimensionsValue();
-        for (const auto& bucket : pair.second) {
-            ValueBucketInfo* bucketInfo = metricData->add_bucket_info();
-            bucketInfo->set_start_bucket_nanos(bucket.mBucketStartNs);
-            bucketInfo->set_end_bucket_nanos(bucket.mBucketEndNs);
-            bucketInfo->set_value(bucket.mValue);
-        }
-    }
-}
-
 void ValueMetricProducer::onDumpReportLocked(const uint64_t dumpTimeNs,
                                              ProtoOutputStream* protoOutput) {
     VLOG("metric %lld dump report now...", (long long)mMetricId);
@@ -155,14 +148,12 @@
         // First fill dimension.
         long long dimensionToken = protoOutput->start(
             FIELD_TYPE_MESSAGE | FIELD_ID_DIMENSION_IN_WHAT);
-        writeDimensionsValueProtoToStream(
-            dimensionKey.getDimensionKeyInWhat().getDimensionsValue(), protoOutput);
+        writeDimensionToProto(dimensionKey.getDimensionKeyInWhat(), protoOutput);
         protoOutput->end(dimensionToken);
         if (dimensionKey.hasDimensionKeyInCondition()) {
             long long dimensionInConditionToken = protoOutput->start(
                     FIELD_TYPE_MESSAGE | FIELD_ID_DIMENSION_IN_CONDITION);
-            writeDimensionsValueProtoToStream(
-                dimensionKey.getDimensionKeyInCondition().getDimensionsValue(), protoOutput);
+            writeDimensionToProto(dimensionKey.getDimensionKeyInCondition(), protoOutput);
             protoOutput->end(dimensionInConditionToken);
         }
 
@@ -284,11 +275,11 @@
     }
     Interval& interval = mCurrentSlicedBucket[eventKey];
 
-    std::shared_ptr<FieldValueMap> valueFieldMap = getValueFields(event);
-    if (valueFieldMap->empty() || valueFieldMap->size() > 1) {
+    int error = 0;
+    const long value = event.GetLong(mField, &error);
+    if (error < 0) {
         return;
     }
-    const long value = getLongFromDimenValue(valueFieldMap->begin()->second);
 
     if (mPullTagId != -1) { // for pulled events
         if (mCondition == true) {
@@ -324,13 +315,6 @@
     }
 }
 
-std::shared_ptr<FieldValueMap> ValueMetricProducer::getValueFields(const LogEvent& event) {
-    std::shared_ptr<FieldValueMap> valueFields =
-        std::make_shared<FieldValueMap>(event.getFieldValueMap());
-    filterFields(mValueField, valueFields.get());
-    return valueFields;
-}
-
 void ValueMetricProducer::flushIfNeededLocked(const uint64_t& eventTimeNs) {
     uint64_t currentBucketEndTimeNs = getCurrentBucketEndTimeNs();
 
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.h b/cmds/statsd/src/metrics/ValueMetricProducer.h
index bf5b7df..6701a46 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.h
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.h
@@ -89,7 +89,6 @@
 private:
     void onDumpReportLocked(const uint64_t dumpTimeNs,
                             android::util::ProtoOutputStream* protoOutput) override;
-    void onDumpReportLocked(const uint64_t dumpTimeNs, StatsLogReport* report) override;
 
     // Internal interface to handle condition change.
     void onConditionChangedLocked(const bool conditionMet, const uint64_t eventTime) override;
@@ -120,6 +119,8 @@
     // tagId for pulled data. -1 if this is not pulled
     const int mPullTagId;
 
+    int mField;
+
     // internal state of a bucket.
     typedef struct {
         // Pulled data always come in pair of <start, end>. This holds the value
@@ -142,8 +143,6 @@
     // TODO: Add a lock to mPastBuckets.
     std::unordered_map<MetricDimensionKey, std::vector<ValueBucket>> mPastBuckets;
 
-    std::shared_ptr<FieldValueMap> getValueFields(const LogEvent& event);
-
     // Util function to check whether the specified dimension hits the guardrail.
     bool hitGuardRailLocked(const MetricDimensionKey& newKey);
 
diff --git a/cmds/statsd/src/metrics/duration_helper/DurationTracker.h b/cmds/statsd/src/metrics/duration_helper/DurationTracker.h
index 356a81c..8f236fa 100644
--- a/cmds/statsd/src/metrics/duration_helper/DurationTracker.h
+++ b/cmds/statsd/src/metrics/duration_helper/DurationTracker.h
@@ -62,7 +62,7 @@
 public:
     DurationTracker(const ConfigKey& key, const int64_t& id, const MetricDimensionKey& eventKey,
                     sp<ConditionWizard> wizard, int conditionIndex,
-                    const FieldMatcher& dimensionInCondition, bool nesting,
+                    const std::vector<Matcher>& dimensionInCondition, bool nesting,
                     uint64_t currentBucketStartNs, uint64_t currentBucketNum, uint64_t startTimeNs,
                     uint64_t bucketSizeNs, bool conditionSliced,
                     const std::vector<sp<DurationAnomalyTracker>>& anomalyTrackers)
@@ -182,7 +182,7 @@
 
     const int64_t mBucketSizeNs;
 
-    const FieldMatcher mDimensionInCondition;
+    const std::vector<Matcher>& mDimensionInCondition;
 
     const bool mNested;
 
diff --git a/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.cpp b/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.cpp
index c3bafc6..c29876b 100644
--- a/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.cpp
+++ b/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.cpp
@@ -27,7 +27,7 @@
 MaxDurationTracker::MaxDurationTracker(const ConfigKey& key, const int64_t& id,
                                        const MetricDimensionKey& eventKey,
                                        sp<ConditionWizard> wizard, int conditionIndex,
-                                       const FieldMatcher& dimensionInCondition, bool nesting,
+                                       const vector<Matcher>& dimensionInCondition, bool nesting,
                                        uint64_t currentBucketStartNs, uint64_t currentBucketNum,
                                        uint64_t startTimeNs, uint64_t bucketSizeNs,
                                        bool conditionSliced,
@@ -55,9 +55,7 @@
     // 1. Report the tuple count if the tuple count > soft limit
     if (mInfos.size() > StatsdStats::kDimensionKeySizeSoftLimit - 1) {
         size_t newTupleCount = mInfos.size() + 1;
-        StatsdStats::getInstance().noteMetricDimensionSize(
-            mConfigKey, hashMetricDimensionKey(mTrackerId, mEventKey),
-            newTupleCount);
+        StatsdStats::getInstance().noteMetricDimensionSize(mConfigKey, mTrackerId, newTupleCount);
         // 2. Don't add more tuples, we are above the allowed threshold. Drop the data.
         if (newTupleCount > StatsdStats::kDimensionKeySizeHardLimit) {
             ALOGE("MaxDurTracker %lld dropping data for dimension key %s",
@@ -229,10 +227,11 @@
         ConditionState conditionState = mWizard->query(
             mConditionTrackerIndex, pair.second.conditionKeys, mDimensionInCondition,
             &conditionDimensionKeySet);
-        bool conditionMet = (conditionState == ConditionState::kTrue) &&
-            (!mDimensionInCondition.has_field() ||
-             conditionDimensionKeySet.find(mEventKey.getDimensionKeyInCondition()) !=
-                conditionDimensionKeySet.end());
+        bool conditionMet =
+                (conditionState == ConditionState::kTrue) &&
+                (mDimensionInCondition.size() == 0 ||
+                 conditionDimensionKeySet.find(mEventKey.getDimensionKeyInCondition()) !=
+                         conditionDimensionKeySet.end());
         VLOG("key: %s, condition: %d", pair.first.c_str(), conditionMet);
         noteConditionChanged(pair.first, conditionMet, timestamp);
     }
diff --git a/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.h b/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.h
index fba4119..95863b6 100644
--- a/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.h
+++ b/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.h
@@ -30,7 +30,7 @@
 public:
     MaxDurationTracker(const ConfigKey& key, const int64_t& id, const MetricDimensionKey& eventKey,
                        sp<ConditionWizard> wizard, int conditionIndex,
-                       const FieldMatcher& dimensionInCondition, bool nesting,
+                       const std::vector<Matcher>& dimensionInCondition, bool nesting,
                        uint64_t currentBucketStartNs, uint64_t currentBucketNum,
                        uint64_t startTimeNs, uint64_t bucketSizeNs, bool conditionSliced,
                        const std::vector<sp<DurationAnomalyTracker>>& anomalyTrackers);
diff --git a/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.cpp b/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.cpp
index 85f7b7c..f583f91 100644
--- a/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.cpp
+++ b/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.cpp
@@ -26,7 +26,7 @@
 
 OringDurationTracker::OringDurationTracker(
         const ConfigKey& key, const int64_t& id, const MetricDimensionKey& eventKey,
-        sp<ConditionWizard> wizard, int conditionIndex, const FieldMatcher& dimensionInCondition,
+        sp<ConditionWizard> wizard, int conditionIndex, const vector<Matcher>& dimensionInCondition,
         bool nesting, uint64_t currentBucketStartNs, uint64_t currentBucketNum,
         uint64_t startTimeNs, uint64_t bucketSizeNs, bool conditionSliced,
         const vector<sp<DurationAnomalyTracker>>& anomalyTrackers)
@@ -53,9 +53,7 @@
     }
     if (mConditionKeyMap.size() > StatsdStats::kDimensionKeySizeSoftLimit - 1) {
         size_t newTupleCount = mConditionKeyMap.size() + 1;
-        StatsdStats::getInstance().noteMetricDimensionSize(
-            mConfigKey, hashMetricDimensionKey(mTrackerId, mEventKey),
-            newTupleCount);
+        StatsdStats::getInstance().noteMetricDimensionSize(mConfigKey, mTrackerId, newTupleCount);
         // 2. Don't add more tuples, we are above the allowed threshold. Drop the data.
         if (newTupleCount > StatsdStats::kDimensionKeySizeHardLimit) {
             ALOGE("OringDurTracker %lld dropping data for dimension key %s",
@@ -229,9 +227,9 @@
                 mWizard->query(mConditionTrackerIndex, mConditionKeyMap[key],
                                mDimensionInCondition, &conditionDimensionKeySet);
             if (conditionState != ConditionState::kTrue ||
-                (mDimensionInCondition.has_field() &&
+                (mDimensionInCondition.size() != 0 &&
                  conditionDimensionKeySet.find(mEventKey.getDimensionKeyInCondition()) ==
-                    conditionDimensionKeySet.end())) {
+                         conditionDimensionKeySet.end())) {
                 startedToPaused.push_back(*it);
                 it = mStarted.erase(it);
                 VLOG("Key %s started -> paused", key.c_str());
@@ -261,9 +259,9 @@
                 mWizard->query(mConditionTrackerIndex, mConditionKeyMap[key],
                                mDimensionInCondition, &conditionDimensionKeySet);
             if (conditionState == ConditionState::kTrue &&
-                (!mDimensionInCondition.has_field() ||
-                 conditionDimensionKeySet.find(mEventKey.getDimensionKeyInCondition())
-                    != conditionDimensionKeySet.end())) {
+                (mDimensionInCondition.size() == 0 ||
+                 conditionDimensionKeySet.find(mEventKey.getDimensionKeyInCondition()) !=
+                         conditionDimensionKeySet.end())) {
                 pausedToStarted.push_back(*it);
                 it = mPaused.erase(it);
                 VLOG("Key %s paused -> started", key.c_str());
diff --git a/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.h b/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.h
index 73e50e0..07c1329 100644
--- a/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.h
+++ b/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.h
@@ -29,8 +29,8 @@
 public:
     OringDurationTracker(const ConfigKey& key, const int64_t& id,
                          const MetricDimensionKey& eventKey, sp<ConditionWizard> wizard,
-                         int conditionIndex, const FieldMatcher& dimensionInCondition, bool nesting,
-                         uint64_t currentBucketStartNs, uint64_t currentBucketNum,
+                         int conditionIndex, const std::vector<Matcher>& dimensionInCondition,
+                         bool nesting, uint64_t currentBucketStartNs, uint64_t currentBucketNum,
                          uint64_t startTimeNs, uint64_t bucketSizeNs, bool conditionSliced,
                          const std::vector<sp<DurationAnomalyTracker>>& anomalyTrackers);
 
diff --git a/cmds/statsd/src/metrics/metrics_manager_util.cpp b/cmds/statsd/src/metrics/metrics_manager_util.cpp
index 205c8e4..769f46d 100644
--- a/cmds/statsd/src/metrics/metrics_manager_util.cpp
+++ b/cmds/statsd/src/metrics/metrics_manager_util.cpp
@@ -38,6 +38,22 @@
 namespace os {
 namespace statsd {
 
+namespace {
+
+bool hasLeafNode(const FieldMatcher& matcher) {
+    if (!matcher.has_field()) {
+        return false;
+    }
+    for (int i = 0; i < matcher.child_size(); ++i) {
+        if (hasLeafNode(matcher.child(i))) {
+            return true;
+        }
+    }
+    return true;
+}
+
+}  // namespace
+
 bool handleMetricWithLogTrackers(const int64_t what, const int metricIndex,
                                  const bool usedForDimension,
                                  const vector<sp<LogMatchingTracker>>& allAtomMatchers,
diff --git a/cmds/statsd/src/packages/UidMap.cpp b/cmds/statsd/src/packages/UidMap.cpp
index 0d7b722..691423e 100644
--- a/cmds/statsd/src/packages/UidMap.cpp
+++ b/cmds/statsd/src/packages/UidMap.cpp
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#define DEBUG false  // STOPSHIP if true
+#define DEBUG true  // STOPSHIP if true
 #include "Log.h"
 
 #include "guardrail/StatsdStats.h"
diff --git a/cmds/statsd/src/stats_log_util.cpp b/cmds/statsd/src/stats_log_util.cpp
index 6c61400..86c258b 100644
--- a/cmds/statsd/src/stats_log_util.cpp
+++ b/cmds/statsd/src/stats_log_util.cpp
@@ -16,9 +16,10 @@
 
 #include "stats_log_util.h"
 
+#include <logd/LogEvent.h>
+#include <utils/Log.h>
 #include <set>
 #include <stack>
-#include <utils/Log.h>
 
 using android::util::FIELD_COUNT_REPEATED;
 using android::util::FIELD_TYPE_BOOL;
@@ -42,6 +43,8 @@
 const int DIMENSIONS_VALUE_VALUE_FLOAT = 6;
 const int DIMENSIONS_VALUE_VALUE_TUPLE = 7;
 
+const int DIMENSIONS_VALUE_TUPLE_VALUE = 1;
+
 // for MessageValue Proto
 const int FIELD_ID_FIELD_VALUE_IN_MESSAGE_VALUE_PROTO = 1;
 
@@ -51,52 +54,79 @@
 const int FIELD_ID_TOTAL_PULL = 2;
 const int FIELD_ID_TOTAL_PULL_FROM_CACHE = 3;
 const int FIELD_ID_MIN_PULL_INTERVAL_SEC = 4;
+namespace {
 
-void writeDimensionsValueProtoToStream(const DimensionsValue& dimensionsValue,
-                                       ProtoOutputStream* protoOutput) {
-    if (!dimensionsValue.has_field()) {
+void writeDimensionToProtoHelper(const std::vector<FieldValue>& dims, size_t* index, int depth,
+                                 int prefix, ProtoOutputStream* protoOutput) {
+    size_t count = dims.size();
+    while (*index < count) {
+        const auto& dim = dims[*index];
+        const int valueDepth = dim.mField.getDepth();
+        const int valuePrefix = dim.mField.getPrefix(depth);
+        const int fieldNum = dim.mField.getPosAtDepth(depth);
+        if (valueDepth > 2) {
+            ALOGE("Depth > 2 not supported");
+            return;
+        }
+
+        if (depth == valueDepth && valuePrefix == prefix) {
+            long long token = protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED |
+                                                 DIMENSIONS_VALUE_TUPLE_VALUE);
+            protoOutput->write(FIELD_TYPE_INT32 | DIMENSIONS_VALUE_FIELD, fieldNum);
+            switch (dim.mValue.getType()) {
+                case INT:
+                    protoOutput->write(FIELD_TYPE_INT32 | DIMENSIONS_VALUE_VALUE_INT,
+                                       dim.mValue.int_value);
+                    break;
+                case LONG:
+                    protoOutput->write(FIELD_TYPE_INT64 | DIMENSIONS_VALUE_VALUE_LONG,
+                                       (long long)dim.mValue.long_value);
+                    break;
+                case FLOAT:
+                    protoOutput->write(FIELD_TYPE_FLOAT | DIMENSIONS_VALUE_VALUE_FLOAT,
+                                       dim.mValue.float_value);
+                    break;
+                case STRING:
+                    protoOutput->write(FIELD_TYPE_STRING | DIMENSIONS_VALUE_VALUE_STR,
+                                       dim.mValue.str_value);
+                    break;
+                default:
+                    break;
+            }
+            if (token != 0) {
+                protoOutput->end(token);
+            }
+            (*index)++;
+        } else if (valueDepth > depth && valuePrefix == prefix) {
+            // Writing the sub tree
+            long long dimensionToken = protoOutput->start(
+                    FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | DIMENSIONS_VALUE_TUPLE_VALUE);
+            protoOutput->write(FIELD_TYPE_INT32 | DIMENSIONS_VALUE_FIELD, fieldNum);
+            long long tupleToken =
+                    protoOutput->start(FIELD_TYPE_MESSAGE | DIMENSIONS_VALUE_VALUE_TUPLE);
+            writeDimensionToProtoHelper(dims, index, valueDepth, dim.mField.getPrefix(valueDepth),
+                                        protoOutput);
+            protoOutput->end(tupleToken);
+            protoOutput->end(dimensionToken);
+        } else {
+            // Done with the prev sub tree
+            return;
+        }
+    }
+}
+
+}  // namespace
+
+void writeDimensionToProto(const HashableDimensionKey& dimension, ProtoOutputStream* protoOutput) {
+    if (dimension.getValues().size() == 0) {
         return;
     }
-    protoOutput->write(FIELD_TYPE_INT32 | DIMENSIONS_VALUE_FIELD, dimensionsValue.field());
-    switch (dimensionsValue.value_case()) {
-        case DimensionsValue::ValueCase::kValueStr:
-            protoOutput->write(FIELD_TYPE_STRING | DIMENSIONS_VALUE_VALUE_STR,
-                dimensionsValue.value_str());
-            break;
-        case DimensionsValue::ValueCase::kValueInt:
-            protoOutput->write(FIELD_TYPE_INT32 | DIMENSIONS_VALUE_VALUE_INT,
-                dimensionsValue.value_int());
-            break;
-        case DimensionsValue::ValueCase::kValueLong:
-            protoOutput->write(FIELD_TYPE_INT64 | DIMENSIONS_VALUE_VALUE_LONG,
-                dimensionsValue.value_long());
-            break;
-        case DimensionsValue::ValueCase::kValueBool:
-            protoOutput->write(FIELD_TYPE_BOOL | DIMENSIONS_VALUE_VALUE_BOOL,
-                dimensionsValue.value_bool());
-            break;
-        case DimensionsValue::ValueCase::kValueFloat:
-            protoOutput->write(FIELD_TYPE_FLOAT | DIMENSIONS_VALUE_VALUE_FLOAT,
-                dimensionsValue.value_float());
-            break;
-        case DimensionsValue::ValueCase::kValueTuple:
-            {
-                long long tupleToken = protoOutput->start(
-                    FIELD_TYPE_MESSAGE | DIMENSIONS_VALUE_VALUE_TUPLE);
-                for (int i = 0; i < dimensionsValue.value_tuple().dimensions_value_size(); ++i) {
-                    long long token = protoOutput->start(
-                        FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED
-                        | FIELD_ID_FIELD_VALUE_IN_MESSAGE_VALUE_PROTO);
-                    writeDimensionsValueProtoToStream(
-                        dimensionsValue.value_tuple().dimensions_value(i), protoOutput);
-                    protoOutput->end(token);
-                }
-                protoOutput->end(tupleToken);
-            }
-            break;
-        default:
-            break;
-    }
+    protoOutput->write(FIELD_TYPE_INT32 | DIMENSIONS_VALUE_FIELD,
+                       dimension.getValues()[0].mField.getTag());
+    long long topToken = protoOutput->start(FIELD_TYPE_MESSAGE | DIMENSIONS_VALUE_VALUE_TUPLE);
+    size_t index = 0;
+    writeDimensionToProtoHelper(dimension.getValues(), &index, 0, 0, protoOutput);
+    protoOutput->end(topToken);
 }
 
 // for Field Proto
@@ -104,133 +134,92 @@
 const int FIELD_POSITION_INDEX = 2;
 const int FIELD_CHILD = 3;
 
-void writeFieldProtoToStream(
-    const Field& field, util::ProtoOutputStream* protoOutput) {
-    if (!field.has_field()) {
-        return;
-    }
-    protoOutput->write(FIELD_TYPE_INT32 | FIELD_FIELD, field.field());
-    if (field.has_position_index()) {
-      protoOutput->write(FIELD_TYPE_INT32 | FIELD_POSITION_INDEX, field.position_index());
-    }
-    for (int i = 0; i < field.child_size(); ++i) {
-        long long childToken = protoOutput->start(
-            FIELD_TYPE_MESSAGE| FIELD_COUNT_REPEATED | FIELD_CHILD);
-        writeFieldProtoToStream(field.child(i), protoOutput);
-        protoOutput->end(childToken);
-    }
-}
-
-namespace {
-
-void addOrUpdateChildrenMap(
-    const Field& root,
-    const Field& node,
-    std::map<Field, std::set<Field, FieldCmp>, FieldCmp> *childrenMap) {
-    Field parentNode = root;
-    if (node.has_position_index()) {
-        appendLeaf(&parentNode, node.field(), node.position_index());
-    } else {
-        appendLeaf(&parentNode, node.field());
-    }
-    if (childrenMap->find(parentNode) == childrenMap->end()) {
-        childrenMap->insert(std::make_pair(parentNode, std::set<Field, FieldCmp>{}));
-    }
-    auto it = childrenMap->find(parentNode);
-    for (int i = 0; i < node.child_size(); ++i) {
-        auto child = node.child(i);
-        Field childNode = parentNode;
-        if (child.has_position_index()) {
-            appendLeaf(&childNode, child.field(), child.position_index());
-        } else {
-            appendLeaf(&childNode, child.field());
+// Supported Atoms format
+// XYZ_Atom {
+//     repeated SubMsg field_1 = 1;
+//     SubMsg2 field_2 = 2;
+//     int32/float/string/int63 field_3 = 3;
+// }
+// logd's msg format, doesn't allow us to distinguish between the 2 cases below
+// Case (1):
+// Atom {
+//   SubMsg {
+//     int i = 1;
+//     int j = 2;
+//   }
+//   repeated SubMsg
+// }
+//
+// and case (2):
+// Atom {
+//   SubMsg {
+//     repeated int i = 1;
+//     repeated int j = 2;
+//   }
+//   optional SubMsg = 1;
+// }
+//
+//
+void writeFieldValueTreeToStreamHelper(const std::vector<FieldValue>& dims, size_t* index,
+                                       int depth, int prefix, ProtoOutputStream* protoOutput) {
+    size_t count = dims.size();
+    while (*index < count) {
+        const auto& dim = dims[*index];
+        const int valueDepth = dim.mField.getDepth();
+        const int valuePrefix = dim.mField.getPrefix(depth);
+        const int fieldNum = dim.mField.getPosAtDepth(depth);
+        if (valueDepth > 2) {
+            ALOGE("Depth > 2 not supported");
+            return;
         }
-        it->second.insert(childNode);
-        addOrUpdateChildrenMap(parentNode, child, childrenMap);
+
+        if (depth == valueDepth && valuePrefix == prefix) {
+            switch (dim.mValue.getType()) {
+                case INT:
+                    protoOutput->write(FIELD_TYPE_INT32 | fieldNum, dim.mValue.int_value);
+                    break;
+                case LONG:
+                    protoOutput->write(FIELD_TYPE_INT64 | fieldNum,
+                                       (long long)dim.mValue.long_value);
+                    break;
+                case FLOAT:
+                    protoOutput->write(FIELD_TYPE_FLOAT | fieldNum, dim.mValue.float_value);
+                    break;
+                case STRING:
+                    protoOutput->write(FIELD_TYPE_STRING | fieldNum, dim.mValue.str_value);
+                    break;
+            }
+            (*index)++;
+        } else if (valueDepth > depth && valuePrefix == prefix) {
+            // Writing the sub tree
+            long long msg_token = 0;
+            if (valueDepth == depth + 2) {
+                msg_token =
+                        protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | fieldNum);
+            } else if (valueDepth == depth + 1) {
+                msg_token = protoOutput->start(FIELD_TYPE_MESSAGE | fieldNum);
+            }
+            // Directly jump to the leaf value because the repeated position field is implied
+            // by the position of the sub msg in the parent field.
+            writeFieldValueTreeToStreamHelper(dims, index, valueDepth,
+                                              dim.mField.getPrefix(valueDepth), protoOutput);
+            if (msg_token != 0) {
+                protoOutput->end(msg_token);
+            }
+        } else {
+            // Done with the prev sub tree
+            return;
+        }
     }
 }
 
-void addOrUpdateChildrenMap(
-    const Field& field,
-    std::map<Field, std::set<Field, FieldCmp>, FieldCmp> *childrenMap) {
-    Field root;
-    addOrUpdateChildrenMap(root, field, childrenMap);
-}
-
-} // namespace
-
-void writeFieldValueTreeToStream(const FieldValueMap &fieldValueMap,
+void writeFieldValueTreeToStream(int tagId, const std::vector<FieldValue>& values,
                                  util::ProtoOutputStream* protoOutput) {
-    std::map<Field, std::set<Field, FieldCmp>, FieldCmp> childrenMap;
-    // Rebuild the field tree.
-    for (auto it = fieldValueMap.begin(); it != fieldValueMap.end(); ++it) {
-        addOrUpdateChildrenMap(it->first, &childrenMap);
-    }
-    std::stack<std::pair<long long, Field>> tokenStack;
-    // Iterate over the node tree to fill the Atom proto.
-    for (auto it = childrenMap.begin(); it != childrenMap.end(); ++it) {
-        const Field* nodeLeaf = getSingleLeaf(&it->first);
-        const int fieldNum = nodeLeaf->field();
-        while (!tokenStack.empty()) {
-            auto currentMsgNode = tokenStack.top().second;
-            auto currentMsgNodeChildrenIt = childrenMap.find(currentMsgNode);
-            if (currentMsgNodeChildrenIt->second.find(it->first) ==
-                currentMsgNodeChildrenIt->second.end()) {
-                protoOutput->end(tokenStack.top().first);
-                tokenStack.pop();
-            } else {
-                break;
-            }
-        }
-        if (it->second.size() == 0) {
-            auto itValue = fieldValueMap.find(it->first);
-            if (itValue != fieldValueMap.end()) {
-                const DimensionsValue& value = itValue->second;
-                switch (value.value_case()) {
-                        case DimensionsValue::ValueCase::kValueStr:
-                            protoOutput->write(FIELD_TYPE_STRING | fieldNum,
-                                value.value_str());
-                            break;
-                        case DimensionsValue::ValueCase::kValueInt:
-                            protoOutput->write(FIELD_TYPE_INT32 | fieldNum,
-                                value.value_int());
-                            break;
-                        case DimensionsValue::ValueCase::kValueLong:
-                            protoOutput->write(FIELD_TYPE_INT64 | fieldNum,
-                                value.value_long());
-                            break;
-                        case DimensionsValue::ValueCase::kValueBool:
-                            protoOutput->write(FIELD_TYPE_BOOL | fieldNum,
-                                value.value_bool());
-                            break;
-                        case DimensionsValue::ValueCase::kValueFloat:
-                            protoOutput->write(FIELD_TYPE_FLOAT | fieldNum,
-                                value.value_float());
-                            break;
-                        // This would not happen as the node has no child.
-                        case DimensionsValue::ValueCase::kValueTuple:
-                            break;
-                        default:
-                            break;
-                }
-            } else {
-                ALOGE("Leaf node value not found. This should never happen.");
-            }
-        } else {
-            long long token;
-            if (nodeLeaf->has_position_index()) {
-                token = protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | fieldNum);
-            } else {
-                token = protoOutput->start(FIELD_TYPE_MESSAGE | fieldNum);
-            }
-            tokenStack.push(std::make_pair(token, it->first));
-        }
-    }
+    long long atomToken = protoOutput->start(FIELD_TYPE_MESSAGE | tagId);
 
-    while (!tokenStack.empty()) {
-        protoOutput->end(tokenStack.top().first);
-        tokenStack.pop();
-    }
+    size_t index = 0;
+    writeFieldValueTreeToStreamHelper(values, &index, 0, 0, protoOutput);
+    protoOutput->end(atomToken);
 }
 
 int64_t TimeUnitToBucketSizeInMillis(TimeUnit unit) {
diff --git a/cmds/statsd/src/stats_log_util.h b/cmds/statsd/src/stats_log_util.h
index cee9200..6583f57 100644
--- a/cmds/statsd/src/stats_log_util.h
+++ b/cmds/statsd/src/stats_log_util.h
@@ -17,7 +17,8 @@
 #pragma once
 
 #include <android/util/ProtoOutputStream.h>
-#include "field_util.h"
+#include "FieldValue.h"
+#include "HashableDimensionKey.h"
 #include "frameworks/base/cmds/statsd/src/stats_log.pb.h"
 #include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
 #include "guardrail/StatsdStats.h"
@@ -26,16 +27,10 @@
 namespace os {
 namespace statsd {
 
-// Helper function to write DimensionsValue proto to ProtoOutputStream.
-void writeDimensionsValueProtoToStream(const DimensionsValue& fieldValue,
-                                       util::ProtoOutputStream* protoOutput);
-
-// Helper function to write Field proto to ProtoOutputStream.
-void writeFieldProtoToStream(const Field& field, util::ProtoOutputStream* protoOutput);
-
-// Helper function to construct the field value tree and write to ProtoOutputStream
-void writeFieldValueTreeToStream(const FieldValueMap& fieldValueMap,
+void writeFieldValueTreeToStream(int tagId, const std::vector<FieldValue>& values,
                                  util::ProtoOutputStream* protoOutput);
+void writeDimensionToProto(const HashableDimensionKey& dimension,
+                           util::ProtoOutputStream* protoOutput);
 
 // Convert the TimeUnit enum to the bucket size in millis.
 int64_t TimeUnitToBucketSizeInMillis(TimeUnit unit);
diff --git a/cmds/statsd/src/statsd_internal.proto b/cmds/statsd/src/statsd_internal.proto
deleted file mode 100644
index 25aacee..0000000
--- a/cmds/statsd/src/statsd_internal.proto
+++ /dev/null
@@ -1,29 +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.
- */
-
-syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
-
-package android.os.statsd;
-
-option java_package = "com.android.os";
-option java_outer_classname = "StatsdInternalProto";
-
-message Field {
-  optional int32 field = 1;
-  optional int32 position_index = 2 [default = -1];
-  repeated Field child = 3;
-}
diff --git a/cmds/statsd/src/subscriber/SubscriberReporter.cpp b/cmds/statsd/src/subscriber/SubscriberReporter.cpp
index 3af684f..9f68fc4 100644
--- a/cmds/statsd/src/subscriber/SubscriberReporter.cpp
+++ b/cmds/statsd/src/subscriber/SubscriberReporter.cpp
@@ -98,50 +98,66 @@
         ALOGW("Failed to send subscriber broadcast: could not access StatsCompanionService.");
         return;
     }
-    mStatsCompanionService->sendSubscriberBroadcast(intentSender,
-                                                    configKey.GetUid(),
-                                                    configKey.GetId(),
-                                                    subscription.id(),
-                                                    subscription.rule_id(),
-                                                    protoToStatsDimensionsValue(dimKey));
+    mStatsCompanionService->sendSubscriberBroadcast(
+            intentSender, configKey.GetUid(), configKey.GetId(), subscription.id(),
+            subscription.rule_id(), getStatsDimensionsValue(dimKey.getDimensionKeyInWhat()));
 }
 
-StatsDimensionsValue SubscriberReporter::protoToStatsDimensionsValue(
-        const MetricDimensionKey& dimKey) {
-    return protoToStatsDimensionsValue(dimKey.getDimensionKeyInWhat().getDimensionsValue());
-}
-
-StatsDimensionsValue SubscriberReporter::protoToStatsDimensionsValue(
-        const DimensionsValue& protoDimsVal) {
-    int32_t field = protoDimsVal.field();
-
-    switch (protoDimsVal.value_case()) {
-        case DimensionsValue::ValueCase::kValueStr:
-            return StatsDimensionsValue(field, String16(protoDimsVal.value_str().c_str()));
-        case DimensionsValue::ValueCase::kValueInt:
-            return StatsDimensionsValue(field, static_cast<int32_t>(protoDimsVal.value_int()));
-        case DimensionsValue::ValueCase::kValueLong:
-            return StatsDimensionsValue(field, static_cast<int64_t>(protoDimsVal.value_long()));
-        case DimensionsValue::ValueCase::kValueBool:
-            return StatsDimensionsValue(field, static_cast<bool>(protoDimsVal.value_bool()));
-        case DimensionsValue::ValueCase::kValueFloat:
-            return StatsDimensionsValue(field, static_cast<float>(protoDimsVal.value_float()));
-        case DimensionsValue::ValueCase::kValueTuple:
-            {
-                int sz = protoDimsVal.value_tuple().dimensions_value_size();
-                std::vector<StatsDimensionsValue> sdvVec(sz);
-                for (int i = 0; i < sz; i++) {
-                    sdvVec[i] = protoToStatsDimensionsValue(
-                            protoDimsVal.value_tuple().dimensions_value(i));
-                }
-                return StatsDimensionsValue(field, sdvVec);
+void getStatsDimensionsValueHelper(const std::vector<FieldValue>& dims, size_t* index, int depth,
+                                   int prefix, vector<StatsDimensionsValue>* output) {
+    size_t count = dims.size();
+    while (*index < count) {
+        const auto& dim = dims[*index];
+        const int valueDepth = dim.mField.getDepth();
+        const int valuePrefix = dim.mField.getPrefix(depth);
+        if (valueDepth > 2) {
+            ALOGE("Depth > 2 not supported");
+            return;
+        }
+        if (depth == valueDepth && valuePrefix == prefix) {
+            switch (dim.mValue.getType()) {
+                case INT:
+                    output->push_back(StatsDimensionsValue(dim.mField.getPosAtDepth(depth),
+                                                           dim.mValue.int_value));
+                    break;
+                case LONG:
+                    output->push_back(StatsDimensionsValue(dim.mField.getPosAtDepth(depth),
+                                                           dim.mValue.long_value));
+                    break;
+                case FLOAT:
+                    output->push_back(StatsDimensionsValue(dim.mField.getPosAtDepth(depth),
+                                                           dim.mValue.float_value));
+                    break;
+                case STRING:
+                    output->push_back(StatsDimensionsValue(dim.mField.getPosAtDepth(depth),
+                                                           String16(dim.mValue.str_value.c_str())));
+                    break;
+                default:
+                    break;
             }
-        default:
-            ALOGW("protoToStatsDimensionsValue failed: illegal type.");
-            return StatsDimensionsValue();
+            (*index)++;
+        } else if (valueDepth > depth && valuePrefix == prefix) {
+            vector<StatsDimensionsValue> childOutput;
+            getStatsDimensionsValueHelper(dims, index, depth + 1, dim.mField.getPrefix(depth + 1),
+                                          &childOutput);
+            output->push_back(StatsDimensionsValue(dim.mField.getPosAtDepth(depth), childOutput));
+        } else {
+            return;
+        }
     }
 }
 
+StatsDimensionsValue SubscriberReporter::getStatsDimensionsValue(const HashableDimensionKey& dim) {
+    if (dim.getValues().size() == 0) {
+        return StatsDimensionsValue();
+    }
+
+    vector<StatsDimensionsValue> fields;
+    size_t index = 0;
+    getStatsDimensionsValueHelper(dim.getValues(), &index, 0, 0, &fields);
+    return StatsDimensionsValue(dim.getValues()[0].mField.getTag(), fields);
+}
+
 }  // namespace statsd
 }  // namespace os
 }  // namespace android
diff --git a/cmds/statsd/src/subscriber/SubscriberReporter.h b/cmds/statsd/src/subscriber/SubscriberReporter.h
index 13fc7fd..c7d1a5b 100644
--- a/cmds/statsd/src/subscriber/SubscriberReporter.h
+++ b/cmds/statsd/src/subscriber/SubscriberReporter.h
@@ -82,6 +82,8 @@
                                   const Subscription& subscription,
                                   const MetricDimensionKey& dimKey) const;
 
+    static StatsDimensionsValue getStatsDimensionsValue(const HashableDimensionKey& dim);
+
 private:
     SubscriberReporter() {};
 
@@ -102,14 +104,6 @@
                              const ConfigKey& configKey,
                              const Subscription& subscription,
                              const MetricDimensionKey& dimKey) const;
-
-    /** Converts a stats_log.proto DimensionsValue to a StatsDimensionsValue. */
-    static StatsDimensionsValue protoToStatsDimensionsValue(
-            const DimensionsValue& protoDimsVal);
-
-    /** Converts a HashableDimensionKey to a StatsDimensionsValue. */
-    static StatsDimensionsValue protoToStatsDimensionsValue(
-            const MetricDimensionKey& dimKey);
 };
 
 }  // namespace statsd
diff --git a/cmds/statsd/tests/FieldValue_test.cpp b/cmds/statsd/tests/FieldValue_test.cpp
new file mode 100644
index 0000000..f1ad0c8
--- /dev/null
+++ b/cmds/statsd/tests/FieldValue_test.cpp
@@ -0,0 +1,350 @@
+/*
+ * 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/logd/LogEvent.h"
+#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
+#include "matchers/matcher_util.h"
+#include "stats_log_util.h"
+#include "stats_util.h"
+#include "subscriber/SubscriberReporter.h"
+
+#ifdef __ANDROID__
+
+namespace android {
+namespace os {
+namespace statsd {
+
+TEST(AtomMatcherTest, TestFieldTranslation) {
+    FieldMatcher matcher1;
+    matcher1.set_field(10);
+    FieldMatcher* child = matcher1.add_child();
+    child->set_field(1);
+    child->set_position(Position::ANY);
+
+    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)0x2010001, matcher12.mMatcher.getField());
+    EXPECT_EQ((int32_t)0xff7f007f, matcher12.mMask);
+}
+
+TEST(AtomMatcherTest, TestFilter) {
+    FieldMatcher matcher1;
+    matcher1.set_field(10);
+    FieldMatcher* child = matcher1.add_child();
+    child->set_field(1);
+    child->set_position(Position::ANY);
+
+    child = child->add_child();
+    child->set_field(1);
+
+    child = matcher1.add_child();
+    child->set_field(2);
+
+    vector<Matcher> matchers;
+    translateFieldMatcher(matcher1, &matchers);
+
+    AttributionNode attribution_node1;
+    attribution_node1.set_uid(1111);
+    attribution_node1.set_tag("location1");
+
+    AttributionNode attribution_node2;
+    attribution_node2.set_uid(2222);
+    attribution_node2.set_tag("location2");
+
+    AttributionNode attribution_node3;
+    attribution_node3.set_uid(3333);
+    attribution_node3.set_tag("location3");
+    std::vector<AttributionNode> attribution_nodes = {attribution_node1, attribution_node2,
+                                                      attribution_node3};
+
+    // Set up the event
+    LogEvent event(10, 12345);
+    event.write(attribution_nodes);
+    event.write("some value");
+    // Convert to a LogEvent
+    event.init();
+    vector<HashableDimensionKey> output;
+
+    filterValues(matchers, event.getValues(), &output);
+
+    EXPECT_EQ((size_t)(3), output.size());
+
+    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);
+
+    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);
+
+    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);
+}
+
+TEST(AtomMatcherTest, TestSubDimension) {
+    HashableDimensionKey dim;
+
+    int pos1[] = {1, 1, 1};
+    int pos2[] = {1, 1, 2};
+    int pos3[] = {1, 1, 3};
+    int pos4[] = {2, 0, 0};
+    Field field1(10, pos1, 2);
+    Field field2(10, pos2, 2);
+
+    Field field3(10, pos3, 2);
+    Field field4(10, pos4, 0);
+
+    Value value1((int32_t)10025);
+    Value value2("tag");
+
+    Value value11((int32_t)10026);
+    Value value22("tag2");
+
+    dim.addValue(FieldValue(field1, value1));
+    dim.addValue(FieldValue(field2, value2));
+
+    HashableDimensionKey subDim1;
+    subDim1.addValue(FieldValue(field1, value1));
+
+    HashableDimensionKey subDim2;
+    subDim1.addValue(FieldValue(field2, value2));
+
+    EXPECT_TRUE(dim.contains(dim));
+    EXPECT_TRUE(dim.contains(subDim1));
+    EXPECT_TRUE(dim.contains(subDim2));
+
+    HashableDimensionKey subDim3;
+    subDim3.addValue(FieldValue(field1, value11));
+    EXPECT_FALSE(dim.contains(subDim3));
+
+    HashableDimensionKey subDim4;
+    // Empty dimension is always a sub dimension of other dimensions
+    EXPECT_TRUE(dim.contains(subDim4));
+}
+
+TEST(AtomMatcherTest, TestMetric2ConditionLink) {
+    AttributionNode attribution_node1;
+    attribution_node1.set_uid(1111);
+    attribution_node1.set_tag("location1");
+
+    AttributionNode attribution_node2;
+    attribution_node2.set_uid(2222);
+    attribution_node2.set_tag("location2");
+
+    AttributionNode attribution_node3;
+    attribution_node3.set_uid(3333);
+    attribution_node3.set_tag("location3");
+    std::vector<AttributionNode> attribution_nodes = {attribution_node1, attribution_node2,
+                                                      attribution_node3};
+
+    // Set up the event
+    LogEvent event(10, 12345);
+    event.write(attribution_nodes);
+    event.write("some value");
+    // Convert to a LogEvent
+    event.init();
+
+    FieldMatcher whatMatcher;
+    whatMatcher.set_field(10);
+    FieldMatcher* child11 = whatMatcher.add_child();
+    child11->set_field(1);
+    child11->set_position(Position::ANY);
+    child11 = child11->add_child();
+    child11->set_field(1);
+
+    FieldMatcher conditionMatcher;
+    conditionMatcher.set_field(27);
+    FieldMatcher* child2 = conditionMatcher.add_child();
+    child2->set_field(2);
+    child2->set_position(Position::LAST);
+
+    child2 = child2->add_child();
+    child2->set_field(2);
+
+    Metric2Condition link;
+
+    translateFieldMatcher(whatMatcher, &link.metricFields);
+    translateFieldMatcher(conditionMatcher, &link.conditionFields);
+
+    EXPECT_EQ((size_t)1, link.metricFields.size());
+    EXPECT_EQ((int32_t)0x02010001, link.metricFields[0].mMatcher.getField());
+    EXPECT_EQ((int32_t)0xff7f007f, link.metricFields[0].mMask);
+    EXPECT_EQ((int32_t)10, link.metricFields[0].mMatcher.getTag());
+
+    EXPECT_EQ((size_t)1, link.conditionFields.size());
+    EXPECT_EQ((int32_t)0x02028002, link.conditionFields[0].mMatcher.getField());
+    EXPECT_EQ((int32_t)0xff7f807f, link.conditionFields[0].mMask);
+    EXPECT_EQ((int32_t)27, link.conditionFields[0].mMatcher.getTag());
+}
+
+TEST(AtomMatcherTest, TestSubscriberDimensionWrite) {
+    HashableDimensionKey dim;
+
+    int pos1[] = {1, 1, 1};
+    int pos2[] = {1, 1, 2};
+    int pos3[] = {1, 1, 3};
+    int pos4[] = {2, 0, 0};
+
+    Field field1(10, pos1, 2);
+    Field field2(10, pos2, 2);
+    Field field3(10, pos3, 2);
+    Field field4(10, pos4, 0);
+
+    Value value1((int32_t)10025);
+    Value value2("tag");
+    Value value3((int32_t)987654);
+    Value value4((int32_t)99999);
+
+    dim.addValue(FieldValue(field1, value1));
+    dim.addValue(FieldValue(field2, value2));
+    dim.addValue(FieldValue(field3, value3));
+    dim.addValue(FieldValue(field4, value4));
+
+    SubscriberReporter::getStatsDimensionsValue(dim);
+    // TODO: can't test anything here because SubscriberReport class doesn't have any read api.
+}
+
+TEST(AtomMatcherTest, TestWriteDimensionToProto) {
+    HashableDimensionKey dim;
+    int pos1[] = {1, 1, 1};
+    int pos2[] = {1, 1, 2};
+    int pos3[] = {1, 1, 3};
+    int pos4[] = {2, 0, 0};
+    Field field1(10, pos1, 2);
+    Field field2(10, pos2, 2);
+    Field field3(10, pos3, 2);
+    Field field4(10, pos4, 0);
+
+    Value value1((int32_t)10025);
+    Value value2("tag");
+    Value value3((int32_t)987654);
+    Value value4((int32_t)99999);
+
+    dim.addValue(FieldValue(field1, value1));
+    dim.addValue(FieldValue(field2, value2));
+    dim.addValue(FieldValue(field3, value3));
+    dim.addValue(FieldValue(field4, value4));
+
+    android::util::ProtoOutputStream protoOut;
+    writeDimensionToProto(dim, &protoOut);
+
+    vector<uint8_t> outData;
+    outData.resize(protoOut.size());
+    size_t pos = 0;
+    auto iter = protoOut.data();
+    while (iter.readBuffer() != NULL) {
+        size_t toRead = iter.currentToRead();
+        std::memcpy(&(outData[pos]), iter.readBuffer(), toRead);
+        pos += toRead;
+        iter.rp()->move(toRead);
+    }
+
+    DimensionsValue result;
+    EXPECT_EQ(true, result.ParseFromArray(&outData[0], outData.size()));
+    EXPECT_EQ(10, result.field());
+    EXPECT_EQ(DimensionsValue::ValueCase::kValueTuple, result.value_case());
+    EXPECT_EQ(2, result.value_tuple().dimensions_value_size());
+
+    const auto& dim1 = result.value_tuple().dimensions_value(0);
+    EXPECT_EQ(DimensionsValue::ValueCase::kValueTuple, dim1.value_case());
+    EXPECT_EQ(3, dim1.value_tuple().dimensions_value_size());
+
+    const auto& dim11 = dim1.value_tuple().dimensions_value(0);
+    EXPECT_EQ(DimensionsValue::ValueCase::kValueInt, dim11.value_case());
+    EXPECT_EQ(10025, dim11.value_int());
+
+    const auto& dim12 = dim1.value_tuple().dimensions_value(1);
+    EXPECT_EQ(DimensionsValue::ValueCase::kValueStr, dim12.value_case());
+    EXPECT_EQ("tag", dim12.value_str());
+
+    const auto& dim13 = dim1.value_tuple().dimensions_value(2);
+    EXPECT_EQ(DimensionsValue::ValueCase::kValueInt, dim13.value_case());
+    EXPECT_EQ(987654, dim13.value_int());
+
+    const auto& dim2 = result.value_tuple().dimensions_value(1);
+    EXPECT_EQ(DimensionsValue::ValueCase::kValueInt, dim2.value_case());
+    EXPECT_EQ(99999, dim2.value_int());
+}
+
+TEST(AtomMatcherTest, TestWriteAtomToProto) {
+    AttributionNode attribution_node1;
+    attribution_node1.set_uid(1111);
+    attribution_node1.set_tag("location1");
+
+    AttributionNode attribution_node2;
+    attribution_node2.set_uid(2222);
+    attribution_node2.set_tag("location2");
+
+    std::vector<AttributionNode> attribution_nodes = {attribution_node1, attribution_node2};
+
+    // Set up the event
+    LogEvent event(4, 12345);
+    event.write(attribution_nodes);
+    event.write((int32_t)999);
+    // Convert to a LogEvent
+    event.init();
+
+    android::util::ProtoOutputStream protoOutput;
+    writeFieldValueTreeToStream(event.GetTagId(), event.getValues(), &protoOutput);
+
+    vector<uint8_t> outData;
+    outData.resize(protoOutput.size());
+    size_t pos = 0;
+    auto iter = protoOutput.data();
+    while (iter.readBuffer() != NULL) {
+        size_t toRead = iter.currentToRead();
+        std::memcpy(&(outData[pos]), iter.readBuffer(), toRead);
+        pos += toRead;
+        iter.rp()->move(toRead);
+    }
+
+    Atom result;
+    EXPECT_EQ(true, result.ParseFromArray(&outData[0], outData.size()));
+    EXPECT_EQ(Atom::PushedCase::kBleScanResultReceived, result.pushed_case());
+    const auto& atom = result.ble_scan_result_received();
+    EXPECT_EQ(2, atom.attribution_node_size());
+    EXPECT_EQ(1111, atom.attribution_node(0).uid());
+    EXPECT_EQ("location1", atom.attribution_node(0).tag());
+    EXPECT_EQ(2222, atom.attribution_node(1).uid());
+    EXPECT_EQ("location2", atom.attribution_node(1).tag());
+    EXPECT_EQ(999, atom.num_of_results());
+}
+
+
+}  // namespace statsd
+}  // namespace os
+}  // namespace android
+#else
+GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif
\ No newline at end of file
diff --git a/cmds/statsd/tests/LogEntryMatcher_test.cpp b/cmds/statsd/tests/LogEntryMatcher_test.cpp
index 111b4ba..1023ea4 100644
--- a/cmds/statsd/tests/LogEntryMatcher_test.cpp
+++ b/cmds/statsd/tests/LogEntryMatcher_test.cpp
@@ -14,6 +14,7 @@
 
 #include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
 #include "matchers/matcher_util.h"
+#include "stats_log_util.h"
 #include "stats_util.h"
 
 #include <gtest/gtest.h>
@@ -35,8 +36,6 @@
 const int ATTRIBUTION_UID_FIELD_ID = 1;
 const int ATTRIBUTION_TAG_FIELD_ID = 2;
 
-// Private API from liblog.
-extern "C" void android_log_rewind(android_log_context ctx);
 
 #ifdef __ANDROID__
 TEST(AtomMatcherTest, TestSimpleMatcher) {
@@ -597,7 +596,6 @@
     matcherResults.push_back(MatchingState::kMatched);
     EXPECT_FALSE(combinationMatch(children, operation, matcherResults));
 }
-
 #else
 GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif
diff --git a/cmds/statsd/tests/LogEvent_test.cpp b/cmds/statsd/tests/LogEvent_test.cpp
index fd28460..b649215 100644
--- a/cmds/statsd/tests/LogEvent_test.cpp
+++ b/cmds/statsd/tests/LogEvent_test.cpp
@@ -22,548 +22,142 @@
 namespace os {
 namespace statsd {
 
-TEST(LogEventTest, testEmptyEvent) {
-    const int32_t TAG_ID = 123;
-    LogEvent event(TAG_ID, 0);
-    event.init();
+TEST(LogEventTest, TestLogParsing) {
+    LogEvent event1(1, 2000);
 
-    DimensionsValue dimensionsValue;
-    EXPECT_FALSE(event.GetSimpleAtomDimensionsValueProto(234, &dimensionsValue));
-    FieldMatcher dimensions;
-    dimensions.set_field(event.GetTagId());
-    EXPECT_FALSE(event.GetAtomDimensionsValueProto(dimensions, &dimensionsValue));
+    std::vector<AttributionNode> nodes;
 
-    dimensions.add_child()->set_field(3);
-    dimensions.mutable_child(0)->set_position(Position::FIRST);
-    EXPECT_FALSE(event.GetAtomDimensionsValueProto(dimensions, &dimensionsValue));
+    AttributionNode node1;
+    node1.set_uid(1000);
+    node1.set_tag("tag1");
+    nodes.push_back(node1);
 
-    dimensions.mutable_child(0)->set_position(Position::ANY);
-    EXPECT_FALSE(event.GetAtomDimensionsValueProto(dimensions, &dimensionsValue));
+    AttributionNode node2;
+    node2.set_uid(2000);
+    node2.set_tag("tag2");
+    nodes.push_back(node2);
 
-    dimensions.mutable_child(0)->set_position(Position::LAST);
-    EXPECT_FALSE(event.GetAtomDimensionsValueProto(dimensions, &dimensionsValue));
+    event1.write(nodes);
+    event1.write("hello");
+    event1.write((int32_t)10);
+    event1.write((int64_t)20);
+    event1.write((float)1.1);
+    event1.init();
+
+    const auto& items = event1.getValues();
+    EXPECT_EQ((size_t)8, items.size());
+    EXPECT_EQ(1, event1.GetTagId());
+
+    const FieldValue& item0 = event1.getValues()[0];
+    EXPECT_EQ(0x2010101, item0.mField.getField());
+    EXPECT_EQ(Type::INT, item0.mValue.getType());
+    EXPECT_EQ(1000, item0.mValue.int_value);
+
+    const FieldValue& item1 = event1.getValues()[1];
+    EXPECT_EQ(0x2010182, item1.mField.getField());
+    EXPECT_EQ(Type::STRING, item1.mValue.getType());
+    EXPECT_EQ("tag1", item1.mValue.str_value);
+
+    const FieldValue& item2 = event1.getValues()[2];
+    EXPECT_EQ(0x2018201, item2.mField.getField());
+    EXPECT_EQ(Type::INT, item2.mValue.getType());
+    EXPECT_EQ(2000, item2.mValue.int_value);
+
+    const FieldValue& item3 = event1.getValues()[3];
+    EXPECT_EQ(0x2018282, item3.mField.getField());
+    EXPECT_EQ(Type::STRING, item3.mValue.getType());
+    EXPECT_EQ("tag2", item3.mValue.str_value);
+
+    const FieldValue& item4 = event1.getValues()[4];
+    EXPECT_EQ(0x20000, item4.mField.getField());
+    EXPECT_EQ(Type::STRING, item4.mValue.getType());
+    EXPECT_EQ("hello", item4.mValue.str_value);
+
+    const FieldValue& item5 = event1.getValues()[5];
+    EXPECT_EQ(0x30000, item5.mField.getField());
+    EXPECT_EQ(Type::INT, item5.mValue.getType());
+    EXPECT_EQ(10, item5.mValue.int_value);
+
+    const FieldValue& item6 = event1.getValues()[6];
+    EXPECT_EQ(0x40000, item6.mField.getField());
+    EXPECT_EQ(Type::LONG, item6.mValue.getType());
+    EXPECT_EQ((int64_t)20, item6.mValue.long_value);
+
+    const FieldValue& item7 = event1.getValues()[7];
+    EXPECT_EQ(0x50000, item7.mField.getField());
+    EXPECT_EQ(Type::FLOAT, item7.mValue.getType());
+    EXPECT_EQ((float)1.1, item7.mValue.float_value);
 }
 
-TEST(LogEventTest, testRepeatedAttributionNode) {
-    const int32_t TAG_ID = 123;
-    LogEvent event(TAG_ID, 0);
-    AttributionNode attribution_node1;
-    attribution_node1.set_uid(1111);
-    attribution_node1.set_tag("locationService");
+TEST(LogEventTest, TestLogParsing2) {
+    LogEvent event1(1, 2000);
 
-    AttributionNode attribution_node2;
-    attribution_node2.set_uid(2222);
-    attribution_node2.set_tag("locationService2");
+    std::vector<AttributionNode> nodes;
 
-    AttributionNode attribution_node3;
-    attribution_node3.set_uid(3333);
-    attribution_node3.set_tag("locationService3");
-    std::vector<AttributionNode> attribution_nodes =
-        {attribution_node1, attribution_node2, attribution_node3};
+    event1.write("hello");
 
-    // 1nd field: int32.
-    EXPECT_TRUE(event.write(int32_t(11)));
-    // 2rd field: float.
-    EXPECT_TRUE(event.write(3.45f));
-    // Here it assume that the atom proto contains a repeated AttributionNode field.
-    // 3rd field: attribution node. This is repeated field.
-    EXPECT_TRUE(event.write(attribution_nodes));
-    // 4th field: bool.
-    EXPECT_TRUE(event.write(true));
-    // 5th field: long.
-    EXPECT_TRUE(event.write(uint64_t(1234)));
+    // repeated msg can be in the middle
+    AttributionNode node1;
+    node1.set_uid(1000);
+    node1.set_tag("tag1");
+    nodes.push_back(node1);
 
-    event.init();
+    AttributionNode node2;
+    node2.set_uid(2000);
+    node2.set_tag("tag2");
+    nodes.push_back(node2);
+    event1.write(nodes);
 
-    DimensionsValue dimensionsValue;
-    // Query single primitive fields.
-    EXPECT_TRUE(event.GetSimpleAtomDimensionsValueProto(1, &dimensionsValue));
-    EXPECT_EQ(dimensionsValue.field(), event.GetTagId());
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value_size(), 1);
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(0).field(), 1);
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(0).value_int(), 11);
+    event1.write((int32_t)10);
+    event1.write((int64_t)20);
+    event1.write((float)1.1);
+    event1.init();
 
-    EXPECT_TRUE(event.GetSimpleAtomDimensionsValueProto(2, &dimensionsValue));
-    EXPECT_EQ(dimensionsValue.field(), event.GetTagId());
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value_size(), 1);
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(0).field(), 2);
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(0).value_float(), 3.45f);
+    const auto& items = event1.getValues();
+    EXPECT_EQ((size_t)8, items.size());
+    EXPECT_EQ(1, event1.GetTagId());
 
-    EXPECT_TRUE(event.GetSimpleAtomDimensionsValueProto(4, &dimensionsValue));
-    EXPECT_EQ(dimensionsValue.field(), event.GetTagId());
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value_size(), 1);
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(0).field(), 4);
-    // The bool value is stored in value_int field as logD does not support bool.
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(0).value_int(), true);
+    const FieldValue& item = event1.getValues()[0];
+    EXPECT_EQ(0x00010000, item.mField.getField());
+    EXPECT_EQ(Type::STRING, item.mValue.getType());
+    EXPECT_EQ("hello", item.mValue.str_value);
 
-    EXPECT_TRUE(event.GetSimpleAtomDimensionsValueProto(5, &dimensionsValue));
-    EXPECT_EQ(dimensionsValue.field(), event.GetTagId());
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value_size(), 1);
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(0).field(), 5);
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(0).value_long(), long(1234));
+    const FieldValue& item0 = event1.getValues()[1];
+    EXPECT_EQ(0x2020101, item0.mField.getField());
+    EXPECT_EQ(Type::INT, item0.mValue.getType());
+    EXPECT_EQ(1000, item0.mValue.int_value);
 
-    // First attribution.
-    FieldMatcher first_uid_dimensions;
-    first_uid_dimensions.set_field(event.GetTagId());
-    first_uid_dimensions.add_child()->set_field(3);
-    first_uid_dimensions.mutable_child(0)->set_position(Position::FIRST);
-    first_uid_dimensions.mutable_child(0)->add_child()->set_field(1);
-    EXPECT_TRUE(event.GetAtomDimensionsValueProto(first_uid_dimensions, &dimensionsValue));
-    EXPECT_EQ(dimensionsValue.field(), event.GetTagId());
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value_size(), 1);
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(0).field(), 3);
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(0).value_tuple()
-        .dimensions_value_size(), 1);
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(0).value_tuple()
-        .dimensions_value(0).field(), 1);
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(0).value_tuple()
-        .dimensions_value(0).value_int(), 1111);
+    const FieldValue& item1 = event1.getValues()[2];
+    EXPECT_EQ(0x2020182, item1.mField.getField());
+    EXPECT_EQ(Type::STRING, item1.mValue.getType());
+    EXPECT_EQ("tag1", item1.mValue.str_value);
 
-    FieldMatcher first_tag_dimensions = first_uid_dimensions;
-    first_tag_dimensions.mutable_child(0)->mutable_child(0)->set_field(2);
-    EXPECT_TRUE(event.GetAtomDimensionsValueProto(first_tag_dimensions, &dimensionsValue));
-    EXPECT_EQ(dimensionsValue.field(), event.GetTagId());
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value_size(), 1);
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(0).field(), 3);
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(0).value_tuple()
-        .dimensions_value_size(), 1);
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(0).value_tuple()
-        .dimensions_value(0).field(), 2);
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(0).value_tuple()
-        .dimensions_value(0).value_str(), "locationService");
+    const FieldValue& item2 = event1.getValues()[3];
+    EXPECT_EQ(0x2028201, item2.mField.getField());
+    EXPECT_EQ(Type::INT, item2.mValue.getType());
+    EXPECT_EQ(2000, item2.mValue.int_value);
 
-    FieldMatcher first_attribution_dimensions = first_uid_dimensions;
-    first_attribution_dimensions.mutable_child(0)->add_child()->set_field(2);
-    EXPECT_TRUE(event.GetAtomDimensionsValueProto(first_attribution_dimensions, &dimensionsValue));
-    EXPECT_EQ(dimensionsValue.field(), event.GetTagId());
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value_size(), 1);
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(0).field(), 3);
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(0).value_tuple()
-        .dimensions_value_size(), 2);
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(0).value_tuple()
-        .dimensions_value(0).field(), 1);
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(0).value_tuple()
-        .dimensions_value(0).value_int(), 1111);
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(0).value_tuple()
-        .dimensions_value(1).field(), 2);
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(0).value_tuple()
-        .dimensions_value(1).value_str(), "locationService");
+    const FieldValue& item3 = event1.getValues()[4];
+    EXPECT_EQ(0x2028282, item3.mField.getField());
+    EXPECT_EQ(Type::STRING, item3.mValue.getType());
+    EXPECT_EQ("tag2", item3.mValue.str_value);
 
-    FieldMatcher last_attribution_dimensions = first_attribution_dimensions;
-    last_attribution_dimensions.mutable_child(0)->set_position(Position::LAST);
-    EXPECT_TRUE(event.GetAtomDimensionsValueProto(last_attribution_dimensions, &dimensionsValue));
-    EXPECT_EQ(dimensionsValue.field(), event.GetTagId());
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value_size(), 1);
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(0).field(), 3);
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(0).value_tuple()
-        .dimensions_value_size(), 2);
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(0).value_tuple()
-        .dimensions_value(0).field(), 1);
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(0).value_tuple()
-        .dimensions_value(0).value_int(), 3333);
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(0).value_tuple()
-        .dimensions_value(1).field(), 2);
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(0).value_tuple()
-        .dimensions_value(1).value_str(), "locationService3");
+    const FieldValue& item5 = event1.getValues()[5];
+    EXPECT_EQ(0x30000, item5.mField.getField());
+    EXPECT_EQ(Type::INT, item5.mValue.getType());
+    EXPECT_EQ(10, item5.mValue.int_value);
 
-    FieldMatcher any_attribution_dimensions = first_attribution_dimensions;
-    any_attribution_dimensions.mutable_child(0)->set_position(Position::ANY);
-    std::vector<DimensionsValue> dimensionsValues;
-    event.GetAtomDimensionsValueProtos(any_attribution_dimensions, &dimensionsValues);
-    EXPECT_EQ(dimensionsValues.size(), 3u);
-    EXPECT_EQ(dimensionsValues[0].field(), event.GetTagId());
-    EXPECT_EQ(dimensionsValues[0].value_tuple().dimensions_value_size(), 1);
-    EXPECT_EQ(dimensionsValues[0].value_tuple().dimensions_value(0).field(), 3);
-    EXPECT_EQ(dimensionsValues[0].value_tuple().dimensions_value(0).value_tuple()
-        .dimensions_value_size(), 2);
-    EXPECT_EQ(dimensionsValues[0].value_tuple().dimensions_value(0).value_tuple()
-        .dimensions_value(0).field(), 1);
-    EXPECT_EQ(dimensionsValues[0].value_tuple().dimensions_value(0).value_tuple()
-        .dimensions_value(0).value_int(), 1111);
-    EXPECT_EQ(dimensionsValues[0].value_tuple().dimensions_value(0).value_tuple()
-        .dimensions_value(1).field(), 2);
-    EXPECT_EQ(dimensionsValues[0].value_tuple().dimensions_value(0).value_tuple()
-        .dimensions_value(1).value_str(), "locationService");
-    EXPECT_EQ(dimensionsValues[1].field(), event.GetTagId());
-    EXPECT_EQ(dimensionsValues[1].value_tuple().dimensions_value_size(), 1);
-    EXPECT_EQ(dimensionsValues[1].value_tuple().dimensions_value(0).field(), 3);
-    EXPECT_EQ(dimensionsValues[1].value_tuple().dimensions_value(0).value_tuple()
-        .dimensions_value_size(), 2);
-    EXPECT_EQ(dimensionsValues[1].value_tuple().dimensions_value(0).value_tuple()
-        .dimensions_value(0).field(), 1);
-    EXPECT_EQ(dimensionsValues[1].value_tuple().dimensions_value(0).value_tuple()
-        .dimensions_value(0).value_int(), 2222);
-    EXPECT_EQ(dimensionsValues[1].value_tuple().dimensions_value(0).value_tuple()
-        .dimensions_value(1).field(), 2);
-    EXPECT_EQ(dimensionsValues[1].value_tuple().dimensions_value(0).value_tuple()
-        .dimensions_value(1).value_str(), "locationService2");
-    EXPECT_EQ(dimensionsValues[2].field(), event.GetTagId());
-    EXPECT_EQ(dimensionsValues[2].value_tuple().dimensions_value_size(), 1);
-    EXPECT_EQ(dimensionsValues[2].value_tuple().dimensions_value(0).field(), 3);
-    EXPECT_EQ(dimensionsValues[2].value_tuple().dimensions_value(0).value_tuple()
-        .dimensions_value_size(), 2);
-    EXPECT_EQ(dimensionsValues[2].value_tuple().dimensions_value(0).value_tuple()
-        .dimensions_value(0).field(), 1);
-    EXPECT_EQ(dimensionsValues[2].value_tuple().dimensions_value(0).value_tuple()
-        .dimensions_value(0).value_int(), 3333);
-    EXPECT_EQ(dimensionsValues[2].value_tuple().dimensions_value(0).value_tuple()
-        .dimensions_value(1).field(), 2);
-    EXPECT_EQ(dimensionsValues[2].value_tuple().dimensions_value(0).value_tuple()
-        .dimensions_value(1).value_str(), "locationService3");
+    const FieldValue& item6 = event1.getValues()[6];
+    EXPECT_EQ(0x40000, item6.mField.getField());
+    EXPECT_EQ(Type::LONG, item6.mValue.getType());
+    EXPECT_EQ((int64_t)20, item6.mValue.long_value);
 
-    FieldMatcher mixed_dimensions = any_attribution_dimensions;
-    mixed_dimensions.add_child()->set_field(1000);
-    mixed_dimensions.add_child()->set_field(6); // missing field.
-    mixed_dimensions.add_child()->set_field(3); // position not set.
-    mixed_dimensions.add_child()->set_field(5);
-    mixed_dimensions.add_child()->set_field(1);
-    dimensionsValues.clear();
-    event.GetAtomDimensionsValueProtos(mixed_dimensions, &dimensionsValues);
-    EXPECT_EQ(dimensionsValues.size(), 3u);
-    EXPECT_EQ(dimensionsValues[0].field(), event.GetTagId());
-    EXPECT_EQ(dimensionsValues[0].value_tuple().dimensions_value_size(), 3);
-    EXPECT_EQ(dimensionsValues[0].value_tuple().dimensions_value(0).field(), 3);
-    EXPECT_EQ(dimensionsValues[0].value_tuple().dimensions_value(0).value_tuple().dimensions_value_size(), 2);
-    EXPECT_EQ(dimensionsValues[0].value_tuple().dimensions_value(0).value_tuple().dimensions_value(0).field(), 1);
-    EXPECT_EQ(dimensionsValues[0].value_tuple().dimensions_value(0).value_tuple().dimensions_value(0).value_int(),
-              1111);
-    EXPECT_EQ(dimensionsValues[0].value_tuple().dimensions_value(0).value_tuple().dimensions_value(1).field(), 2);
-    EXPECT_EQ(dimensionsValues[0].value_tuple().dimensions_value(0).value_tuple().dimensions_value(1).value_str(),
-              "locationService");
-    EXPECT_EQ(dimensionsValues[0].value_tuple().dimensions_value(1).field(), 5);
-    EXPECT_EQ(dimensionsValues[0].value_tuple().dimensions_value(1).value_long(), long(1234));
-    EXPECT_EQ(dimensionsValues[0].value_tuple().dimensions_value(2).field(), 1);
-    EXPECT_EQ(dimensionsValues[0].value_tuple().dimensions_value(2).value_int(), 11);
-
-    EXPECT_EQ(dimensionsValues[1].field(), event.GetTagId());
-    EXPECT_EQ(dimensionsValues[1].value_tuple().dimensions_value_size(), 3);
-    EXPECT_EQ(dimensionsValues[1].value_tuple().dimensions_value(0).field(), 3);
-    EXPECT_EQ(dimensionsValues[1].value_tuple().dimensions_value(0).value_tuple().dimensions_value_size(), 2);
-    EXPECT_EQ(dimensionsValues[1].value_tuple().dimensions_value(0).value_tuple().dimensions_value(0).field(), 1);
-    EXPECT_EQ(dimensionsValues[1].value_tuple().dimensions_value(0).value_tuple().dimensions_value(0).value_int(),
-              2222);
-    EXPECT_EQ(dimensionsValues[1].value_tuple().dimensions_value(0).value_tuple().dimensions_value(1).field(), 2);
-    EXPECT_EQ(dimensionsValues[1].value_tuple().dimensions_value(0).value_tuple().dimensions_value(1).value_str(),
-              "locationService2");
-    EXPECT_EQ(dimensionsValues[1].value_tuple().dimensions_value(1).field(), 5);
-    EXPECT_EQ(dimensionsValues[1].value_tuple().dimensions_value(1).value_long(), long(1234));
-    EXPECT_EQ(dimensionsValues[1].value_tuple().dimensions_value(2).field(), 1);
-    EXPECT_EQ(dimensionsValues[1].value_tuple().dimensions_value(2).value_int(), 11);
-
-    EXPECT_EQ(dimensionsValues[2].field(), event.GetTagId());
-    EXPECT_EQ(dimensionsValues[2].value_tuple().dimensions_value_size(), 3);
-    EXPECT_EQ(dimensionsValues[2].value_tuple().dimensions_value(0).field(), 3);
-    EXPECT_EQ(dimensionsValues[2].value_tuple().dimensions_value(0).value_tuple().dimensions_value_size(), 2);
-    EXPECT_EQ(dimensionsValues[2].value_tuple().dimensions_value(0).value_tuple().dimensions_value(0).field(), 1);
-    EXPECT_EQ(dimensionsValues[2].value_tuple().dimensions_value(0).value_tuple().dimensions_value(0).value_int(),
-              3333);
-    EXPECT_EQ(dimensionsValues[2].value_tuple().dimensions_value(0).value_tuple().dimensions_value(1).field(), 2);
-    EXPECT_EQ(dimensionsValues[2].value_tuple().dimensions_value(0).value_tuple().dimensions_value(1).value_str(),
-              "locationService3");
-    EXPECT_EQ(dimensionsValues[2].value_tuple().dimensions_value(1).field(), 5);
-    EXPECT_EQ(dimensionsValues[2].value_tuple().dimensions_value(1).value_long(), long(1234));
-    EXPECT_EQ(dimensionsValues[2].value_tuple().dimensions_value(2).field(), 1);
-    EXPECT_EQ(dimensionsValues[2].value_tuple().dimensions_value(2).value_int(), 11);
-
-    FieldMatcher wrong_dimensions = mixed_dimensions;
-    // Wrong tagId.
-    wrong_dimensions.set_field(event.GetTagId() + 100);
-    dimensionsValues.clear();
-    event.GetAtomDimensionsValueProtos(wrong_dimensions, &dimensionsValues);
-    EXPECT_TRUE(dimensionsValues.empty());
+    const FieldValue& item7 = event1.getValues()[7];
+    EXPECT_EQ(0x50000, item7.mField.getField());
+    EXPECT_EQ(Type::FLOAT, item7.mValue.getType());
+    EXPECT_EQ((float)1.1, item7.mValue.float_value);
 }
 
-TEST(LogEventTest, testMessageField) {
-    const int32_t TAG_ID = 123;
-    LogEvent event(TAG_ID, 0);
-    AttributionNode attribution_node1;
-    attribution_node1.set_uid(1111);
-    attribution_node1.set_tag("locationService");
-
-    AttributionNode attribution_node2;
-    attribution_node2.set_uid(2222);
-    attribution_node2.set_tag("locationService2");
-
-    // 1nd field: int32.
-    EXPECT_TRUE(event.write(int32_t(11)));
-    // 2rd field: float.
-    EXPECT_TRUE(event.write(3.45f));
-    // Here it assume that the atom proto contains two optional AttributionNode fields.
-    // 3rd field: attribution node. This is not repeated field.
-    EXPECT_TRUE(event.write(attribution_node1));
-    // 4th field: another attribution field. This is not repeated field.
-    EXPECT_TRUE(event.write(attribution_node2));
-    // 5th field: bool.
-    EXPECT_TRUE(event.write(true));
-    // 6th field: long.
-    EXPECT_TRUE(event.write(uint64_t(1234)));
-
-    event.init();
-
-    FieldMatcher uid_dimensions1;
-    uid_dimensions1.set_field(event.GetTagId());
-    uid_dimensions1.add_child()->set_field(3);
-    uid_dimensions1.mutable_child(0)->add_child()->set_field(1);
-
-    FieldMatcher tag_dimensions1;
-    tag_dimensions1.set_field(event.GetTagId());
-    tag_dimensions1.add_child()->set_field(3);
-    tag_dimensions1.mutable_child(0)->add_child()->set_field(2);
-
-    FieldMatcher attribution_dimensions1;
-    attribution_dimensions1.set_field(event.GetTagId());
-    attribution_dimensions1.add_child()->set_field(3);
-    attribution_dimensions1.mutable_child(0)->add_child()->set_field(1);
-    attribution_dimensions1.mutable_child(0)->add_child()->set_field(2);
-
-    FieldMatcher uid_dimensions2 = uid_dimensions1;
-    uid_dimensions2.mutable_child(0)->set_field(4);
-
-    FieldMatcher tag_dimensions2 = tag_dimensions1;
-    tag_dimensions2.mutable_child(0)->set_field(4);
-
-    FieldMatcher attribution_dimensions2 = attribution_dimensions1;
-    attribution_dimensions2.mutable_child(0)->set_field(4);
-
-    FieldMatcher mixed_dimensions = attribution_dimensions1;
-    mixed_dimensions.add_child()->set_field(4);
-    mixed_dimensions.mutable_child(1)->add_child()->set_field(1);
-    mixed_dimensions.add_child()->set_field(1000);
-    mixed_dimensions.add_child()->set_field(5);
-    mixed_dimensions.add_child()->set_field(1);
-
-    DimensionsValue dimensionsValue;
-
-    // Query single primitive fields.
-    EXPECT_TRUE(event.GetSimpleAtomDimensionsValueProto(1, &dimensionsValue));
-    EXPECT_EQ(dimensionsValue.field(), event.GetTagId());
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value_size(), 1);
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(0).field(), 1);
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(0).value_int(), 11);
-
-    EXPECT_TRUE(event.GetSimpleAtomDimensionsValueProto(2, &dimensionsValue));
-    EXPECT_EQ(dimensionsValue.field(), event.GetTagId());
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value_size(), 1);
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(0).field(), 2);
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(0).value_float(), 3.45f);
-
-    EXPECT_TRUE(event.GetSimpleAtomDimensionsValueProto(5, &dimensionsValue));
-    EXPECT_EQ(dimensionsValue.field(), event.GetTagId());
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value_size(), 1);
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(0).field(), 5);
-    // The bool value is stored in value_int field as logD does not support bool.
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(0).value_int(), true);
-
-    EXPECT_TRUE(event.GetSimpleAtomDimensionsValueProto(6, &dimensionsValue));
-    EXPECT_EQ(dimensionsValue.field(), event.GetTagId());
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value_size(), 1);
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(0).field(), 6);
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(0).value_long(), long(1234));
-
-    // Query atom field 3: attribution node uid field only.
-    EXPECT_TRUE(event.GetAtomDimensionsValueProto(uid_dimensions1, &dimensionsValue));
-    EXPECT_EQ(dimensionsValue.field(), event.GetTagId());
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value_size(), 1);
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(0).field(), 3);
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(0).value_tuple()
-        .dimensions_value_size(), 1);
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(0).value_tuple()
-        .dimensions_value(0).field(), 1);
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(0).value_tuple()
-        .dimensions_value(0).value_int(), 1111);
-
-    // Query atom field 3: attribution node tag field only.
-    EXPECT_TRUE(event.GetAtomDimensionsValueProto(tag_dimensions1, &dimensionsValue));
-    EXPECT_EQ(dimensionsValue.field(), event.GetTagId());
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value_size(), 1);
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(0).field(), 3);
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(0).value_tuple()
-        .dimensions_value_size(), 1);
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(0).value_tuple()
-        .dimensions_value(0).field(), 2);
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(0).value_tuple()
-        .dimensions_value(0).value_str(), "locationService");
-
-    // Query atom field 3: attribution node uid + tag fields.
-    EXPECT_TRUE(event.GetAtomDimensionsValueProto(attribution_dimensions1, &dimensionsValue));
-    EXPECT_EQ(dimensionsValue.field(), event.GetTagId());
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value_size(), 1);
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(0).field(), 3);
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(0).value_tuple()
-        .dimensions_value_size(), 2);
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(0).value_tuple()
-        .dimensions_value(0).field(), 1);
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(0).value_tuple()
-        .dimensions_value(0).value_int(), 1111);
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(0).value_tuple()
-        .dimensions_value(1).field(), 2);
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(0).value_tuple()
-        .dimensions_value(1).value_str(), "locationService");
-
-    // Query atom field 4: attribution node uid field only.
-    EXPECT_TRUE(event.GetAtomDimensionsValueProto(uid_dimensions2, &dimensionsValue));
-    EXPECT_EQ(dimensionsValue.field(), event.GetTagId());
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value_size(), 1);
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(0).field(), 4);
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(0).value_tuple()
-        .dimensions_value_size(), 1);
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(0).value_tuple()
-        .dimensions_value(0).field(), 1);
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(0).value_tuple()
-        .dimensions_value(0).value_int(), 2222);
-
-    // Query atom field 4: attribution node tag field only.
-    EXPECT_TRUE(event.GetAtomDimensionsValueProto(tag_dimensions2, &dimensionsValue));
-    EXPECT_EQ(dimensionsValue.field(), event.GetTagId());
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value_size(), 1);
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(0).field(), 4);
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(0).value_tuple()
-        .dimensions_value_size(), 1);
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(0).value_tuple()
-        .dimensions_value(0).field(), 2);
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(0).value_tuple()
-        .dimensions_value(0).value_str(), "locationService2");
-
-    // Query atom field 4: attribution node uid + tag fields.
-    EXPECT_TRUE(event.GetAtomDimensionsValueProto(attribution_dimensions2, &dimensionsValue));
-    EXPECT_EQ(dimensionsValue.field(), event.GetTagId());
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value_size(), 1);
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(0).field(), 4);
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(0).value_tuple()
-        .dimensions_value_size(), 2);
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(0).value_tuple()
-        .dimensions_value(0).field(), 1);
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(0).value_tuple()
-        .dimensions_value(0).value_int(), 2222);
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(0).value_tuple()
-        .dimensions_value(1).field(), 2);
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(0).value_tuple()
-        .dimensions_value(1).value_str(), "locationService2");
-
-    // Query multiple fields:
-    // 1/ Field 3: attribution uid + tag.
-    // 2/ Field 4: attribution uid only.
-    // 3/ Field not exist.
-    // 4/ Primitive fields #5
-    // 5/ Primitive fields #1
-    EXPECT_TRUE(event.GetAtomDimensionsValueProto(mixed_dimensions, &dimensionsValue));
-    EXPECT_EQ(dimensionsValue.field(), event.GetTagId());
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value_size(), 4);
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(0).field(), 3);
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(0).value_tuple()
-        .dimensions_value_size(), 2);
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(0).value_tuple()
-        .dimensions_value(0).field(), 1);
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(0).value_tuple()
-        .dimensions_value(0).value_int(), 1111);
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(0).value_tuple()
-        .dimensions_value(1).field(), 2);
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(0).value_tuple()
-        .dimensions_value(1).value_str(), "locationService");
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(1).field(), 4);
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(1).value_tuple()
-        .dimensions_value_size(), 1);
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(1).value_tuple()
-        .dimensions_value(0).field(), 1);
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(1).value_tuple()
-        .dimensions_value(0).value_int(), 2222);
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(2).field(), 5);
-    // The bool value is stored in value_int field as logD does not support bool.
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(2).value_int(), true);
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(3).field(), 1);
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(3).value_int(), 11);
-}
-
-TEST(LogEventTest, testAllPrimitiveFields) {
-    const int32_t TAG_ID = 123;
-    LogEvent event(TAG_ID, 0);
-
-    // 1nd field: int32.
-    EXPECT_TRUE(event.write(int32_t(11)));
-    // 2rd field: float.
-    EXPECT_TRUE(event.write(3.45f));
-    // 3th field: string.
-    EXPECT_TRUE(event.write("test"));
-    // 4th field: bool.
-    EXPECT_TRUE(event.write(true));
-    // 5th field: bool.
-    EXPECT_TRUE(event.write(false));
-    // 6th field: long.
-    EXPECT_TRUE(event.write(uint64_t(1234)));
-
-    event.init();
-
-    DimensionsValue dimensionsValue;
-    EXPECT_TRUE(event.GetSimpleAtomDimensionsValueProto(1, &dimensionsValue));
-    EXPECT_EQ(dimensionsValue.field(), event.GetTagId());
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value_size(), 1);
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(0).field(), 1);
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(0).value_int(), 11);
-
-    EXPECT_TRUE(event.GetSimpleAtomDimensionsValueProto(2, &dimensionsValue));
-    EXPECT_EQ(dimensionsValue.field(), event.GetTagId());
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value_size(), 1);
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(0).field(), 2);
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(0).value_float(), 3.45f);
-
-    EXPECT_TRUE(event.GetSimpleAtomDimensionsValueProto(3, &dimensionsValue));
-    EXPECT_EQ(dimensionsValue.field(), event.GetTagId());
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value_size(), 1);
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(0).field(), 3);
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(0).value_str(), "test");
-
-    EXPECT_TRUE(event.GetSimpleAtomDimensionsValueProto(4, &dimensionsValue));
-    EXPECT_EQ(dimensionsValue.field(), event.GetTagId());
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value_size(), 1);
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(0).field(), 4);
-    // The bool value is stored in value_int field as logD does not support bool.
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(0).value_int(), true);
-
-    EXPECT_TRUE(event.GetSimpleAtomDimensionsValueProto(5, &dimensionsValue));
-    EXPECT_EQ(dimensionsValue.field(), event.GetTagId());
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value_size(), 1);
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(0).field(), 5);
-    // The bool value is stored in value_int field as logD does not support bool.
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(0).value_int(), false);
-
-    EXPECT_TRUE(event.GetSimpleAtomDimensionsValueProto(6, &dimensionsValue));
-    EXPECT_EQ(dimensionsValue.field(), event.GetTagId());
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value_size(), 1);
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(0).field(), 6);
-    EXPECT_EQ(dimensionsValue.value_tuple().dimensions_value(0).value_long(), long(1234));
-
-    // Field not exist.
-    EXPECT_FALSE(event.GetSimpleAtomDimensionsValueProto(7, &dimensionsValue));
-}
-
-TEST(LogEventTest, testWriteAtomProtoToStream) {
-    AttributionNode attribution_node1;
-    attribution_node1.set_uid(1111);
-    attribution_node1.set_tag("locationService");
-
-    AttributionNode attribution_node2;
-    attribution_node2.set_uid(2222);
-    attribution_node2.set_tag("locationService2");
-
-    AttributionNode attribution_node3;
-    attribution_node3.set_uid(3333);
-    attribution_node3.set_tag("locationService3");
-    std::vector<AttributionNode> attribution_nodes =
-        {attribution_node1, attribution_node2, attribution_node3};
-
-    LogEvent event(1, 0);
-    EXPECT_TRUE(event.write("222"));
-    EXPECT_TRUE(event.write(attribution_nodes));
-    EXPECT_TRUE(event.write(345));
-    EXPECT_TRUE(event.write(attribution_node3));
-    EXPECT_TRUE(event.write("hello"));
-    event.init();
-
-    util::ProtoOutputStream protoOutput;
-    // For now only see whether it will crash.
-    // TODO(yanglu): test parsing from stream.
-    event.ToProto(protoOutput);
-}
 
 }  // namespace statsd
 }  // namespace os
diff --git a/cmds/statsd/tests/StatsLogProcessor_test.cpp b/cmds/statsd/tests/StatsLogProcessor_test.cpp
index aab5bed..cb72697 100644
--- a/cmds/statsd/tests/StatsLogProcessor_test.cpp
+++ b/cmds/statsd/tests/StatsLogProcessor_test.cpp
@@ -45,7 +45,7 @@
     }
 
     MOCK_METHOD0(byteSize, size_t());
-    MOCK_METHOD1(onDumpReport, void(ProtoOutputStream* output));
+    MOCK_METHOD2(onDumpReport, void(const uint64_t timeNs, ProtoOutputStream* output));
 };
 
 TEST(StatsLogProcessorTest, TestRateLimitByteSize) {
@@ -69,24 +69,26 @@
     sp<UidMap> m = new UidMap();
     sp<AnomalyMonitor> anomalyMonitor;
     int broadcastCount = 0;
-    StatsLogProcessor p(m, anomalyMonitor, 0,
-                        [&broadcastCount](const ConfigKey& key) { broadcastCount++; });
+    StatsLogProcessor p(m, anomalyMonitor, 0, [&broadcastCount](const ConfigKey& key) {
+        broadcastCount++;
+    });
 
     MockMetricsManager mockMetricsManager;
 
     ConfigKey key(100, 12345);
     EXPECT_CALL(mockMetricsManager, byteSize())
-            .Times(2)
+            .Times(1)
             .WillRepeatedly(Return(int(StatsdStats::kMaxMetricsBytesPerConfig * .95)));
 
     // Expect only one broadcast despite always returning a size that should trigger broadcast.
     p.flushIfNecessaryLocked(1, key, mockMetricsManager);
     EXPECT_EQ(1, broadcastCount);
 
+    // b/73089712
     // This next call to flush should not trigger a broadcast.
-    p.mLastByteSizeTimes.clear();  // Force another check for byte size.
-    p.flushIfNecessaryLocked(2, key, mockMetricsManager);
-    EXPECT_EQ(1, broadcastCount);
+    // p.mLastByteSizeTimes.clear();  // Force another check for byte size.
+    // p.flushIfNecessaryLocked(2, key, mockMetricsManager);
+    // EXPECT_EQ(1, broadcastCount);
 }
 
 TEST(StatsLogProcessorTest, TestDropWhenByteSizeTooLarge) {
@@ -103,7 +105,7 @@
             .Times(1)
             .WillRepeatedly(Return(int(StatsdStats::kMaxMetricsBytesPerConfig * 1.2)));
 
-    EXPECT_CALL(mockMetricsManager, onDumpReport(_)).Times(1);
+    EXPECT_CALL(mockMetricsManager, onDumpReport(_, _)).Times(1);
 
     // Expect to call the onDumpReport and skip the broadcast.
     p.flushIfNecessaryLocked(1, key, mockMetricsManager);
diff --git a/cmds/statsd/tests/anomaly/AnomalyTracker_test.cpp b/cmds/statsd/tests/anomaly/AnomalyTracker_test.cpp
index a415ea1..b4a7bb7 100644
--- a/cmds/statsd/tests/anomaly/AnomalyTracker_test.cpp
+++ b/cmds/statsd/tests/anomaly/AnomalyTracker_test.cpp
@@ -34,10 +34,10 @@
 const ConfigKey kConfigKey(0, 12345);
 
 MetricDimensionKey getMockMetricDimensionKey(int key, string value) {
-    DimensionsValue dimensionsValue;
-    dimensionsValue.set_field(key);
-    dimensionsValue.set_value_str(value);
-    return MetricDimensionKey(HashableDimensionKey(dimensionsValue), DEFAULT_DIMENSION_KEY);
+    int pos[] = {key, 0, 0};
+    HashableDimensionKey dim;
+    dim.addValue(FieldValue(Field(1, pos, 0), Value(value)));
+    return MetricDimensionKey(dim, DEFAULT_DIMENSION_KEY);
 }
 
 void AddValueToBucket(const std::vector<std::pair<MetricDimensionKey, long>>& key_value_pair_list,
diff --git a/cmds/statsd/tests/condition/SimpleConditionTracker_test.cpp b/cmds/statsd/tests/condition/SimpleConditionTracker_test.cpp
index d1b7b28..038d449 100644
--- a/cmds/statsd/tests/condition/SimpleConditionTracker_test.cpp
+++ b/cmds/statsd/tests/condition/SimpleConditionTracker_test.cpp
@@ -80,31 +80,31 @@
     const std::vector<int> &uids, const string& conditionName) {
     std::map<int64_t, std::vector<HashableDimensionKey>> outputKeyMap;
     std::vector<int> uid_indexes;
+    int pos[] = {1, 1, 1};
+    int depth = 2;
+    Field field(1, pos, depth);
     switch(position) {
         case Position::FIRST:
             uid_indexes.push_back(0);
             break;
         case Position::LAST:
             uid_indexes.push_back(uids.size() - 1);
+            field.setField(0x02018001);
             break;
         case Position::ANY:
             uid_indexes.resize(uids.size());
             std::iota(uid_indexes.begin(), uid_indexes.end(), 0);
+            field.setField(0x02010001);
             break;
         default:
             break;
     }
 
     for (const int idx : uid_indexes) {
-        DimensionsValue dimensionsValue;
-        dimensionsValue.set_field(TAG_ID);
-        dimensionsValue.mutable_value_tuple()->add_dimensions_value()->set_field(
-            ATTRIBUTION_NODE_FIELD_ID);
-        dimensionsValue.mutable_value_tuple()->mutable_dimensions_value(0)
-            ->mutable_value_tuple()->add_dimensions_value()->set_field(ATTRIBUTION_NODE_FIELD_ID);
-        dimensionsValue.mutable_value_tuple()->mutable_dimensions_value(0)
-            ->mutable_value_tuple()->mutable_dimensions_value(0)->set_value_int(uids[idx]);
-        outputKeyMap[StringToId(conditionName)].push_back(HashableDimensionKey(dimensionsValue));
+        Value value((int32_t)uids[idx]);
+        HashableDimensionKey dim;
+        dim.addValue(FieldValue(field, value));
+        outputKeyMap[StringToId(conditionName)].push_back(dim);
     }
     return outputKeyMap;
 }
@@ -265,7 +265,7 @@
 TEST(SimpleConditionTrackerTest, TestSlicedCondition) {
     for (Position position :
             { Position::ANY, Position::FIRST, Position::LAST}) {
-        FieldMatcher dimensionInCondition;
+        vector<Matcher> dimensionInCondition;
         std::unordered_set<HashableDimensionKey> dimensionKeys;
 
         SimplePredicate simplePredicate = getWakeLockHeldCondition(
@@ -374,7 +374,7 @@
 }
 
 TEST(SimpleConditionTrackerTest, TestSlicedWithNoOutputDim) {
-    FieldMatcher dimensionInCondition;
+    vector<Matcher> dimensionInCondition;
     std::unordered_set<HashableDimensionKey> dimensionKeys;
 
     SimplePredicate simplePredicate = getWakeLockHeldCondition(
@@ -470,7 +470,7 @@
 TEST(SimpleConditionTrackerTest, TestStopAll) {
     for (Position position :
             {Position::ANY, Position::FIRST, Position::LAST}) {
-        FieldMatcher dimensionInCondition;
+        vector<Matcher> dimensionInCondition;
         std::unordered_set<HashableDimensionKey> dimensionKeys;
         SimplePredicate simplePredicate = getWakeLockHeldCondition(
                 true /*nesting*/, true /*default to false*/, true /*output slice by uid*/,
@@ -576,7 +576,6 @@
                                         conditionCache, dimensionKeys);
         EXPECT_EQ(ConditionState::kFalse, conditionCache[0]);
     }
-
 }
 
 }  // namespace statsd
diff --git a/cmds/statsd/tests/dimension_test.cpp b/cmds/statsd/tests/dimension_test.cpp
deleted file mode 100644
index 678abae..0000000
--- a/cmds/statsd/tests/dimension_test.cpp
+++ /dev/null
@@ -1,149 +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 "dimension.h"
-
-#include <gtest/gtest.h>
-
-using namespace android::os::statsd;
-
-#ifdef __ANDROID__
-
-TEST(DimensionTest, subLeafNodes) {
-    DimensionsValue dimension;
-    int tagId = 100;
-    dimension.set_field(tagId);
-    auto child = dimension.mutable_value_tuple()->add_dimensions_value();
-    child->set_field(1);
-    child->set_value_int(2000);
-
-    child = dimension.mutable_value_tuple()->add_dimensions_value();
-    child->set_field(3);
-    child->set_value_str("test");
-
-    child = dimension.mutable_value_tuple()->add_dimensions_value();
-    child->set_field(4);
-    auto grandChild = child->mutable_value_tuple()->add_dimensions_value();
-    grandChild->set_field(1);
-    grandChild->set_value_float(1.3f);
-    grandChild = child->mutable_value_tuple()->add_dimensions_value();
-    grandChild->set_field(3);
-    grandChild->set_value_str("tag");
-
-    child = dimension.mutable_value_tuple()->add_dimensions_value();
-    child->set_field(6);
-    child->set_value_bool(false);
-
-    DimensionsValue sub_dimension;
-    FieldMatcher matcher;
-
-    // Tag id not matched.
-    matcher.set_field(tagId + 1);
-    EXPECT_FALSE(getSubDimension(dimension, matcher, &sub_dimension));
-
-    // Field not exist.
-    matcher.Clear();
-    matcher.set_field(tagId);
-    matcher.add_child()->set_field(5);
-    EXPECT_FALSE(getSubDimension(dimension, matcher, &sub_dimension));
-
-    // Field exists.
-    matcher.Clear();
-    matcher.set_field(tagId);
-    matcher.add_child()->set_field(3);
-    EXPECT_TRUE(getSubDimension(dimension, matcher, &sub_dimension));
-
-    // Field exists.
-    matcher.Clear();
-    sub_dimension.Clear();
-    matcher.set_field(tagId);
-    matcher.add_child()->set_field(6);
-    EXPECT_TRUE(getSubDimension(dimension, matcher, &sub_dimension));
-
-    // Field exists.
-    matcher.Clear();
-    sub_dimension.Clear();
-    matcher.set_field(tagId);
-    matcher.add_child()->set_field(1);
-    EXPECT_TRUE(getSubDimension(dimension, matcher, &sub_dimension));
-
-    // Not leaf field.
-    matcher.Clear();
-    sub_dimension.Clear();
-    matcher.set_field(tagId);
-    matcher.add_child()->set_field(4);
-    EXPECT_FALSE(getSubDimension(dimension, matcher, &sub_dimension));
-
-    // Grand-child leaf field not exist.
-    matcher.Clear();
-    sub_dimension.Clear();
-    matcher.set_field(tagId);
-    auto childMatcher = matcher.add_child();
-    childMatcher->set_field(4);
-    childMatcher->add_child()->set_field(2);
-    EXPECT_FALSE(getSubDimension(dimension, matcher, &sub_dimension));
-
-    // Grand-child leaf field.
-    matcher.Clear();
-    sub_dimension.Clear();
-    matcher.set_field(tagId);
-    childMatcher = matcher.add_child();
-    childMatcher->set_field(4);
-    childMatcher->add_child()->set_field(1);
-    EXPECT_TRUE(getSubDimension(dimension, matcher, &sub_dimension));
-
-    matcher.Clear();
-    sub_dimension.Clear();
-    matcher.set_field(tagId);
-    childMatcher = matcher.add_child();
-    childMatcher->set_field(4);
-    childMatcher->add_child()->set_field(3);
-    EXPECT_TRUE(getSubDimension(dimension, matcher, &sub_dimension));
-
-    // Multiple grand-child fields.
-    matcher.Clear();
-    sub_dimension.Clear();
-    matcher.set_field(tagId);
-    childMatcher = matcher.add_child();
-    childMatcher->set_field(4);
-    childMatcher->add_child()->set_field(3);
-    childMatcher->add_child()->set_field(1);
-    EXPECT_TRUE(getSubDimension(dimension, matcher, &sub_dimension));
-
-    // Multiple fields.
-    matcher.Clear();
-    sub_dimension.Clear();
-    matcher.set_field(tagId);
-    childMatcher = matcher.add_child();
-    childMatcher->set_field(4);
-    childMatcher->add_child()->set_field(3);
-    childMatcher->add_child()->set_field(1);
-    matcher.add_child()->set_field(3);
-    EXPECT_TRUE(getSubDimension(dimension, matcher, &sub_dimension));
-
-    // Subset of the fields not exist.
-    matcher.Clear();
-    sub_dimension.Clear();
-    matcher.set_field(tagId);
-    childMatcher = matcher.add_child();
-    childMatcher->set_field(4);
-    childMatcher->add_child()->set_field(3);
-    childMatcher->add_child()->set_field(1);
-    matcher.add_child()->set_field(2);
-    EXPECT_FALSE(getSubDimension(dimension, matcher, &sub_dimension));
-}
-
-#else
-GTEST_LOG_(INFO) << "This test does nothing.\n";
-#endif
diff --git a/cmds/statsd/tests/e2e/Attribution_e2e_test.cpp b/cmds/statsd/tests/e2e/Attribution_e2e_test.cpp
index a56db28..01743ef 100644
--- a/cmds/statsd/tests/e2e/Attribution_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/Attribution_e2e_test.cpp
@@ -146,9 +146,13 @@
         processor->OnLogEvent(event.get());
     }
     ConfigMetricsReportList reports;
-    processor->onDumpReport(cfgKey, bucketStartTimeNs + 4 * bucketSizeNs + 1, &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(), 4);
diff --git a/cmds/statsd/tests/e2e/DimensionInCondition_e2e_test.cpp b/cmds/statsd/tests/e2e/DimensionInCondition_e2e_test.cpp
index b5d48ef..275b5824 100644
--- a/cmds/statsd/tests/e2e/DimensionInCondition_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/DimensionInCondition_e2e_test.cpp
@@ -43,8 +43,8 @@
     auto holdingWakelockPredicate = CreateHoldingWakelockPredicate();
     // The predicate is dimensioning by any attribution node and both by uid and tag.
     *holdingWakelockPredicate.mutable_simple_predicate()->mutable_dimensions() =
-        CreateAttributionUidAndTagDimensions(
-            android::util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
+            CreateAttributionUidAndTagDimensions(android::util::WAKELOCK_STATE_CHANGED,
+                                                 {Position::FIRST});
     *config.add_predicate() = holdingWakelockPredicate;
 
     auto combinationPredicate = config.add_predicate();
@@ -57,8 +57,8 @@
     metric->set_id(StringToId("ScreenBrightnessChangeMetric"));
     metric->set_what(screenBrightnessChangeAtomMatcher.id());
     metric->set_condition(combinationPredicate->id());
-    *metric->mutable_dimensions_in_what() = CreateDimensions(
-            android::util::SCREEN_BRIGHTNESS_CHANGED, {1 /* level */});
+    *metric->mutable_dimensions_in_what() =
+            CreateDimensions(android::util::SCREEN_BRIGHTNESS_CHANGED, {1 /* level */});
     *metric->mutable_dimensions_in_condition() = CreateAttributionUidDimensions(
             android::util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
     metric->set_bucket(ONE_MINUTE);
@@ -72,62 +72,54 @@
     auto config = CreateCountMetricWithNoLinkConfig();
     int64_t bucketStartTimeNs = 10000000000;
     int64_t bucketSizeNs =
-        TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000LL;
+            TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000LL;
 
     auto processor = CreateStatsLogProcessor(bucketStartTimeNs / NS_PER_SEC, config, cfgKey);
     EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
     EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
 
-    std::vector<AttributionNode> attributions1 =
-        {CreateAttribution(111, "App1"), CreateAttribution(222, "GMSCoreModule1"),
-         CreateAttribution(222, "GMSCoreModule2")};
+    std::vector<AttributionNode> attributions1 = {CreateAttribution(111, "App1"),
+                                                  CreateAttribution(222, "GMSCoreModule1"),
+                                                  CreateAttribution(222, "GMSCoreModule2")};
 
-    std::vector<AttributionNode> attributions2 =
-        {CreateAttribution(333, "App2"), CreateAttribution(222, "GMSCoreModule1"),
-         CreateAttribution(555, "GMSCoreModule2")};
+    std::vector<AttributionNode> attributions2 = {CreateAttribution(333, "App2"),
+                                                  CreateAttribution(222, "GMSCoreModule1"),
+                                                  CreateAttribution(555, "GMSCoreModule2")};
 
     std::vector<std::unique_ptr<LogEvent>> events;
-    events.push_back(CreateScreenStateChangedEvent(
-        android::view::DISPLAY_STATE_ON, bucketStartTimeNs + 10));
-    events.push_back(CreateScreenStateChangedEvent(
-        android::view::DISPLAY_STATE_OFF, bucketStartTimeNs + 100));
-    events.push_back(CreateScreenStateChangedEvent(
-        android::view::DISPLAY_STATE_ON, bucketStartTimeNs + bucketSizeNs + 1));
-    events.push_back(CreateScreenStateChangedEvent(
-        android::view::DISPLAY_STATE_OFF, bucketStartTimeNs + 2 * bucketSizeNs - 10));
+    events.push_back(
+            CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, bucketStartTimeNs + 10));
+    events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
+                                                   bucketStartTimeNs + 100));
+    events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
+                                                   bucketStartTimeNs + bucketSizeNs + 1));
+    events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
+                                                   bucketStartTimeNs + 2 * bucketSizeNs - 10));
 
-    events.push_back(CreateAcquireWakelockEvent(
-        attributions1, "wl1", bucketStartTimeNs + 200));
-    events.push_back(CreateReleaseWakelockEvent(
-        attributions1, "wl1", bucketStartTimeNs + bucketSizeNs + 1));
+    events.push_back(CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + 200));
+    events.push_back(
+            CreateReleaseWakelockEvent(attributions1, "wl1", bucketStartTimeNs + bucketSizeNs + 1));
 
-    events.push_back(CreateAcquireWakelockEvent(
-        attributions2, "wl2", bucketStartTimeNs + bucketSizeNs - 100));
-    events.push_back(CreateReleaseWakelockEvent(
-        attributions2, "wl2", bucketStartTimeNs + 2 * bucketSizeNs - 50));
+    events.push_back(CreateAcquireWakelockEvent(attributions2, "wl2",
+                                                bucketStartTimeNs + bucketSizeNs - 100));
+    events.push_back(CreateReleaseWakelockEvent(attributions2, "wl2",
+                                                bucketStartTimeNs + 2 * bucketSizeNs - 50));
 
-    events.push_back(CreateScreenBrightnessChangedEvent(
-        123, bucketStartTimeNs + 11));
-    events.push_back(CreateScreenBrightnessChangedEvent(
-        123, bucketStartTimeNs + 101));
-    events.push_back(CreateScreenBrightnessChangedEvent(
-        123, bucketStartTimeNs + 201));
-    events.push_back(CreateScreenBrightnessChangedEvent(
-        456, bucketStartTimeNs + 203));
-    events.push_back(CreateScreenBrightnessChangedEvent(
-        456, bucketStartTimeNs + bucketSizeNs - 99));
-    events.push_back(CreateScreenBrightnessChangedEvent(
-        456, bucketStartTimeNs + bucketSizeNs - 2));
-    events.push_back(CreateScreenBrightnessChangedEvent(
-        789, bucketStartTimeNs + bucketSizeNs - 1));
-    events.push_back(CreateScreenBrightnessChangedEvent(
-        456, bucketStartTimeNs + bucketSizeNs + 2));
-    events.push_back(CreateScreenBrightnessChangedEvent(
-        789, bucketStartTimeNs + 2 * bucketSizeNs - 11));
-    events.push_back(CreateScreenBrightnessChangedEvent(
-        789, bucketStartTimeNs + 2 * bucketSizeNs - 9));
-    events.push_back(CreateScreenBrightnessChangedEvent(
-        789, bucketStartTimeNs + 2 * bucketSizeNs - 1));
+    events.push_back(CreateScreenBrightnessChangedEvent(123, bucketStartTimeNs + 11));
+    events.push_back(CreateScreenBrightnessChangedEvent(123, bucketStartTimeNs + 101));
+    events.push_back(CreateScreenBrightnessChangedEvent(123, bucketStartTimeNs + 201));
+    events.push_back(CreateScreenBrightnessChangedEvent(456, bucketStartTimeNs + 203));
+    events.push_back(
+            CreateScreenBrightnessChangedEvent(456, bucketStartTimeNs + bucketSizeNs - 99));
+    events.push_back(CreateScreenBrightnessChangedEvent(456, bucketStartTimeNs + bucketSizeNs - 2));
+    events.push_back(CreateScreenBrightnessChangedEvent(789, bucketStartTimeNs + bucketSizeNs - 1));
+    events.push_back(CreateScreenBrightnessChangedEvent(456, bucketStartTimeNs + bucketSizeNs + 2));
+    events.push_back(
+            CreateScreenBrightnessChangedEvent(789, bucketStartTimeNs + 2 * bucketSizeNs - 11));
+    events.push_back(
+            CreateScreenBrightnessChangedEvent(789, bucketStartTimeNs + 2 * bucketSizeNs - 9));
+    events.push_back(
+            CreateScreenBrightnessChangedEvent(789, bucketStartTimeNs + 2 * bucketSizeNs - 1));
 
     sortLogEventsByTimestamp(&events);
 
@@ -136,7 +128,10 @@
     }
 
     ConfigMetricsReportList reports;
-    processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, &reports);
+    vector<uint8_t> buffer;
+    processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * 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);
@@ -147,7 +142,7 @@
     auto data = countMetrics.data(0);
     EXPECT_EQ(data.bucket_info_size(), 1);
     EXPECT_EQ(data.bucket_info(0).count(), 1);
-    EXPECT_EQ(data.bucket_info(0).start_bucket_nanos(), bucketStartTimeNs );
+    EXPECT_EQ(data.bucket_info(0).start_bucket_nanos(), bucketStartTimeNs);
     EXPECT_EQ(data.bucket_info(0).end_bucket_nanos(), bucketStartTimeNs + bucketSizeNs);
     EXPECT_EQ(data.dimensions_in_what().field(), android::util::SCREEN_BRIGHTNESS_CHANGED);
     EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1);
@@ -164,7 +159,8 @@
     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);
     EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), 123);
-    ValidateAttributionUidDimension(data.dimensions_in_condition(), android::util::WAKELOCK_STATE_CHANGED, 111);
+    ValidateAttributionUidDimension(data.dimensions_in_condition(),
+                                    android::util::WAKELOCK_STATE_CHANGED, 111);
 
     data = countMetrics.data(2);
     EXPECT_EQ(data.bucket_info_size(), 1);
@@ -175,7 +171,8 @@
     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);
     EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), 456);
-    ValidateAttributionUidDimension(data.dimensions_in_condition(), android::util::WAKELOCK_STATE_CHANGED, 111);
+    ValidateAttributionUidDimension(data.dimensions_in_condition(),
+                                    android::util::WAKELOCK_STATE_CHANGED, 111);
 
     data = countMetrics.data(3);
     EXPECT_EQ(data.bucket_info_size(), 2);
@@ -189,7 +186,8 @@
     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);
     EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), 456);
-    ValidateAttributionUidDimension(data.dimensions_in_condition(), android::util::WAKELOCK_STATE_CHANGED, 333);
+    ValidateAttributionUidDimension(data.dimensions_in_condition(),
+                                    android::util::WAKELOCK_STATE_CHANGED, 333);
 
     data = countMetrics.data(4);
     EXPECT_EQ(data.bucket_info_size(), 1);
@@ -211,7 +209,8 @@
     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);
     EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), 789);
-    ValidateAttributionUidDimension(data.dimensions_in_condition(), android::util::WAKELOCK_STATE_CHANGED, 111);
+    ValidateAttributionUidDimension(data.dimensions_in_condition(),
+                                    android::util::WAKELOCK_STATE_CHANGED, 111);
 
     data = countMetrics.data(6);
     EXPECT_EQ(data.bucket_info_size(), 1);
@@ -222,7 +221,8 @@
     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);
     EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), 789);
-    ValidateAttributionUidDimension(data.dimensions_in_condition(), android::util::WAKELOCK_STATE_CHANGED, 333);
+    ValidateAttributionUidDimension(data.dimensions_in_condition(),
+                                    android::util::WAKELOCK_STATE_CHANGED, 333);
 }
 
 namespace {
@@ -239,8 +239,8 @@
     auto screenIsOffPredicate = CreateScreenIsOffPredicate();
     auto isSyncingPredicate = CreateIsSyncingPredicate();
     auto syncDimension = isSyncingPredicate.mutable_simple_predicate()->mutable_dimensions();
-    *syncDimension = CreateAttributionUidAndTagDimensions(
-        android::util::SYNC_STATE_CHANGED, {Position::FIRST});
+    *syncDimension = CreateAttributionUidAndTagDimensions(android::util::SYNC_STATE_CHANGED,
+                                                          {Position::FIRST});
     syncDimension->add_child()->set_field(2 /* name field*/);
 
     *config.add_predicate() = screenIsOffPredicate;
@@ -256,8 +256,8 @@
     metric->set_id(StringToId("AppCrashMetric"));
     metric->set_what(appCrashMatcher.id());
     metric->set_condition(combinationPredicate->id());
-    *metric->mutable_dimensions_in_what() = CreateDimensions(
-            android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, {1 /* uid */});
+    *metric->mutable_dimensions_in_what() =
+            CreateDimensions(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, {1 /* uid */});
     *metric->mutable_dimensions_in_condition() = CreateAttributionUidAndTagDimensions(
             android::util::SYNC_STATE_CHANGED, {Position::FIRST});
 
@@ -267,8 +267,8 @@
     auto dimensionWhat = links->mutable_fields_in_what();
     dimensionWhat->set_field(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED);
     dimensionWhat->add_child()->set_field(1);  // uid field.
-    *links->mutable_fields_in_condition() = CreateAttributionUidDimensions(
-            android::util::SYNC_STATE_CHANGED, {Position::FIRST});
+    *links->mutable_fields_in_condition() =
+            CreateAttributionUidDimensions(android::util::SYNC_STATE_CHANGED, {Position::FIRST});
     return config;
 }
 
@@ -279,18 +279,18 @@
     auto config = CreateCountMetricWithLinkConfig();
     int64_t bucketStartTimeNs = 10000000000;
     int64_t bucketSizeNs =
-        TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000LL;
+            TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000LL;
 
     auto processor = CreateStatsLogProcessor(bucketStartTimeNs / NS_PER_SEC, config, cfgKey);
     EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
     EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
-    std::vector<AttributionNode> attributions1 =
-        {CreateAttribution(111, "App1"), CreateAttribution(222, "GMSCoreModule1"),
-         CreateAttribution(222, "GMSCoreModule2")};
+    std::vector<AttributionNode> attributions1 = {CreateAttribution(111, "App1"),
+                                                  CreateAttribution(222, "GMSCoreModule1"),
+                                                  CreateAttribution(222, "GMSCoreModule2")};
 
-    std::vector<AttributionNode> attributions2 =
-        {CreateAttribution(333, "App2"), CreateAttribution(222, "GMSCoreModule1"),
-         CreateAttribution(555, "GMSCoreModule2")};
+    std::vector<AttributionNode> attributions2 = {CreateAttribution(333, "App2"),
+                                                  CreateAttribution(222, "GMSCoreModule1"),
+                                                  CreateAttribution(555, "GMSCoreModule2")};
 
     std::vector<std::unique_ptr<LogEvent>> events;
 
@@ -311,26 +311,26 @@
 
     events.push_back(CreateAppCrashEvent(777, bucketStartTimeNs + bucketSizeNs + 701));
 
-    events.push_back(CreateScreenStateChangedEvent(
-        android::view::DISPLAY_STATE_ON, bucketStartTimeNs + 10));
-    events.push_back(CreateScreenStateChangedEvent(
-        android::view::DISPLAY_STATE_OFF, bucketStartTimeNs + 100));
-    events.push_back(CreateScreenStateChangedEvent(
-        android::view::DISPLAY_STATE_ON, bucketStartTimeNs + 202));
-    events.push_back(CreateScreenStateChangedEvent(
-        android::view::DISPLAY_STATE_OFF, bucketStartTimeNs + bucketSizeNs + 700));
+    events.push_back(
+            CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, bucketStartTimeNs + 10));
+    events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
+                                                   bucketStartTimeNs + 100));
+    events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
+                                                   bucketStartTimeNs + 202));
+    events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
+                                                   bucketStartTimeNs + bucketSizeNs + 700));
 
     events.push_back(CreateSyncStartEvent(attributions1, "ReadEmail", bucketStartTimeNs + 200));
-    events.push_back(CreateSyncEndEvent(attributions1, "ReadEmail",
-        bucketStartTimeNs + bucketSizeNs + 300));
+    events.push_back(
+            CreateSyncEndEvent(attributions1, "ReadEmail", bucketStartTimeNs + bucketSizeNs + 300));
 
     events.push_back(CreateSyncStartEvent(attributions1, "ReadDoc", bucketStartTimeNs + 400));
-    events.push_back(CreateSyncEndEvent(attributions1, "ReadDoc",
-        bucketStartTimeNs + bucketSizeNs - 1));
+    events.push_back(
+            CreateSyncEndEvent(attributions1, "ReadDoc", bucketStartTimeNs + bucketSizeNs - 1));
 
     events.push_back(CreateSyncStartEvent(attributions2, "ReadEmail", bucketStartTimeNs + 400));
-    events.push_back(CreateSyncEndEvent(attributions2, "ReadEmail",
-        bucketStartTimeNs + bucketSizeNs + 600));
+    events.push_back(
+            CreateSyncEndEvent(attributions2, "ReadEmail", bucketStartTimeNs + bucketSizeNs + 600));
 
     sortLogEventsByTimestamp(&events);
 
@@ -339,7 +339,10 @@
     }
 
     ConfigMetricsReportList reports;
-    processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, &reports);
+    vector<uint8_t> buffer;
+    processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * 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);
@@ -363,8 +366,8 @@
     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);
     EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), 111);
-    ValidateAttributionUidAndTagDimension(
-        data.dimensions_in_condition(), android::util::SYNC_STATE_CHANGED, 111, "App1");
+    ValidateAttributionUidAndTagDimension(data.dimensions_in_condition(),
+                                          android::util::SYNC_STATE_CHANGED, 111, "App1");
     EXPECT_EQ(data.bucket_info_size(), 1);
     EXPECT_EQ(data.bucket_info(0).count(), 2);
     EXPECT_EQ(data.bucket_info(0).start_bucket_nanos(), bucketStartTimeNs);
@@ -386,8 +389,8 @@
     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);
     EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), 333);
-    ValidateAttributionUidAndTagDimension(
-        data.dimensions_in_condition(), android::util::SYNC_STATE_CHANGED, 333, "App2");
+    ValidateAttributionUidAndTagDimension(data.dimensions_in_condition(),
+                                          android::util::SYNC_STATE_CHANGED, 333, "App2");
     EXPECT_EQ(data.bucket_info_size(), 2);
     EXPECT_EQ(data.bucket_info(0).count(), 1);
     EXPECT_EQ(data.bucket_info(0).start_bucket_nanos(), bucketStartTimeNs);
@@ -424,8 +427,8 @@
     auto screenIsOffPredicate = CreateScreenIsOffPredicate();
     auto isSyncingPredicate = CreateIsSyncingPredicate();
     auto syncDimension = isSyncingPredicate.mutable_simple_predicate()->mutable_dimensions();
-    *syncDimension = CreateAttributionUidAndTagDimensions(
-        android::util::SYNC_STATE_CHANGED, {Position::FIRST});
+    *syncDimension = CreateAttributionUidAndTagDimensions(android::util::SYNC_STATE_CHANGED,
+                                                          {Position::FIRST});
     syncDimension->add_child()->set_field(2 /* name field */);
 
     *config.add_predicate() = inBatterySaverModePredicate;
@@ -449,26 +452,25 @@
 
 }  // namespace
 
-
 TEST(DimensionInConditionE2eTest, TestDurationMetricNoLink) {
-    for (auto aggregationType : { DurationMetric::SUM, DurationMetric::MAX_SPARSE}) {
+    for (auto aggregationType : {DurationMetric::SUM, DurationMetric::MAX_SPARSE}) {
         ConfigKey cfgKey;
         auto config = CreateDurationMetricConfigNoLink(aggregationType);
         int64_t bucketStartTimeNs = 10000000000;
         int64_t bucketSizeNs =
-            TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
+                TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
 
         auto processor = CreateStatsLogProcessor(bucketStartTimeNs / NS_PER_SEC, config, cfgKey);
         EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
         EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
 
-        std::vector<AttributionNode> attributions1 =
-            {CreateAttribution(111, "App1"), CreateAttribution(222, "GMSCoreModule1"),
-             CreateAttribution(222, "GMSCoreModule2")};
+        std::vector<AttributionNode> attributions1 = {CreateAttribution(111, "App1"),
+                                                      CreateAttribution(222, "GMSCoreModule1"),
+                                                      CreateAttribution(222, "GMSCoreModule2")};
 
-        std::vector<AttributionNode> attributions2 =
-            {CreateAttribution(333, "App2"), CreateAttribution(222, "GMSCoreModule1"),
-             CreateAttribution(555, "GMSCoreModule2")};
+        std::vector<AttributionNode> attributions2 = {CreateAttribution(333, "App2"),
+                                                      CreateAttribution(222, "GMSCoreModule1"),
+                                                      CreateAttribution(555, "GMSCoreModule2")};
 
         std::vector<std::unique_ptr<LogEvent>> events;
 
@@ -485,26 +487,26 @@
         events.push_back(CreateBatterySaverOnEvent(bucketStartTimeNs + bucketSizeNs + 870));
         events.push_back(CreateBatterySaverOffEvent(bucketStartTimeNs + bucketSizeNs + 900));
 
-        events.push_back(CreateScreenStateChangedEvent(
-            android::view::DISPLAY_STATE_ON, bucketStartTimeNs + 10));
-        events.push_back(CreateScreenStateChangedEvent(
-            android::view::DISPLAY_STATE_OFF, bucketStartTimeNs + 100));
-        events.push_back(CreateScreenStateChangedEvent(
-            android::view::DISPLAY_STATE_ON, bucketStartTimeNs + 202));
-        events.push_back(CreateScreenStateChangedEvent(
-            android::view::DISPLAY_STATE_OFF, bucketStartTimeNs + bucketSizeNs + 800));
+        events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
+                                                       bucketStartTimeNs + 10));
+        events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
+                                                       bucketStartTimeNs + 100));
+        events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
+                                                       bucketStartTimeNs + 202));
+        events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
+                                                       bucketStartTimeNs + bucketSizeNs + 800));
 
         events.push_back(CreateSyncStartEvent(attributions1, "ReadEmail", bucketStartTimeNs + 200));
         events.push_back(CreateSyncEndEvent(attributions1, "ReadEmail",
-            bucketStartTimeNs + bucketSizeNs + 300));
+                                            bucketStartTimeNs + bucketSizeNs + 300));
 
         events.push_back(CreateSyncStartEvent(attributions1, "ReadDoc", bucketStartTimeNs + 400));
-        events.push_back(CreateSyncEndEvent(attributions1, "ReadDoc",
-            bucketStartTimeNs + bucketSizeNs - 1));
+        events.push_back(
+                CreateSyncEndEvent(attributions1, "ReadDoc", bucketStartTimeNs + bucketSizeNs - 1));
 
         events.push_back(CreateSyncStartEvent(attributions2, "ReadEmail", bucketStartTimeNs + 401));
         events.push_back(CreateSyncEndEvent(attributions2, "ReadEmail",
-            bucketStartTimeNs + bucketSizeNs + 700));
+                                            bucketStartTimeNs + bucketSizeNs + 700));
 
         sortLogEventsByTimestamp(&events);
 
@@ -513,7 +515,10 @@
         }
 
         ConfigMetricsReportList reports;
-        processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, &reports);
+        vector<uint8_t> buffer;
+        processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * 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);
@@ -534,8 +539,8 @@
 
         data = metrics.data(1);
         EXPECT_FALSE(data.dimensions_in_what().has_field());
-        ValidateAttributionUidAndTagDimension(
-            data.dimensions_in_condition(), android::util::SYNC_STATE_CHANGED, 111, "App1");
+        ValidateAttributionUidAndTagDimension(data.dimensions_in_condition(),
+                                              android::util::SYNC_STATE_CHANGED, 111, "App1");
         EXPECT_EQ(data.bucket_info_size(), 2);
         EXPECT_EQ(data.bucket_info(0).duration_nanos(), 500 - 201 + bucketSizeNs - 600);
         EXPECT_EQ(data.bucket_info(0).start_bucket_nanos(), bucketStartTimeNs);
@@ -546,8 +551,8 @@
 
         data = metrics.data(2);
         EXPECT_FALSE(data.dimensions_in_what().has_field());
-        ValidateAttributionUidAndTagDimension(
-            data.dimensions_in_condition(), android::util::SYNC_STATE_CHANGED, 333, "App2");
+        ValidateAttributionUidAndTagDimension(data.dimensions_in_condition(),
+                                              android::util::SYNC_STATE_CHANGED, 333, "App2");
         EXPECT_EQ(data.bucket_info_size(), 2);
         EXPECT_EQ(data.bucket_info(0).duration_nanos(), 500 - 401 + bucketSizeNs - 600);
         EXPECT_EQ(data.bucket_info(0).start_bucket_nanos(), bucketStartTimeNs);
@@ -572,13 +577,13 @@
     auto screenIsOffPredicate = CreateScreenIsOffPredicate();
     auto isSyncingPredicate = CreateIsSyncingPredicate();
     auto syncDimension = isSyncingPredicate.mutable_simple_predicate()->mutable_dimensions();
-    *syncDimension = CreateAttributionUidAndTagDimensions(
-        android::util::SYNC_STATE_CHANGED, {Position::FIRST});
+    *syncDimension = CreateAttributionUidAndTagDimensions(android::util::SYNC_STATE_CHANGED,
+                                                          {Position::FIRST});
     syncDimension->add_child()->set_field(2 /* name field */);
 
     auto isInBackgroundPredicate = CreateIsInBackgroundPredicate();
     *isInBackgroundPredicate.mutable_simple_predicate()->mutable_dimensions() =
-        CreateDimensions(android::util::ACTIVITY_FOREGROUND_STATE_CHANGED, {1 /* uid field */ });
+            CreateDimensions(android::util::ACTIVITY_FOREGROUND_STATE_CHANGED, {1 /* uid field */});
 
     *config.add_predicate() = screenIsOffPredicate;
     *config.add_predicate() = isSyncingPredicate;
@@ -594,8 +599,8 @@
     metric->set_id(StringToId("AppInBackgroundMetric"));
     metric->set_what(isInBackgroundPredicate.id());
     metric->set_condition(combinationPredicate->id());
-    *metric->mutable_dimensions_in_what() = CreateDimensions(
-        android::util::ACTIVITY_FOREGROUND_STATE_CHANGED, {1 /* uid field */ });
+    *metric->mutable_dimensions_in_what() =
+            CreateDimensions(android::util::ACTIVITY_FOREGROUND_STATE_CHANGED, {1 /* uid field */});
     *metric->mutable_dimensions_in_condition() = CreateAttributionUidAndTagDimensions(
             android::util::SYNC_STATE_CHANGED, {Position::FIRST});
 
@@ -605,32 +610,32 @@
     auto dimensionWhat = links->mutable_fields_in_what();
     dimensionWhat->set_field(android::util::ACTIVITY_FOREGROUND_STATE_CHANGED);
     dimensionWhat->add_child()->set_field(1);  // uid field.
-    *links->mutable_fields_in_condition() = CreateAttributionUidDimensions(
-            android::util::SYNC_STATE_CHANGED, {Position::FIRST});
+    *links->mutable_fields_in_condition() =
+            CreateAttributionUidDimensions(android::util::SYNC_STATE_CHANGED, {Position::FIRST});
     return config;
 }
 
 }  // namespace
 
 TEST(DimensionInConditionE2eTest, TestDurationMetricWithLink) {
-    for (auto aggregationType : { DurationMetric::SUM, DurationMetric::MAX_SPARSE}) {
+    for (auto aggregationType : {DurationMetric::SUM, DurationMetric::MAX_SPARSE}) {
         ConfigKey cfgKey;
         auto config = CreateDurationMetricConfigWithLink(aggregationType);
         int64_t bucketStartTimeNs = 10000000000;
         int64_t bucketSizeNs =
-            TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
+                TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
 
         auto processor = CreateStatsLogProcessor(bucketStartTimeNs / NS_PER_SEC, config, cfgKey);
         EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
         EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
 
-        std::vector<AttributionNode> attributions1 =
-            {CreateAttribution(111, "App1"), CreateAttribution(222, "GMSCoreModule1"),
-             CreateAttribution(222, "GMSCoreModule2")};
+        std::vector<AttributionNode> attributions1 = {CreateAttribution(111, "App1"),
+                                                      CreateAttribution(222, "GMSCoreModule1"),
+                                                      CreateAttribution(222, "GMSCoreModule2")};
 
-        std::vector<AttributionNode> attributions2 =
-            {CreateAttribution(333, "App2"), CreateAttribution(222, "GMSCoreModule1"),
-             CreateAttribution(555, "GMSCoreModule2")};
+        std::vector<AttributionNode> attributions2 = {CreateAttribution(333, "App2"),
+                                                      CreateAttribution(222, "GMSCoreModule1"),
+                                                      CreateAttribution(555, "GMSCoreModule2")};
 
         std::vector<std::unique_ptr<LogEvent>> events;
 
@@ -643,26 +648,26 @@
         events.push_back(CreateMoveToBackgroundEvent(333, bucketStartTimeNs + 399));
         events.push_back(CreateMoveToForegroundEvent(333, bucketStartTimeNs + bucketSizeNs + 800));
 
-        events.push_back(CreateScreenStateChangedEvent(
-            android::view::DISPLAY_STATE_ON, bucketStartTimeNs + 10));
-        events.push_back(CreateScreenStateChangedEvent(
-            android::view::DISPLAY_STATE_OFF, bucketStartTimeNs + 100));
-        events.push_back(CreateScreenStateChangedEvent(
-            android::view::DISPLAY_STATE_ON, bucketStartTimeNs + 202));
-        events.push_back(CreateScreenStateChangedEvent(
-            android::view::DISPLAY_STATE_OFF, bucketStartTimeNs + bucketSizeNs + 801));
+        events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
+                                                       bucketStartTimeNs + 10));
+        events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
+                                                       bucketStartTimeNs + 100));
+        events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
+                                                       bucketStartTimeNs + 202));
+        events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
+                                                       bucketStartTimeNs + bucketSizeNs + 801));
 
         events.push_back(CreateSyncStartEvent(attributions1, "ReadEmail", bucketStartTimeNs + 200));
         events.push_back(CreateSyncEndEvent(attributions1, "ReadEmail",
-            bucketStartTimeNs + bucketSizeNs + 300));
+                                            bucketStartTimeNs + bucketSizeNs + 300));
 
         events.push_back(CreateSyncStartEvent(attributions1, "ReadDoc", bucketStartTimeNs + 400));
-        events.push_back(CreateSyncEndEvent(attributions1, "ReadDoc",
-            bucketStartTimeNs + bucketSizeNs - 1));
+        events.push_back(
+                CreateSyncEndEvent(attributions1, "ReadDoc", bucketStartTimeNs + bucketSizeNs - 1));
 
         events.push_back(CreateSyncStartEvent(attributions2, "ReadEmail", bucketStartTimeNs + 401));
         events.push_back(CreateSyncEndEvent(attributions2, "ReadEmail",
-            bucketStartTimeNs + bucketSizeNs + 700));
+                                            bucketStartTimeNs + bucketSizeNs + 700));
 
         sortLogEventsByTimestamp(&events);
 
@@ -671,7 +676,10 @@
         }
 
         ConfigMetricsReportList reports;
-        processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, &reports);
+        vector<uint8_t> buffer;
+        processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * 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);
@@ -691,8 +699,8 @@
         data = metrics.data(1);
         EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1);
         EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), 111);
-        ValidateAttributionUidAndTagDimension(
-            data.dimensions_in_condition(), android::util::SYNC_STATE_CHANGED, 111, "App1");
+        ValidateAttributionUidAndTagDimension(data.dimensions_in_condition(),
+                                              android::util::SYNC_STATE_CHANGED, 111, "App1");
         EXPECT_EQ(data.bucket_info_size(), 2);
         EXPECT_EQ(data.bucket_info(0).duration_nanos(), bucketSizeNs - 201);
         EXPECT_EQ(data.bucket_info(0).start_bucket_nanos(), bucketStartTimeNs);
@@ -704,8 +712,8 @@
         data = metrics.data(2);
         EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1);
         EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), 333);
-        ValidateAttributionUidAndTagDimension(
-            data.dimensions_in_condition(), android::util::SYNC_STATE_CHANGED, 333, "App2");
+        ValidateAttributionUidAndTagDimension(data.dimensions_in_condition(),
+                                              android::util::SYNC_STATE_CHANGED, 333, "App2");
         EXPECT_EQ(data.bucket_info_size(), 2);
         EXPECT_EQ(data.bucket_info(0).duration_nanos(), bucketSizeNs - 401);
         EXPECT_EQ(data.bucket_info(0).start_bucket_nanos(), bucketStartTimeNs);
diff --git a/cmds/statsd/tests/e2e/GaugeMetric_e2e_test.cpp b/cmds/statsd/tests/e2e/GaugeMetric_e2e_test.cpp
index a80fdc5..674d810 100644
--- a/cmds/statsd/tests/e2e/GaugeMetric_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/GaugeMetric_e2e_test.cpp
@@ -140,7 +140,10 @@
         processor->OnLogEvent(event.get());
     }
     ConfigMetricsReportList reports;
-    processor->onDumpReport(cfgKey, bucketStartTimeNs + 3 * bucketSizeNs, &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;
diff --git a/cmds/statsd/tests/e2e/MetricConditionLink_e2e_test.cpp b/cmds/statsd/tests/e2e/MetricConditionLink_e2e_test.cpp
index 233031c..d005181 100644
--- a/cmds/statsd/tests/e2e/MetricConditionLink_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/MetricConditionLink_e2e_test.cpp
@@ -95,8 +95,10 @@
 }
 }  // namespace
 
-
-TEST(MetricConditionLinkE2eTest, TestMultiplePredicatesAndLinks) {
+// If we want to test multiple dump data, we must do it in separate tests, because in the e2e tests,
+// we should use the real API which will clear the data after dump data is called.
+// TODO: better refactor the code so that the tests are not so verbose.
+TEST(MetricConditionLinkE2eTest, TestMultiplePredicatesAndLinks1) {
     auto config = CreateStatsdConfig();
     uint64_t bucketStartTimeNs = 10000000000;
     uint64_t bucketSizeNs =
@@ -195,7 +197,10 @@
         processor->OnLogEvent(event.get());
     }
     ConfigMetricsReportList reports;
-    processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs - 1, &reports);
+    vector<uint8_t> buffer;
+    processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * 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);
     EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data_size(), 1);
@@ -208,16 +213,115 @@
     // Uid field.
     EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1);
     EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), appUid);
+}
 
-    reports.Clear();
-    processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, &reports);
+TEST(MetricConditionLinkE2eTest, TestMultiplePredicatesAndLinks2) {
+    auto config = CreateStatsdConfig();
+    uint64_t bucketStartTimeNs = 10000000000;
+    uint64_t bucketSizeNs =
+            TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000LL;
+
+    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 appUid = 123;
+    auto crashEvent1 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 1);
+    auto crashEvent2 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 201);
+    auto crashEvent3 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 2 * bucketSizeNs - 101);
+
+    auto crashEvent4 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 51);
+    auto crashEvent5 = CreateAppCrashEvent(appUid, bucketStartTimeNs + bucketSizeNs + 299);
+    auto crashEvent6 = CreateAppCrashEvent(appUid, bucketStartTimeNs + bucketSizeNs + 2001);
+
+    auto crashEvent7 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 16);
+    auto crashEvent8 = CreateAppCrashEvent(appUid, bucketStartTimeNs + bucketSizeNs + 249);
+
+    auto crashEvent9 = CreateAppCrashEvent(appUid, bucketStartTimeNs + bucketSizeNs + 351);
+    auto crashEvent10 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 2 * bucketSizeNs - 2);
+
+    auto screenTurnedOnEvent = CreateScreenStateChangedEvent(
+            android::view::DisplayStateEnum::DISPLAY_STATE_ON, bucketStartTimeNs + 2);
+    auto screenTurnedOffEvent = CreateScreenStateChangedEvent(
+            android::view::DisplayStateEnum::DISPLAY_STATE_OFF, bucketStartTimeNs + 200);
+    auto screenTurnedOnEvent2 =
+            CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
+                                          bucketStartTimeNs + 2 * bucketSizeNs - 100);
+
+    std::vector<AttributionNode> attributions = {CreateAttribution(appUid, "App1"),
+                                                 CreateAttribution(appUid + 1, "GMSCoreModule1")};
+    auto syncOnEvent1 = CreateSyncStartEvent(attributions, "ReadEmail", bucketStartTimeNs + 50);
+    auto syncOffEvent1 =
+            CreateSyncEndEvent(attributions, "ReadEmail", bucketStartTimeNs + bucketSizeNs + 300);
+    auto syncOnEvent2 =
+            CreateSyncStartEvent(attributions, "ReadDoc", bucketStartTimeNs + bucketSizeNs + 2000);
+
+    auto moveToBackgroundEvent1 = CreateMoveToBackgroundEvent(appUid, bucketStartTimeNs + 15);
+    auto moveToForegroundEvent1 =
+            CreateMoveToForegroundEvent(appUid, bucketStartTimeNs + bucketSizeNs + 250);
+
+    auto moveToBackgroundEvent2 =
+            CreateMoveToBackgroundEvent(appUid, bucketStartTimeNs + bucketSizeNs + 350);
+    auto moveToForegroundEvent2 =
+            CreateMoveToForegroundEvent(appUid, bucketStartTimeNs + 2 * bucketSizeNs - 1);
+
+    /*
+                    bucket #1                               bucket #2
+
+
+       |      |   |  |                      |   |          |        |   |   |     (crashEvents)
+    |-------------------------------------|-----------------------------------|---------
+
+             |                                           |                        (MoveToBkground)
+
+                                             |                               |    (MoveToForeground)
+
+                |                                                 |                (SyncIsOn)
+                                                  |                                (SyncIsOff)
+          |                                                               |        (ScreenIsOn)
+                   |                                                               (ScreenIsOff)
+    */
+    std::vector<std::unique_ptr<LogEvent>> events;
+    events.push_back(std::move(crashEvent1));
+    events.push_back(std::move(crashEvent2));
+    events.push_back(std::move(crashEvent3));
+    events.push_back(std::move(crashEvent4));
+    events.push_back(std::move(crashEvent5));
+    events.push_back(std::move(crashEvent6));
+    events.push_back(std::move(crashEvent7));
+    events.push_back(std::move(crashEvent8));
+    events.push_back(std::move(crashEvent9));
+    events.push_back(std::move(crashEvent10));
+    events.push_back(std::move(screenTurnedOnEvent));
+    events.push_back(std::move(screenTurnedOffEvent));
+    events.push_back(std::move(screenTurnedOnEvent2));
+    events.push_back(std::move(syncOnEvent1));
+    events.push_back(std::move(syncOffEvent1));
+    events.push_back(std::move(syncOnEvent2));
+    events.push_back(std::move(moveToBackgroundEvent1));
+    events.push_back(std::move(moveToForegroundEvent1));
+    events.push_back(std::move(moveToBackgroundEvent2));
+    events.push_back(std::move(moveToForegroundEvent2));
+
+    sortLogEventsByTimestamp(&events);
+
+    for (const auto& event : events) {
+        processor->OnLogEvent(event.get());
+    }
+    ConfigMetricsReportList reports;
+    vector<uint8_t> buffer;
+
+    processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * 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);
     EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data_size(), 1);
     EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data(0).bucket_info_size(), 2);
     EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data(0).bucket_info(0).count(), 1);
     EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data(0).bucket_info(1).count(), 3);
-    data = reports.reports(0).metrics(0).count_metrics().data(0);
+    auto data = reports.reports(0).metrics(0).count_metrics().data(0);
     // Validate dimension value.
     EXPECT_EQ(data.dimensions_in_what().field(),
               android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED);
diff --git a/cmds/statsd/tests/e2e/WakelockDuration_e2e_test.cpp b/cmds/statsd/tests/e2e/WakelockDuration_e2e_test.cpp
index a99dbe8..3b25694b 100644
--- a/cmds/statsd/tests/e2e/WakelockDuration_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/WakelockDuration_e2e_test.cpp
@@ -114,7 +114,7 @@
 
 }  // namespace
 
-TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForSumDuration) {
+TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForSumDuration1) {
     ConfigKey cfgKey;
     auto config = CreateStatsdConfig(DurationMetric::SUM);
     uint64_t bucketStartTimeNs = 10000000000;
@@ -124,8 +124,11 @@
     EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
     EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
     FeedEvents(config, processor);
+    vector<uint8_t> buffer;
     ConfigMetricsReportList reports;
-    processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs - 1, &reports);
+    processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * 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);
@@ -142,15 +145,30 @@
     // The wakelock holding interval starts from the screen off event and to the end of the 1st
     // bucket.
     EXPECT_EQ((unsigned long long)data.bucket_info(0).duration_nanos(), bucketSizeNs - 200);
+}
 
-    reports.Clear();
-    processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, &reports);
+TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForSumDuration2) {
+    ConfigKey cfgKey;
+    auto config = CreateStatsdConfig(DurationMetric::SUM);
+    uint64_t bucketStartTimeNs = 10000000000;
+    uint64_t bucketSizeNs =
+            TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
+    auto processor = CreateStatsLogProcessor(bucketStartTimeNs / NS_PER_SEC, config, cfgKey);
+    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+    EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
+    FeedEvents(config, processor);
+    vector<uint8_t> buffer;
+    ConfigMetricsReportList reports;
+
+    processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * 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);
     EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data_size(), 1);
     // Dump the report after the end of 2nd bucket.
     EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data(0).bucket_info_size(), 2);
-    data = reports.reports(0).metrics(0).duration_metrics().data(0);
+    auto data = reports.reports(0).metrics(0).duration_metrics().data(0);
     // Validate dimension value.
     ValidateAttributionUidDimension(data.dimensions_in_what(),
                                     android::util::WAKELOCK_STATE_CHANGED, 111);
@@ -162,6 +180,19 @@
     // The wakelock holding interval in the 2nd bucket starts at the beginning of the bucket and
     // ends at the second screen on event.
     EXPECT_EQ((unsigned long long)data.bucket_info(1).duration_nanos(), 500UL);
+}
+TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForSumDuration3) {
+    ConfigKey cfgKey;
+    auto config = CreateStatsdConfig(DurationMetric::SUM);
+    uint64_t bucketStartTimeNs = 10000000000;
+    uint64_t bucketSizeNs =
+            TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
+    auto processor = CreateStatsLogProcessor(bucketStartTimeNs / NS_PER_SEC, config, cfgKey);
+    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+    EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
+    FeedEvents(config, processor);
+    vector<uint8_t> buffer;
+    ConfigMetricsReportList reports;
 
     std::vector<std::unique_ptr<LogEvent>> events;
     events.push_back(
@@ -175,13 +206,15 @@
     for (const auto& event : events) {
         processor->OnLogEvent(event.get());
     }
-    reports.Clear();
-    processor->onDumpReport(cfgKey, bucketStartTimeNs + 6 * bucketSizeNs + 1, &reports);
+
+    processor->onDumpReport(cfgKey, bucketStartTimeNs + 6 * 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);
     EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data_size(), 1);
     EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data(0).bucket_info_size(), 6);
-    data = reports.reports(0).metrics(0).duration_metrics().data(0);
+    auto data = reports.reports(0).metrics(0).duration_metrics().data(0);
     ValidateAttributionUidDimension(data.dimensions_in_what(),
                                     android::util::WAKELOCK_STATE_CHANGED, 111);
     // The last wakelock holding spans 4 buckets.
@@ -191,7 +224,7 @@
     EXPECT_EQ((unsigned long long)data.bucket_info(5).duration_nanos(), 100UL);
 }
 
-TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForMaxDuration) {
+TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForMaxDuration1) {
     ConfigKey cfgKey;
     auto config = CreateStatsdConfig(DurationMetric::MAX_SPARSE);
     uint64_t bucketStartTimeNs = 10000000000;
@@ -202,15 +235,35 @@
     EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
     FeedEvents(config, processor);
     ConfigMetricsReportList reports;
-    processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs - 1, &reports);
+    vector<uint8_t> buffer;
+    processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * 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);
-    // Nothing has ended in the first bucket.
-    EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data_size(), 0);
 
-    reports.Clear();
-    processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, &reports);
+    // When using ProtoOutputStream, if nothing written to a sub msg, it won't be treated as
+    // one. It was previsouly 1 because we had a fake onDumpReport which calls add_metric() by
+    // itself.
+    EXPECT_EQ(0, reports.reports(0).metrics_size());
+}
+
+TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForMaxDuration2) {
+    ConfigKey cfgKey;
+    auto config = CreateStatsdConfig(DurationMetric::MAX_SPARSE);
+    uint64_t bucketStartTimeNs = 10000000000;
+    uint64_t bucketSizeNs =
+            TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
+    auto processor = CreateStatsLogProcessor(bucketStartTimeNs / NS_PER_SEC, config, cfgKey);
+    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+    EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
+    FeedEvents(config, processor);
+    ConfigMetricsReportList reports;
+    vector<uint8_t> buffer;
+    processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * 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);
     EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data_size(), 1);
@@ -222,6 +275,20 @@
                                     android::util::WAKELOCK_STATE_CHANGED, 111);
     // The max is acquire event for wl1 to screen off start.
     EXPECT_EQ((unsigned long long)data.bucket_info(0).duration_nanos(), bucketSizeNs + 2 - 200);
+}
+
+TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForMaxDuration3) {
+    ConfigKey cfgKey;
+    auto config = CreateStatsdConfig(DurationMetric::MAX_SPARSE);
+    uint64_t bucketStartTimeNs = 10000000000;
+    uint64_t bucketSizeNs =
+            TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
+    auto processor = CreateStatsLogProcessor(bucketStartTimeNs / NS_PER_SEC, config, cfgKey);
+    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+    EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
+    FeedEvents(config, processor);
+    ConfigMetricsReportList reports;
+    vector<uint8_t> buffer;
 
     std::vector<std::unique_ptr<LogEvent>> events;
     events.push_back(
@@ -235,13 +302,15 @@
     for (const auto& event : events) {
         processor->OnLogEvent(event.get());
     }
-    reports.Clear();
-    processor->onDumpReport(cfgKey, bucketStartTimeNs + 6 * bucketSizeNs + 1, &reports);
+
+    processor->onDumpReport(cfgKey, bucketStartTimeNs + 6 * 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);
     EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data_size(), 1);
     EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data(0).bucket_info_size(), 2);
-    data = reports.reports(0).metrics(0).duration_metrics().data(0);
+    auto data = reports.reports(0).metrics(0).duration_metrics().data(0);
     ValidateAttributionUidDimension(data.dimensions_in_what(),
                                     android::util::WAKELOCK_STATE_CHANGED, 111);
     // The last wakelock holding spans 4 buckets.
diff --git a/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp b/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp
index 87a1079..1e71b73 100644
--- a/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp
@@ -13,7 +13,6 @@
 // limitations under the License.
 
 #include "src/metrics/CountMetricProducer.h"
-#include "src/dimension.h"
 #include "src/stats_log_util.h"
 #include "metrics_test_helper.h"
 #include "tests/statsd_test_util.h"
diff --git a/cmds/statsd/tests/metrics/EventMetricProducer_test.cpp b/cmds/statsd/tests/metrics/EventMetricProducer_test.cpp
index 3deab37..8246268 100644
--- a/cmds/statsd/tests/metrics/EventMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/EventMetricProducer_test.cpp
@@ -13,7 +13,6 @@
 // limitations under the License.
 
 #include "src/metrics/EventMetricProducer.h"
-#include "src/dimension.h"
 #include "metrics_test_helper.h"
 #include "tests/statsd_test_util.h"
 
diff --git a/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp b/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp
index 470d4d0..26f7c26 100644
--- a/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp
@@ -80,9 +80,10 @@
     gaugeProducer.onDataPulled(allData);
     EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
     auto it = gaugeProducer.mCurrentSlicedBucket->begin()->second.front().mFields->begin();
-    EXPECT_EQ(10, it->second.value_int());
+    EXPECT_EQ(INT, it->mValue.getType());
+    EXPECT_EQ(10, it->mValue.int_value);
     it++;
-    EXPECT_EQ(11, it->second.value_int());
+    EXPECT_EQ(11, it->mValue.int_value);
     EXPECT_EQ(0UL, gaugeProducer.mPastBuckets.size());
 
     allData.clear();
@@ -96,16 +97,20 @@
     gaugeProducer.onDataPulled(allData);
     EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
     it = gaugeProducer.mCurrentSlicedBucket->begin()->second.front().mFields->begin();
-    EXPECT_EQ(24, it->second.value_int());
+    EXPECT_EQ(INT, it->mValue.getType());
+    EXPECT_EQ(24, it->mValue.int_value);
     it++;
-    EXPECT_EQ(25, it->second.value_int());
+    EXPECT_EQ(INT, it->mValue.getType());
+    EXPECT_EQ(25, it->mValue.int_value);
     // One dimension.
     EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size());
     EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.begin()->second.size());
     it = gaugeProducer.mPastBuckets.begin()->second.back().mGaugeAtoms.front().mFields->begin();
-    EXPECT_EQ(10L, it->second.value_int());
+    EXPECT_EQ(INT, it->mValue.getType());
+    EXPECT_EQ(10L, it->mValue.int_value);
     it++;
-    EXPECT_EQ(11L, it->second.value_int());
+    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);
@@ -114,9 +119,11 @@
     EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size());
     EXPECT_EQ(2UL, gaugeProducer.mPastBuckets.begin()->second.size());
     it = gaugeProducer.mPastBuckets.begin()->second.back().mGaugeAtoms.front().mFields->begin();
-    EXPECT_EQ(24L, it->second.value_int());
+    EXPECT_EQ(INT, it->mValue.getType());
+    EXPECT_EQ(24L, it->mValue.int_value);
     it++;
-    EXPECT_EQ(25L, it->second.value_int());
+    EXPECT_EQ(INT, it->mValue.getType());
+    EXPECT_EQ(25L, it->mValue.int_value);
     EXPECT_EQ(2UL, gaugeProducer.mPastBuckets.begin()->second.back().mBucketNum);
 }
 
@@ -230,7 +237,7 @@
     EXPECT_EQ(1, gaugeProducer.mCurrentSlicedBucket->begin()
                          ->second.front()
                          .mFields->begin()
-                         ->second.value_int());
+                         ->mValue.int_value);
 
     gaugeProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
     EXPECT_EQ(1UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
@@ -240,7 +247,7 @@
     EXPECT_EQ(2, gaugeProducer.mCurrentSlicedBucket->begin()
                          ->second.front()
                          .mFields->begin()
-                         ->second.value_int());
+                         ->mValue.int_value);
 
     allData.clear();
     event = make_shared<LogEvent>(tagId, bucketStartTimeNs + bucketSizeNs + 1);
@@ -254,7 +261,7 @@
     EXPECT_EQ(3, gaugeProducer.mCurrentSlicedBucket->begin()
                          ->second.front()
                          .mFields->begin()
-                         ->second.value_int());
+                         ->mValue.int_value);
 }
 
 TEST(GaugeMetricProducerTest, TestWithCondition) {
@@ -288,9 +295,10 @@
 
     gaugeProducer.onConditionChanged(true, bucketStartTimeNs + 8);
     EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
-    EXPECT_EQ(100,
-        gaugeProducer.mCurrentSlicedBucket->begin()->
-            second.front().mFields->begin()->second.value_int());
+    EXPECT_EQ(100, gaugeProducer.mCurrentSlicedBucket->begin()
+                           ->second.front()
+                           .mFields->begin()
+                           ->mValue.int_value);
     EXPECT_EQ(0UL, gaugeProducer.mPastBuckets.size());
 
     vector<shared_ptr<LogEvent>> allData;
@@ -303,19 +311,26 @@
     gaugeProducer.onDataPulled(allData);
 
     EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
-    EXPECT_EQ(110,
-        gaugeProducer.mCurrentSlicedBucket->begin()->
-            second.front().mFields->begin()->second.value_int());
+    EXPECT_EQ(110, gaugeProducer.mCurrentSlicedBucket->begin()
+                           ->second.front()
+                           .mFields->begin()
+                           ->mValue.int_value);
     EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size());
-    EXPECT_EQ(100, gaugeProducer.mPastBuckets.begin()->second.back()
-        .mGaugeAtoms.front().mFields->begin()->second.value_int());
+    EXPECT_EQ(100, gaugeProducer.mPastBuckets.begin()
+                           ->second.back()
+                           .mGaugeAtoms.front()
+                           .mFields->begin()
+                           ->mValue.int_value);
 
     gaugeProducer.onConditionChanged(false, bucket2StartTimeNs + 10);
     gaugeProducer.flushIfNeededLocked(bucket3StartTimeNs + 10);
     EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size());
     EXPECT_EQ(2UL, gaugeProducer.mPastBuckets.begin()->second.size());
-    EXPECT_EQ(110L, gaugeProducer.mPastBuckets.begin()->second.back()
-        .mGaugeAtoms.front().mFields->begin()->second.value_int());
+    EXPECT_EQ(110L, gaugeProducer.mPastBuckets.begin()
+                            ->second.back()
+                            .mGaugeAtoms.front()
+                            .mFields->begin()
+                            ->mValue.int_value);
     EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.begin()->second.back().mBucketNum);
 }
 
@@ -353,9 +368,10 @@
 
     gaugeProducer.onDataPulled({event1});
     EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
-    EXPECT_EQ(13L,
-        gaugeProducer.mCurrentSlicedBucket->begin()->
-            second.front().mFields->begin()->second.value_int());
+    EXPECT_EQ(13L, gaugeProducer.mCurrentSlicedBucket->begin()
+                           ->second.front()
+                           .mFields->begin()
+                           ->mValue.int_value);
     EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), 0U);
 
     std::shared_ptr<LogEvent> event2 =
@@ -366,9 +382,10 @@
 
     gaugeProducer.onDataPulled({event2});
     EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
-    EXPECT_EQ(15L,
-        gaugeProducer.mCurrentSlicedBucket->begin()->
-            second.front().mFields->begin()->second.value_int());
+    EXPECT_EQ(15L, gaugeProducer.mCurrentSlicedBucket->begin()
+                           ->second.front()
+                           .mFields->begin()
+                           ->mValue.int_value);
     EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
             event2->GetTimestampNs() / NS_PER_SEC + refPeriodSec);
 
@@ -380,9 +397,10 @@
 
     gaugeProducer.onDataPulled({event3});
     EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
-    EXPECT_EQ(26L,
-        gaugeProducer.mCurrentSlicedBucket->begin()->
-            second.front().mFields->begin()->second.value_int());
+    EXPECT_EQ(26L, gaugeProducer.mCurrentSlicedBucket->begin()
+                           ->second.front()
+                           .mFields->begin()
+                           ->mValue.int_value);
     EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
             event2->GetTimestampNs() / NS_PER_SEC + refPeriodSec);
 
diff --git a/cmds/statsd/tests/metrics/MaxDurationTracker_test.cpp b/cmds/statsd/tests/metrics/MaxDurationTracker_test.cpp
index 2658e4e..3397f14 100644
--- a/cmds/statsd/tests/metrics/MaxDurationTracker_test.cpp
+++ b/cmds/statsd/tests/metrics/MaxDurationTracker_test.cpp
@@ -53,7 +53,8 @@
     const HashableDimensionKey key1 = getMockedDimensionKey(TagId, 1, "1");
     const HashableDimensionKey key2 = getMockedDimensionKey(TagId, 1, "2");
 
-    FieldMatcher dimensionInCondition;
+    vector<Matcher> dimensionInCondition;
+
     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
 
     unordered_map<MetricDimensionKey, vector<DurationBucket>> buckets;
@@ -89,7 +90,7 @@
     const HashableDimensionKey key1 = getMockedDimensionKey(TagId, 1, "1");
     const HashableDimensionKey key2 = getMockedDimensionKey(TagId, 1, "2");
 
-    FieldMatcher dimensionInCondition;
+    vector<Matcher> dimensionInCondition;
     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
 
     unordered_map<MetricDimensionKey, vector<DurationBucket>> buckets;
@@ -126,7 +127,7 @@
     const std::vector<HashableDimensionKey> conditionKey = {getMockedDimensionKey(TagId, 4, "1")};
     const HashableDimensionKey key1 = getMockedDimensionKey(TagId, 1, "1");
     const HashableDimensionKey key2 = getMockedDimensionKey(TagId, 1, "2");
-    FieldMatcher dimensionInCondition;
+    vector<Matcher> dimensionInCondition;
     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
 
     unordered_map<MetricDimensionKey, vector<DurationBucket>> buckets;
@@ -168,7 +169,7 @@
     const std::vector<HashableDimensionKey> conditionKey = {getMockedDimensionKey(TagId, 4, "1")};
     const HashableDimensionKey key1 = getMockedDimensionKey(TagId, 1, "1");
     const HashableDimensionKey key2 = getMockedDimensionKey(TagId, 1, "2");
-    FieldMatcher dimensionInCondition;
+    vector<Matcher> dimensionInCondition;
     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
 
     unordered_map<MetricDimensionKey, vector<DurationBucket>> buckets;
@@ -206,7 +207,7 @@
     const std::vector<HashableDimensionKey> conditionKey = {getMockedDimensionKey(TagId, 4, "1")};
     const HashableDimensionKey key1 = getMockedDimensionKey(TagId, 1, "1");
 
-    FieldMatcher dimensionInCondition;
+    vector<Matcher> dimensionInCondition;
     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
 
     ConditionKey conditionKey1;
diff --git a/cmds/statsd/tests/metrics/OringDurationTracker_test.cpp b/cmds/statsd/tests/metrics/OringDurationTracker_test.cpp
index 4b579b1..293b1a8 100644
--- a/cmds/statsd/tests/metrics/OringDurationTracker_test.cpp
+++ b/cmds/statsd/tests/metrics/OringDurationTracker_test.cpp
@@ -52,7 +52,7 @@
         {getMockedDimensionKey(TagId, 1, "maps")};
     const HashableDimensionKey kEventKey1 = getMockedDimensionKey(TagId, 2, "maps");
     const HashableDimensionKey kEventKey2 = getMockedDimensionKey(TagId, 3, "maps");
-    FieldMatcher dimensionInCondition;
+    vector<Matcher> dimensionInCondition;
     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
 
     unordered_map<MetricDimensionKey, vector<DurationBucket>> buckets;
@@ -88,7 +88,7 @@
         {getMockedDimensionKey(TagId, 1, "maps")};
     const HashableDimensionKey kEventKey1 = getMockedDimensionKey(TagId, 2, "maps");
     const HashableDimensionKey kEventKey2 = getMockedDimensionKey(TagId, 3, "maps");
-    FieldMatcher dimensionInCondition;
+    vector<Matcher> dimensionInCondition;
     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
 
     unordered_map<MetricDimensionKey, vector<DurationBucket>> buckets;
@@ -122,7 +122,7 @@
         {getMockedDimensionKey(TagId, 1, "maps")};
     const HashableDimensionKey kEventKey1 = getMockedDimensionKey(TagId, 2, "maps");
     const HashableDimensionKey kEventKey2 = getMockedDimensionKey(TagId, 3, "maps");
-    FieldMatcher dimensionInCondition;
+    vector<Matcher> dimensionInCondition;
     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
 
     unordered_map<MetricDimensionKey, vector<DurationBucket>> buckets;
@@ -155,7 +155,7 @@
         {getMockedDimensionKey(TagId, 1, "maps")};
     const HashableDimensionKey kEventKey1 = getMockedDimensionKey(TagId, 2, "maps");
     const HashableDimensionKey kEventKey2 = getMockedDimensionKey(TagId, 3, "maps");
-    FieldMatcher dimensionInCondition;
+    vector<Matcher> dimensionInCondition;
     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
 
     unordered_map<MetricDimensionKey, vector<DurationBucket>> buckets;
@@ -197,7 +197,7 @@
         {getMockedDimensionKey(TagId, 1, "maps")};
     const HashableDimensionKey kEventKey1 = getMockedDimensionKey(TagId, 2, "maps");
     const HashableDimensionKey kEventKey2 = getMockedDimensionKey(TagId, 3, "maps");
-    FieldMatcher dimensionInCondition;
+    vector<Matcher> dimensionInCondition;
     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
 
     ConditionKey key1;
@@ -238,7 +238,7 @@
         {getMockedDimensionKey(TagId, 1, "maps")};
     const HashableDimensionKey kEventKey1 = getMockedDimensionKey(TagId, 2, "maps");
     const HashableDimensionKey kEventKey2 = getMockedDimensionKey(TagId, 3, "maps");
-    FieldMatcher dimensionInCondition;
+    vector<Matcher> dimensionInCondition;
     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
 
     ConditionKey key1;
@@ -283,7 +283,7 @@
         {getMockedDimensionKey(TagId, 1, "maps")};
     const HashableDimensionKey kEventKey1 = getMockedDimensionKey(TagId, 2, "maps");
     const HashableDimensionKey kEventKey2 = getMockedDimensionKey(TagId, 3, "maps");
-    FieldMatcher dimensionInCondition;
+    vector<Matcher> dimensionInCondition;
     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
 
     ConditionKey key1;
@@ -326,7 +326,7 @@
         {getMockedDimensionKey(TagId, 1, "maps")};
     const HashableDimensionKey kEventKey1 = getMockedDimensionKey(TagId, 2, "maps");
     const HashableDimensionKey kEventKey2 = getMockedDimensionKey(TagId, 3, "maps");
-    FieldMatcher dimensionInCondition;
+    vector<Matcher> dimensionInCondition;
     Alert alert;
     alert.set_id(101);
     alert.set_metric_id(1);
@@ -395,7 +395,7 @@
     const std::vector<HashableDimensionKey> kConditionKey1 = {getMockedDimensionKey(TagId, 1, "maps")};
     const HashableDimensionKey kEventKey1 = getMockedDimensionKey(TagId, 2, "maps");
     const HashableDimensionKey kEventKey2 = getMockedDimensionKey(TagId, 3, "maps");
-    FieldMatcher dimensionInCondition;
+    vector<Matcher> dimensionInCondition;
     Alert alert;
     alert.set_id(101);
     alert.set_metric_id(1);
@@ -446,7 +446,7 @@
         {getMockedDimensionKey(TagId, 1, "maps")};
     const HashableDimensionKey kEventKey1 = getMockedDimensionKey(TagId, 2, "maps");
     const HashableDimensionKey kEventKey2 = getMockedDimensionKey(TagId, 3, "maps");
-    FieldMatcher dimensionInCondition;
+    vector<Matcher> dimensionInCondition;
     Alert alert;
     alert.set_id(101);
     alert.set_metric_id(1);
diff --git a/cmds/statsd/tests/metrics/metrics_test_helper.cpp b/cmds/statsd/tests/metrics/metrics_test_helper.cpp
index ab9345a..7b9c0d6 100644
--- a/cmds/statsd/tests/metrics/metrics_test_helper.cpp
+++ b/cmds/statsd/tests/metrics/metrics_test_helper.cpp
@@ -19,20 +19,26 @@
 namespace statsd {
 
 HashableDimensionKey getMockedDimensionKey(int tagId, int key, string value) {
-    DimensionsValue dimensionsValue;
-    dimensionsValue.set_field(tagId);
-    dimensionsValue.mutable_value_tuple()->add_dimensions_value()->set_field(key);
-    dimensionsValue.mutable_value_tuple()->mutable_dimensions_value(0)->set_value_str(value);
-    return HashableDimensionKey(dimensionsValue);
+    HashableDimensionKey dimension;
+    int pos[] = {key, 0, 0};
+    dimension.addValue(FieldValue(Field(tagId, pos, 0), Value(value)));
+
+    return dimension;
 }
 
 MetricDimensionKey getMockedMetricDimensionKey(int tagId, int key, string value) {
-    DimensionsValue dimensionsValue;
-    dimensionsValue.set_field(tagId);
-    dimensionsValue.mutable_value_tuple()->add_dimensions_value()->set_field(key);
-    dimensionsValue.mutable_value_tuple()->mutable_dimensions_value(0)->set_value_str(value);
-    return MetricDimensionKey(HashableDimensionKey(dimensionsValue), DEFAULT_DIMENSION_KEY);
+    return MetricDimensionKey(getMockedDimensionKey(tagId, key, value), DEFAULT_DIMENSION_KEY);
 }
+
+void buildSimpleAtomFieldMatcher(const int tagId, FieldMatcher* matcher) {
+    matcher->set_field(tagId);
+}
+
+void buildSimpleAtomFieldMatcher(const int tagId, const int fieldNum, FieldMatcher* matcher) {
+    matcher->set_field(tagId);
+    matcher->add_child()->set_field(fieldNum);
+}
+
 }  // namespace statsd
 }  // namespace os
 }  // namespace android
\ No newline at end of file
diff --git a/cmds/statsd/tests/metrics/metrics_test_helper.h b/cmds/statsd/tests/metrics/metrics_test_helper.h
index b48de54..a01de63 100644
--- a/cmds/statsd/tests/metrics/metrics_test_helper.h
+++ b/cmds/statsd/tests/metrics/metrics_test_helper.h
@@ -26,12 +26,10 @@
 
 class MockConditionWizard : public ConditionWizard {
 public:
-    MOCK_METHOD4(
-            query,
-            ConditionState(const int conditionIndex,
-                           const ConditionKey& conditionParameters,
-                           const FieldMatcher& dimensionFields,
-                           std::unordered_set<HashableDimensionKey> *dimensionKeySet));
+    MOCK_METHOD4(query,
+                 ConditionState(const int conditionIndex, const ConditionKey& conditionParameters,
+                                const vector<Matcher>& dimensionFields,
+                                std::unordered_set<HashableDimensionKey>* dimensionKeySet));
 };
 
 class MockStatsPullerManager : public StatsPullerManager {
@@ -49,6 +47,10 @@
 HashableDimensionKey getMockedDimensionKey(int tagId, int key, std::string value);
 MetricDimensionKey getMockedMetricDimensionKey(int tagId, int key, std::string value);
 
+// Utils to build FieldMatcher proto for simple one-depth atoms.
+void buildSimpleAtomFieldMatcher(const int tagId, const int atomFieldNum, FieldMatcher* matcher);
+void buildSimpleAtomFieldMatcher(const int tagId, FieldMatcher* matcher);
+
 }  // namespace statsd
 }  // namespace os
 }  // namespace android
\ No newline at end of file
diff --git a/cmds/statsd/tests/statsd_test_util.cpp b/cmds/statsd/tests/statsd_test_util.cpp
index 13055cb..d3a89617 100644
--- a/cmds/statsd/tests/statsd_test_util.cpp
+++ b/cmds/statsd/tests/statsd_test_util.cpp
@@ -186,7 +186,7 @@
 
 Predicate CreateScreenIsOffPredicate() {
     Predicate predicate;
-    predicate.set_id(StringToId("ScreenIsOff"));
+    predicate.set_id(1111123);
     predicate.mutable_simple_predicate()->set_start(StringToId("ScreenTurnedOff"));
     predicate.mutable_simple_predicate()->set_stop(StringToId("ScreenTurnedOn"));
     return predicate;
@@ -202,7 +202,7 @@
 
 Predicate CreateIsSyncingPredicate() {
     Predicate predicate;
-    predicate.set_id(StringToId("IsSyncing"));
+    predicate.set_id(33333333333333);
     predicate.mutable_simple_predicate()->set_start(StringToId("SyncStart"));
     predicate.mutable_simple_predicate()->set_stop(StringToId("SyncEnd"));
     return predicate;
@@ -461,6 +461,93 @@
         .value_tuple().dimensions_value(1).value_str(), tag);
 }
 
+bool EqualsTo(const DimensionsValue& s1, const DimensionsValue& s2) {
+    if (s1.field() != s2.field()) {
+        return false;
+    }
+    if (s1.value_case() != s2.value_case()) {
+        return false;
+    }
+    switch (s1.value_case()) {
+        case DimensionsValue::ValueCase::kValueStr:
+            return (s1.value_str() == s2.value_str());
+        case DimensionsValue::ValueCase::kValueInt:
+            return s1.value_int() == s2.value_int();
+        case DimensionsValue::ValueCase::kValueLong:
+            return s1.value_long() == s2.value_long();
+        case DimensionsValue::ValueCase::kValueBool:
+            return s1.value_bool() == s2.value_bool();
+        case DimensionsValue::ValueCase::kValueFloat:
+            return s1.value_float() == s2.value_float();
+        case DimensionsValue::ValueCase::kValueTuple: {
+            if (s1.value_tuple().dimensions_value_size() !=
+                s2.value_tuple().dimensions_value_size()) {
+                return false;
+            }
+            bool allMatched = true;
+            for (int i = 0; allMatched && i < s1.value_tuple().dimensions_value_size(); ++i) {
+                allMatched &= EqualsTo(s1.value_tuple().dimensions_value(i),
+                                       s2.value_tuple().dimensions_value(i));
+            }
+            return allMatched;
+        }
+        case DimensionsValue::ValueCase::VALUE_NOT_SET:
+        default:
+            return true;
+    }
+}
+
+bool LessThan(const DimensionsValue& s1, const DimensionsValue& s2) {
+    if (s1.field() != s2.field()) {
+        return s1.field() < s2.field();
+    }
+    if (s1.value_case() != s2.value_case()) {
+        return s1.value_case() < s2.value_case();
+    }
+    switch (s1.value_case()) {
+        case DimensionsValue::ValueCase::kValueStr:
+            return s1.value_str() < s2.value_str();
+        case DimensionsValue::ValueCase::kValueInt:
+            return s1.value_int() < s2.value_int();
+        case DimensionsValue::ValueCase::kValueLong:
+            return s1.value_long() < s2.value_long();
+        case DimensionsValue::ValueCase::kValueBool:
+            return (int)s1.value_bool() < (int)s2.value_bool();
+        case DimensionsValue::ValueCase::kValueFloat:
+            return s1.value_float() < s2.value_float();
+        case DimensionsValue::ValueCase::kValueTuple: {
+            if (s1.value_tuple().dimensions_value_size() !=
+                s2.value_tuple().dimensions_value_size()) {
+                return s1.value_tuple().dimensions_value_size() <
+                       s2.value_tuple().dimensions_value_size();
+            }
+            for (int i = 0; i < s1.value_tuple().dimensions_value_size(); ++i) {
+                if (EqualsTo(s1.value_tuple().dimensions_value(i),
+                             s2.value_tuple().dimensions_value(i))) {
+                    continue;
+                } else {
+                    return LessThan(s1.value_tuple().dimensions_value(i),
+                                    s2.value_tuple().dimensions_value(i));
+                }
+            }
+            return false;
+        }
+        case DimensionsValue::ValueCase::VALUE_NOT_SET:
+        default:
+            return false;
+    }
+}
+
+bool LessThan(const DimensionsPair& s1, const DimensionsPair& s2) {
+    if (LessThan(s1.dimInWhat, s2.dimInWhat)) {
+        return true;
+    } else if (LessThan(s2.dimInWhat, s1.dimInWhat)) {
+        return false;
+    }
+
+    return LessThan(s1.dimInCondition, s2.dimInCondition);
+}
+
 }  // namespace statsd
 }  // namespace os
 }  // namespace android
\ No newline at end of file
diff --git a/cmds/statsd/tests/statsd_test_util.h b/cmds/statsd/tests/statsd_test_util.h
index 6638893..5d83ed7 100644
--- a/cmds/statsd/tests/statsd_test_util.h
+++ b/cmds/statsd/tests/statsd_test_util.h
@@ -159,14 +159,30 @@
 void ValidateAttributionUidAndTagDimension(
     const DimensionsValue& value, int atomId, int uid, const std::string& tag);
 
+struct DimensionsPair {
+    DimensionsPair(DimensionsValue m1, DimensionsValue m2) : dimInWhat(m1), dimInCondition(m2){};
+
+    DimensionsValue dimInWhat;
+    DimensionsValue dimInCondition;
+};
+
+bool LessThan(const DimensionsValue& s1, const DimensionsValue& s2);
+bool LessThan(const DimensionsPair& s1, const DimensionsPair& s2);
+
+struct DimensionCompare {
+    bool operator()(const DimensionsPair& s1, const DimensionsPair& s2) const {
+        return LessThan(s1, s2);
+    }
+};
+
 template <typename T>
 void sortMetricDataByDimensionsValue(const T& metricData, T* sortedMetricData) {
-    std::map<MetricDimensionKey, int> dimensionIndexMap;
+    std::map<DimensionsPair, int, DimensionCompare> dimensionIndexMap;
     for (int i = 0; i < metricData.data_size(); ++i) {
-        dimensionIndexMap.insert(std::make_pair(
-            MetricDimensionKey(HashableDimensionKey(metricData.data(i).dimensions_in_what()),
-            HashableDimensionKey(metricData.data(i).dimensions_in_condition())),
-            i));
+        dimensionIndexMap.insert(
+                std::make_pair(DimensionsPair(metricData.data(i).dimensions_in_what(),
+                                              metricData.data(i).dimensions_in_condition()),
+                               i));
     }
     for (const auto& itr : dimensionIndexMap) {
         *sortedMetricData->add_data() = metricData.data(itr.second);
diff --git a/config/hiddenapi-light-greylist.txt b/config/hiddenapi-light-greylist.txt
index 71de479..b822f2c 100644
--- a/config/hiddenapi-light-greylist.txt
+++ b/config/hiddenapi-light-greylist.txt
@@ -1,7 +1,11 @@
 Landroid/accounts/AccountManager;->mContext:Landroid/content/Context;
+Landroid/accounts/IAccountManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/accounts/IAccountManager;
+Landroid/accounts/IAccountManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
+Landroid/animation/LayoutTransition;->cancel()V
 Landroid/animation/ValueAnimator;->animateValue(F)V
 Landroid/animation/ValueAnimator;->getDurationScale()F
 Landroid/animation/ValueAnimator;->sDurationScale:F
+Landroid/animation/ValueAnimator;->setDurationScale(F)V
 Landroid/app/Activity;->convertFromTranslucent()V
 Landroid/app/Activity;->convertToTranslucent(Landroid/app/Activity$TranslucentConversionListener;Landroid/app/ActivityOptions;)Z
 Landroid/app/Activity;->getActivityOptions()Landroid/app/ActivityOptions;
@@ -12,6 +16,8 @@
 Landroid/app/ActivityManager;->forceStopPackage(Ljava/lang/String;)V
 Landroid/app/ActivityManager;->getCurrentUser()I
 Landroid/app/ActivityManager;->getPackageImportance(Ljava/lang/String;)I
+Landroid/app/ActivityManager;->getService()Landroid/app/IActivityManager;
+Landroid/app/ActivityManager;->IActivityManagerSingleton:Landroid/util/Singleton;
 Landroid/app/ActivityManager;->isLowRamDeviceStatic()Z
 Landroid/app/ActivityManager;->isUserRunning(I)Z
 Landroid/app/ActivityManager;->mContext:Landroid/content/Context;
@@ -22,43 +28,81 @@
 Landroid/app/ActivityManager$RunningAppProcessInfo;->flags:I
 Landroid/app/ActivityManager$RunningAppProcessInfo;->processState:I
 Landroid/app/Activity;->mApplication:Landroid/app/Application;
+Landroid/app/Activity;->mComponent:Landroid/content/ComponentName;
+Landroid/app/Activity;->mFragments:Landroid/app/FragmentController;
 Landroid/app/Activity;->mHandler:Landroid/os/Handler;
+Landroid/app/Activity;->mInstrumentation:Landroid/app/Instrumentation;
+Landroid/app/Activity;->mReferrer:Ljava/lang/String;
 Landroid/app/Activity;->mResultCode:I
 Landroid/app/Activity;->mResultData:Landroid/content/Intent;
+Landroid/app/Activity;->mResumed:Z
 Landroid/app/Activity;->mToken:Landroid/os/IBinder;
 Landroid/app/Activity;->mWindow:Landroid/view/Window;
 Landroid/app/Activity;->mWindowManager:Landroid/view/WindowManager;
 Landroid/app/Activity;->setDisablePreviewScreenshots(Z)V
 Landroid/app/ActivityThread$ActivityClientRecord;->activityInfo:Landroid/content/pm/ActivityInfo;
+Landroid/app/ActivityThread$ActivityClientRecord;->activity:Landroid/app/Activity;
+Landroid/app/ActivityThread$ActivityClientRecord;->compatInfo:Landroid/content/res/CompatibilityInfo;
+Landroid/app/ActivityThread$ActivityClientRecord;->intent:Landroid/content/Intent;
+Landroid/app/ActivityThread$ActivityClientRecord;->mPreserveWindow:Z
+Landroid/app/ActivityThread$ActivityClientRecord;->packageInfo:Landroid/app/LoadedApk;
+Landroid/app/ActivityThread$ActivityClientRecord;->paused:Z
+Landroid/app/ActivityThread$ActivityClientRecord;->stopped:Z
 Landroid/app/ActivityThread$ActivityClientRecord;->token:Landroid/os/IBinder;
+Landroid/app/ActivityThread$AppBindData;->appInfo:Landroid/content/pm/ApplicationInfo;
 Landroid/app/ActivityThread$AppBindData;->info:Landroid/app/LoadedApk;
 Landroid/app/ActivityThread$AppBindData;->instrumentationArgs:Landroid/os/Bundle;
+Landroid/app/ActivityThread$AppBindData;->providers:Ljava/util/List;
+Landroid/app/ActivityThread$BindServiceData;->intent:Landroid/content/Intent;
+Landroid/app/ActivityThread$BindServiceData;->token:Landroid/os/IBinder;
+Landroid/app/ActivityThread$CreateServiceData;->compatInfo:Landroid/content/res/CompatibilityInfo;
+Landroid/app/ActivityThread$CreateServiceData;->info:Landroid/content/pm/ServiceInfo;
+Landroid/app/ActivityThread$CreateServiceData;->intent:Landroid/content/Intent;
+Landroid/app/ActivityThread$CreateServiceData;->token:Landroid/os/IBinder;
 Landroid/app/ActivityThread;->currentActivityThread()Landroid/app/ActivityThread;
 Landroid/app/ActivityThread;->currentApplication()Landroid/app/Application;
 Landroid/app/ActivityThread;->currentPackageName()Ljava/lang/String;
 Landroid/app/ActivityThread;->currentProcessName()Ljava/lang/String;
+Landroid/app/ActivityThread;->getActivity(Landroid/os/IBinder;)Landroid/app/Activity;
 Landroid/app/ActivityThread;->getApplication()Landroid/app/Application;
 Landroid/app/ActivityThread;->getApplicationThread()Landroid/app/ActivityThread$ApplicationThread;
 Landroid/app/ActivityThread;->getHandler()Landroid/os/Handler;
+Landroid/app/ActivityThread;->getInstrumentation()Landroid/app/Instrumentation;
+Landroid/app/ActivityThread;->getPackageInfo(Landroid/content/pm/ApplicationInfo;Landroid/content/res/CompatibilityInfo;I)Landroid/app/LoadedApk;
+Landroid/app/ActivityThread;->getPackageInfoNoCheck(Landroid/content/pm/ApplicationInfo;Landroid/content/res/CompatibilityInfo;)Landroid/app/LoadedApk;
 Landroid/app/ActivityThread;->getPackageManager()Landroid/content/pm/IPackageManager;
 Landroid/app/ActivityThread;->getProcessName()Ljava/lang/String;
+Landroid/app/ActivityThread;->getSystemContext()Landroid/app/ContextImpl;
 Landroid/app/ActivityThread$H;->BIND_SERVICE:I
 Landroid/app/ActivityThread$H;->CREATE_SERVICE:I
 Landroid/app/ActivityThread$H;->EXIT_APPLICATION:I
+Landroid/app/ActivityThread$H;->GC_WHEN_IDLE:I
 Landroid/app/ActivityThread$H;->RECEIVER:I
 Landroid/app/ActivityThread$H;->REMOVE_PROVIDER:I
 Landroid/app/ActivityThread$H;->SERVICE_ARGS:I
 Landroid/app/ActivityThread$H;->STOP_SERVICE:I
 Landroid/app/ActivityThread$H;->UNBIND_SERVICE:I
 Landroid/app/ActivityThread;->installContentProviders(Landroid/content/Context;Ljava/util/List;)V
+Landroid/app/ActivityThread;->installProvider(Landroid/content/Context;Landroid/app/ContentProviderHolder;Landroid/content/pm/ProviderInfo;ZZZ)Landroid/app/ContentProviderHolder;
 Landroid/app/ActivityThread;->mActivities:Landroid/util/ArrayMap;
 Landroid/app/ActivityThread;->mAllApplications:Ljava/util/ArrayList;
 Landroid/app/ActivityThread;->mBoundApplication:Landroid/app/ActivityThread$AppBindData;
+Landroid/app/ActivityThread;->mH:Landroid/app/ActivityThread$H;
 Landroid/app/ActivityThread;->mInitialApplication:Landroid/app/Application;
 Landroid/app/ActivityThread;->mInstrumentation:Landroid/app/Instrumentation;
 Landroid/app/ActivityThread;->mNumVisibleActivities:I
 Landroid/app/ActivityThread;->mPackages:Landroid/util/ArrayMap;
+Landroid/app/ActivityThread;->mProviderMap:Landroid/util/ArrayMap;
+Landroid/app/ActivityThread;->mServices:Landroid/util/ArrayMap;
 Landroid/app/ActivityThread;->performStopActivity(Landroid/os/IBinder;ZLjava/lang/String;)V
+Landroid/app/ActivityThread$ProviderClientRecord;->mLocalProvider:Landroid/content/ContentProvider;
+Landroid/app/ActivityThread$ReceiverData;->compatInfo:Landroid/content/res/CompatibilityInfo;
+Landroid/app/ActivityThread$ReceiverData;->info:Landroid/content/pm/ActivityInfo;
+Landroid/app/ActivityThread$ReceiverData;->intent:Landroid/content/Intent;
+Landroid/app/ActivityThread;->sCurrentActivityThread:Landroid/app/ActivityThread;
+Landroid/app/ActivityThread;->sendActivityResult(Landroid/os/IBinder;Ljava/lang/String;IILandroid/content/Intent;)V
+Landroid/app/ActivityThread$ServiceArgsData;->args:Landroid/content/Intent;
+Landroid/app/ActivityThread$ServiceArgsData;->token:Landroid/os/IBinder;
 Landroid/app/ActivityThread;->sPackageManager:Landroid/content/pm/IPackageManager;
 Landroid/app/admin/DevicePolicyManager;->getDeviceOwnerComponentOnAnyUser()Landroid/content/ComponentName;
 Landroid/app/admin/DevicePolicyManager;->getDeviceOwner()Ljava/lang/String;
@@ -70,10 +114,14 @@
 Landroid/app/admin/DevicePolicyManager;->packageHasActiveAdmins(Ljava/lang/String;)Z
 Landroid/app/admin/DevicePolicyManager;->setActiveAdmin(Landroid/content/ComponentName;ZI)V
 Landroid/app/admin/DevicePolicyManager;->setActiveAdmin(Landroid/content/ComponentName;Z)V
+Landroid/app/admin/IDevicePolicyManager$Stub;->TRANSACTION_packageHasActiveAdmins:I
+Landroid/app/admin/IDevicePolicyManager$Stub;->TRANSACTION_removeActiveAdmin:I
+Landroid/app/admin/SecurityLog$SecurityEvent;-><init>([B)V
 Landroid/app/AlarmManager;->FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED:I
 Landroid/app/AlarmManager;->FLAG_IDLE_UNTIL:I
 Landroid/app/AlarmManager;->FLAG_STANDALONE:I
 Landroid/app/AlarmManager;->FLAG_WAKE_FROM_IDLE:I
+Landroid/app/AlarmManager;->mService:Landroid/app/IAlarmManager;
 Landroid/app/AlarmManager;->set(IJJJLandroid/app/AlarmManager$OnAlarmListener;Landroid/os/Handler;Landroid/os/WorkSource;)V
 Landroid/app/AlarmManager;->set(IJJJLandroid/app/PendingIntent;Landroid/os/WorkSource;)V
 Landroid/app/AlarmManager;->WINDOW_EXACT:J
@@ -83,26 +131,50 @@
 Landroid/app/AppGlobals;->getInitialApplication()Landroid/app/Application;
 Landroid/app/AppGlobals;->getPackageManager()Landroid/content/pm/IPackageManager;
 Landroid/app/Application;->attach(Landroid/content/Context;)V
+Landroid/app/Application;->collectActivityLifecycleCallbacks()[Ljava/lang/Object;
+Landroid/app/Application;->dispatchActivityCreated(Landroid/app/Activity;Landroid/os/Bundle;)V
+Landroid/app/Application;->dispatchActivityDestroyed(Landroid/app/Activity;)V
+Landroid/app/Application;->dispatchActivityPaused(Landroid/app/Activity;)V
+Landroid/app/Application;->dispatchActivityResumed(Landroid/app/Activity;)V
+Landroid/app/Application;->dispatchActivitySaveInstanceState(Landroid/app/Activity;Landroid/os/Bundle;)V
+Landroid/app/Application;->dispatchActivityStarted(Landroid/app/Activity;)V
+Landroid/app/Application;->dispatchActivityStopped(Landroid/app/Activity;)V
 Landroid/app/ApplicationLoaders;->getDefault()Landroid/app/ApplicationLoaders;
 Landroid/app/ApplicationLoaders;->mLoaders:Landroid/util/ArrayMap;
 Landroid/app/Application;->mComponentCallbacks:Ljava/util/ArrayList;
 Landroid/app/Application;->mLoadedApk:Landroid/app/LoadedApk;
 Landroid/app/ApplicationPackageManager;->deletePackage(Ljava/lang/String;Landroid/content/pm/IPackageDeleteObserver;I)V
+Landroid/app/ApplicationPackageManager;->getPackageSizeInfoAsUser(Ljava/lang/String;ILandroid/content/pm/IPackageStatsObserver;)V
+Landroid/app/ApplicationPackageManager;-><init>(Landroid/app/ContextImpl;Landroid/content/pm/IPackageManager;)V
 Landroid/app/ApplicationPackageManager;->installExistingPackage(Ljava/lang/String;)I
 Landroid/app/ApplicationPackageManager;->installExistingPackage(Ljava/lang/String;I)I
+Landroid/app/ApplicationPackageManager;->mPM:Landroid/content/pm/IPackageManager;
 Landroid/app/AppOpsManager;->checkOp(IILjava/lang/String;)I
 Landroid/app/AppOpsManager;->checkOpNoThrow(IILjava/lang/String;)I
+Landroid/app/AppOpsManager;->mService:Lcom/android/internal/app/IAppOpsService;
 Landroid/app/AppOpsManager;->noteOp(I)I
 Landroid/app/AppOpsManager;->noteOp(IILjava/lang/String;)I
+Landroid/app/AppOpsManager;->OP_COARSE_LOCATION:I
+Landroid/app/AppOpsManager;->OP_FINE_LOCATION:I
+Landroid/app/AppOpsManager;->OP_GET_USAGE_STATS:I
 Landroid/app/AppOpsManager;->OP_POST_NOTIFICATION:I
+Landroid/app/AppOpsManager;->OP_READ_PHONE_STATE:I
+Landroid/app/AppOpsManager;->OP_READ_SMS:I
+Landroid/app/AppOpsManager;->OP_SYSTEM_ALERT_WINDOW:I
 Landroid/app/AppOpsManager;->OP_WIFI_SCAN:I
 Landroid/app/AppOpsManager;->OP_WRITE_SMS:I
+Landroid/app/AppOpsManager;->permissionToOpCode(Ljava/lang/String;)I
 Landroid/app/AppOpsManager;->setMode(IILjava/lang/String;I)V
 Landroid/app/AppOpsManager;->strOpToOp(Ljava/lang/String;)I
+Landroid/app/backup/BackupDataInput$EntityHeader;->dataSize:I
+Landroid/app/backup/BackupDataInput$EntityHeader;->key:Ljava/lang/String;
 Landroid/app/backup/BackupDataInput;-><init>(Ljava/io/FileDescriptor;)V
 Landroid/app/backup/BackupDataInputStream;->dataSize:I
 Landroid/app/backup/BackupDataInputStream;->key:Ljava/lang/String;
 Landroid/app/backup/BackupDataOutput;-><init>(Ljava/io/FileDescriptor;)V
+Landroid/app/backup/BackupDataOutput;->mBackupWriter:J
+Landroid/app/backup/BackupHelperDispatcher$Header;->chunkSize:I
+Landroid/app/backup/BackupHelperDispatcher$Header;->keyPrefix:Ljava/lang/String;
 Landroid/app/backup/BackupManager;->backupNow()V
 Landroid/app/backup/BackupManager;->beginRestoreSession()Landroid/app/backup/RestoreSession;
 Landroid/app/backup/BackupManager;->cancelBackups()V
@@ -116,64 +188,135 @@
 Landroid/app/backup/BackupManager;->selectBackupTransport(Ljava/lang/String;)Ljava/lang/String;
 Landroid/app/backup/BackupManager;->setAutoRestore(Z)V
 Landroid/app/backup/BackupManager;->setBackupEnabled(Z)V
+Landroid/app/backup/BackupManager;->updateTransportAttributes(Landroid/content/ComponentName;Ljava/lang/String;Landroid/content/Intent;Ljava/lang/String;Landroid/content/Intent;Ljava/lang/String;)V
 Landroid/app/backup/BackupObserver;-><init>()V
 Landroid/app/backup/BackupTransport;-><init>()V
 Landroid/app/backup/FullBackup;->backupToTar(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Landroid/app/backup/FullBackupDataOutput;)I
+Landroid/app/backup/FullBackupDataOutput;->addSize(J)V
+Landroid/app/backup/FullBackupDataOutput;->mData:Landroid/app/backup/BackupDataOutput;
 Landroid/app/backup/RestoreDescription;-><init>(Ljava/lang/String;I)V
 Landroid/app/backup/RestoreSession;->endRestoreSession()V
 Landroid/app/backup/RestoreSession;->getAvailableRestoreSets(Landroid/app/backup/RestoreObserver;)I
 Landroid/app/backup/RestoreSession;->restoreAll(JLandroid/app/backup/RestoreObserver;)I
 Landroid/app/backup/RestoreSet;-><init>(Ljava/lang/String;Ljava/lang/String;J)V
 Landroid/app/backup/SelectBackupTransportCallback;-><init>()V
+Landroid/app/ContentProviderHolder;->provider:Landroid/content/IContentProvider;
 Landroid/app/ContextImpl;->createActivityContext(Landroid/app/ActivityThread;Landroid/app/LoadedApk;Landroid/content/pm/ActivityInfo;Landroid/os/IBinder;ILandroid/content/res/Configuration;)Landroid/app/ContextImpl;
 Landroid/app/ContextImpl;->getActivityToken()Landroid/os/IBinder;
+Landroid/app/ContextImpl;->getDisplay()Landroid/view/Display;
+Landroid/app/ContextImpl;->getPreferencesDir()Ljava/io/File;
+Landroid/app/ContextImpl;->mContentResolver:Landroid/app/ContextImpl$ApplicationContentResolver;
 Landroid/app/ContextImpl;->mMainThread:Landroid/app/ActivityThread;
+Landroid/app/ContextImpl;->mOpPackageName:Ljava/lang/String;
+Landroid/app/ContextImpl;->mOuterContext:Landroid/content/Context;
 Landroid/app/ContextImpl;->mPackageInfo:Landroid/app/LoadedApk;
+Landroid/app/ContextImpl;->mPackageManager:Landroid/content/pm/PackageManager;
+Landroid/app/ContextImpl;->mResources:Landroid/content/res/Resources;
+Landroid/app/ContextImpl;->mServiceCache:[Ljava/lang/Object;
+Landroid/app/ContextImpl;->mTheme:Landroid/content/res/Resources$Theme;
+Landroid/app/ContextImpl;->scheduleFinalCleanup(Ljava/lang/String;Ljava/lang/String;)V
 Landroid/app/ContextImpl;->setOuterContext(Landroid/content/Context;)V
 Landroid/app/DatePickerDialog;->mDatePicker:Landroid/widget/DatePicker;
 Landroid/app/Dialog;->CANCEL:I
+Landroid/app/Dialog;->dismissDialog()V
 Landroid/app/Dialog;->mCancelMessage:Landroid/os/Message;
 Landroid/app/Dialog;->mDismissMessage:Landroid/os/Message;
 Landroid/app/Dialog;->mListenersHandler:Landroid/os/Handler;
 Landroid/app/Dialog;->mOwnerActivity:Landroid/app/Activity;
 Landroid/app/Dialog;->mShowMessage:Landroid/os/Message;
 Landroid/app/DownloadManager$Request;->mUri:Landroid/net/Uri;
+Landroid/app/FragmentManagerImpl;->mAdded:Ljava/util/ArrayList;
 Landroid/app/Fragment;->mChildFragmentManager:Landroid/app/FragmentManagerImpl;
 Landroid/app/IActivityManager;->forceStopPackage(Ljava/lang/String;I)V
 Landroid/app/IActivityManager;->getLaunchedFromPackage(Landroid/os/IBinder;)Ljava/lang/String;
+Landroid/app/IActivityManager;->getTaskForActivity(Landroid/os/IBinder;Z)I
 Landroid/app/IActivityManager;->resumeAppSwitches()V
+Landroid/app/IActivityManager;->setRequestedOrientation(Landroid/os/IBinder;I)V
+Landroid/app/IActivityManager$Stub$Proxy;->getConfiguration()Landroid/content/res/Configuration;
+Landroid/app/IActivityManager$Stub$Proxy;->getLaunchedFromUid(Landroid/os/IBinder;)I
+Landroid/app/IActivityManager$Stub$Proxy;->getProcessPss([I)[J
+Landroid/app/IActivityManager$Stub$Proxy;->isAppForeground(I)Z
+Landroid/app/IActivityManager$Stub$Proxy;->mRemote:Landroid/os/IBinder;
+Landroid/app/IAlarmManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
+Landroid/app/IAlarmManager$Stub;->TRANSACTION_remove:I
+Landroid/app/IAlarmManager$Stub;->TRANSACTION_set:I
 Landroid/app/IApplicationThread;->scheduleTrimMemory(I)V
+Landroid/app/INotificationManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/app/INotificationManager;
+Landroid/app/INotificationManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/app/InstantAppResolverService;-><init>()V
 Landroid/app/InstantAppResolverService$InstantAppResolutionCallback;->onInstantAppResolveInfo(Ljava/util/List;)V
+Landroid/app/Instrumentation;->execStartActivity(Landroid/content/Context;Landroid/os/IBinder;Landroid/os/IBinder;Landroid/app/Activity;Landroid/content/Intent;ILandroid/os/Bundle;)Landroid/app/Instrumentation$ActivityResult;
+Landroid/app/Instrumentation;->execStartActivity(Landroid/content/Context;Landroid/os/IBinder;Landroid/os/IBinder;Ljava/lang/String;Landroid/content/Intent;ILandroid/os/Bundle;)Landroid/app/Instrumentation$ActivityResult;
+Landroid/app/Instrumentation;->execStartActivity(Landroid/content/Context;Landroid/os/IBinder;Landroid/os/IBinder;Ljava/lang/String;Landroid/content/Intent;ILandroid/os/Bundle;Landroid/os/UserHandle;)Landroid/app/Instrumentation$ActivityResult;
 Landroid/app/IntentService;->mServiceHandler:Landroid/app/IntentService$ServiceHandler;
+Landroid/app/ISearchManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/app/ISearchManager;
+Landroid/app/ISearchManager$Stub$Proxy;->getGlobalSearchActivity()Landroid/content/ComponentName;
+Landroid/app/ISearchManager$Stub$Proxy;->getWebSearchActivity()Landroid/content/ComponentName;
+Landroid/app/IUiModeManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/app/IWallpaperManager;->getWallpaper(Ljava/lang/String;Landroid/app/IWallpaperManagerCallback;ILandroid/os/Bundle;I)Landroid/os/ParcelFileDescriptor;
+Landroid/app/job/IJobScheduler$Stub;->asInterface(Landroid/os/IBinder;)Landroid/app/job/IJobScheduler;
+Landroid/app/job/IJobScheduler$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
+Landroid/app/LoadedApk;->mActivityThread:Landroid/app/ActivityThread;
+Landroid/app/LoadedApk;->makeApplication(ZLandroid/app/Instrumentation;)Landroid/app/Application;
+Landroid/app/LoadedApk;->mAppDir:Ljava/lang/String;
+Landroid/app/LoadedApk;->mApplicationInfo:Landroid/content/pm/ApplicationInfo;
 Landroid/app/LoadedApk;->mApplication:Landroid/app/Application;
+Landroid/app/LoadedApk;->mBaseClassLoader:Ljava/lang/ClassLoader;
+Landroid/app/LoadedApk;->mClassLoader:Ljava/lang/ClassLoader;
+Landroid/app/LoadedApk;->mDataDir:Ljava/lang/String;
+Landroid/app/LoadedApk;->mPackageName:Ljava/lang/String;
 Landroid/app/LoadedApk;->mReceivers:Landroid/util/ArrayMap;
 Landroid/app/LoadedApk;->mResDir:Ljava/lang/String;
 Landroid/app/LoadedApk;->mResources:Landroid/content/res/Resources;
+Landroid/app/LoadedApk;->mSplitResDirs:[Ljava/lang/String;
 Landroid/app/LocalActivityManager;->mActivities:Ljava/util/Map;
 Landroid/app/LocalActivityManager;->mActivityArray:Ljava/util/ArrayList;
+Landroid/app/NativeActivity;->hideIme(I)V
+Landroid/app/NativeActivity;->setWindowFlags(II)V
+Landroid/app/NativeActivity;->setWindowFormat(I)V
+Landroid/app/NativeActivity;->showIme(I)V
 Landroid/app/Notification$Builder;->mActions:Ljava/util/ArrayList;
 Landroid/app/Notification;->EXTRA_SUBSTITUTE_APP_NAME:Ljava/lang/String;
 Landroid/app/Notification;->isGroupSummary()Z
 Landroid/app/NotificationManager;->getService()Landroid/app/INotificationManager;
 Landroid/app/NotificationManager;->notifyAsUser(Ljava/lang/String;ILandroid/app/Notification;Landroid/os/UserHandle;)V
+Landroid/app/NotificationManager;->sService:Landroid/app/INotificationManager;
+Landroid/app/Notification;->mLargeIcon:Landroid/graphics/drawable/Icon;
+Landroid/app/Notification;->mSmallIcon:Landroid/graphics/drawable/Icon;
 Landroid/app/Notification;->setLatestEventInfo(Landroid/content/Context;Ljava/lang/CharSequence;Ljava/lang/CharSequence;Landroid/app/PendingIntent;)V
 Landroid/app/PendingIntent;->getActivityAsUser(Landroid/content/Context;ILandroid/content/Intent;ILandroid/os/Bundle;Landroid/os/UserHandle;)Landroid/app/PendingIntent;
 Landroid/app/PendingIntent;->getIntent()Landroid/content/Intent;
 Landroid/app/PendingIntent;->isActivity()Z
 Landroid/app/Presentation;->createPresentationContext(Landroid/content/Context;Landroid/view/Display;I)Landroid/content/Context;
 Landroid/app/ProgressDialog;->mProgressNumber:Landroid/widget/TextView;
+Landroid/app/QueuedWork;->addFinisher(Ljava/lang/Runnable;)V
+Landroid/app/QueuedWork;->removeFinisher(Ljava/lang/Runnable;)V
+Landroid/app/ResourcesManager;->appendLibAssetForMainAssetPath(Ljava/lang/String;Ljava/lang/String;)V
+Landroid/app/ResourcesManager;->getInstance()Landroid/app/ResourcesManager;
+Landroid/app/ResourcesManager;->mActivityResourceReferences:Ljava/util/WeakHashMap;
+Landroid/app/ResourcesManager;->mResourceImpls:Landroid/util/ArrayMap;
+Landroid/app/ResourcesManager;->mResourceReferences:Ljava/util/ArrayList;
+Landroid/app/Service;->attach(Landroid/content/Context;Landroid/app/ActivityThread;Ljava/lang/String;Landroid/os/IBinder;Landroid/app/Application;Ljava/lang/Object;)V
+Landroid/app/Service;->mActivityManager:Landroid/app/IActivityManager;
+Landroid/app/Service;->mApplication:Landroid/app/Application;
+Landroid/app/Service;->mClassName:Ljava/lang/String;
+Landroid/app/Service;->mStartCompatibility:Z
+Landroid/app/Service;->mThread:Landroid/app/ActivityThread;
+Landroid/app/Service;->mToken:Landroid/os/IBinder;
 Landroid/app/Service;->setForeground(Z)V
+Landroid/app/SharedPreferencesImpl;->mFile:Ljava/io/File;
 Landroid/app/StatusBarManager;->collapsePanels()V
 Landroid/app/StatusBarManager;->disable(I)V
 Landroid/app/StatusBarManager;->expandNotificationsPanel()V
 Landroid/app/StatusBarManager;->expandSettingsPanel(Ljava/lang/String;)V
 Landroid/app/StatusBarManager;->expandSettingsPanel()V
 Landroid/app/TimePickerDialog;->mTimePicker:Landroid/widget/TimePicker;
+Landroid/app/trust/ITrustManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/app/usage/UsageStatsManager;->getAppStandbyBuckets()Ljava/util/Map;
+Landroid/app/usage/UsageStatsManager;->mService:Landroid/app/usage/IUsageStatsManager;
 Landroid/app/usage/UsageStatsManager;->setAppStandbyBuckets(Ljava/util/Map;)V
 Landroid/app/usage/UsageStatsManager;->whitelistAppTemporarily(Ljava/lang/String;JLandroid/os/UserHandle;)V
+Landroid/app/usage/UsageStats;->mLastEvent:I
 Landroid/app/WallpaperColors;->getColorHints()I
 Landroid/app/WallpaperManager;->getBitmap()Landroid/graphics/Bitmap;
 Landroid/app/WallpaperManager;->getBitmap(Z)Landroid/graphics/Bitmap;
@@ -192,6 +335,7 @@
 Landroid/bluetooth/BluetoothAdapter;->getDiscoverableTimeout()I
 Landroid/bluetooth/BluetoothAdapter;->isBleScanAlwaysAvailable()Z
 Landroid/bluetooth/BluetoothAdapter;->isLeEnabled()Z
+Landroid/bluetooth/BluetoothAdapter;->mService:Landroid/bluetooth/IBluetooth;
 Landroid/bluetooth/BluetoothAdapter;->setScanMode(II)Z
 Landroid/bluetooth/BluetoothAdapter;->setScanMode(I)Z
 Landroid/bluetooth/BluetoothDevice;->cancelBondProcess()Z
@@ -209,15 +353,29 @@
 Landroid/bluetooth/BluetoothHeadset;->close()V
 Landroid/bluetooth/BluetoothHeadset;->setPriority(Landroid/bluetooth/BluetoothDevice;I)Z
 Landroid/bluetooth/BluetoothUuid;->RESERVED_UUIDS:[Landroid/os/ParcelUuid;
+Landroid/bluetooth/IBluetooth;->getAddress()Ljava/lang/String;
 Landroid/bluetooth/IBluetooth$Stub;->asInterface(Landroid/os/IBinder;)Landroid/bluetooth/IBluetooth;
+Landroid/bluetooth/IBluetooth$Stub$Proxy;->getAddress()Ljava/lang/String;
 Landroid/bluetooth/le/BluetoothLeScanner;->startScanFromSource(Ljava/util/List;Landroid/bluetooth/le/ScanSettings;Landroid/os/WorkSource;Landroid/bluetooth/le/ScanCallback;)V
 Landroid/bluetooth/le/ScanSettings$Builder;->setScanResultType(I)Landroid/bluetooth/le/ScanSettings$Builder;
 Landroid/content/AsyncTaskLoader;->mExecutor:Ljava/util/concurrent/Executor;
+Landroid/content/BroadcastReceiver$PendingResult;-><init>(ILjava/lang/String;Landroid/os/Bundle;IZZLandroid/os/IBinder;II)V
+Landroid/content/BroadcastReceiver;->setPendingResult(Landroid/content/BroadcastReceiver$PendingResult;)V
+Landroid/content/ContentProvider;->mContext:Landroid/content/Context;
+Landroid/content/ContentProvider;->mPathPermissions:[Landroid/content/pm/PathPermission;
+Landroid/content/ContentProvider;->mReadPermission:Ljava/lang/String;
+Landroid/content/ContentProvider;->mWritePermission:Ljava/lang/String;
 Landroid/content/ContentProviderOperation;->mSelection:Ljava/lang/String;
 Landroid/content/ContentProviderOperation;->mType:I
+Landroid/content/ContentProviderOperation;->TYPE_DELETE:I
+Landroid/content/ContentProviderOperation;->TYPE_INSERT:I
+Landroid/content/ContentProviderOperation;->TYPE_UPDATE:I
+Landroid/content/ContentResolver;->acquireProvider(Landroid/net/Uri;)Landroid/content/IContentProvider;
 Landroid/content/ContentResolver;->getContentService()Landroid/content/IContentService;
 Landroid/content/ContentResolver;->getSyncStatus(Landroid/accounts/Account;Ljava/lang/String;)Landroid/content/SyncStatusInfo;
 Landroid/content/ContentResolver;->mContext:Landroid/content/Context;
+Landroid/content/ContentResolver;->mPackageName:Ljava/lang/String;
+Landroid/content/ContentValues;-><init>(Ljava/util/HashMap;)V
 Landroid/content/ContentValues;->mValues:Ljava/util/HashMap;
 Landroid/content/Context;->bindServiceAsUser(Landroid/content/Intent;Landroid/content/ServiceConnection;ILandroid/os/UserHandle;)Z
 Landroid/content/Context;->createCredentialProtectedStorageContext()Landroid/content/Context;
@@ -225,40 +383,59 @@
 Landroid/content/Context;->getSharedPrefsFile(Ljava/lang/String;)Ljava/io/File;
 Landroid/content/Context;->getThemeResId()I
 Landroid/content/Context;->isCredentialProtectedStorage()Z
+Landroid/content/Context;->PERSISTENT_DATA_BLOCK_SERVICE:Ljava/lang/String;
 Landroid/content/Context;->sendBroadcastAsUser(Landroid/content/Intent;Landroid/os/UserHandle;Ljava/lang/String;I)V
 Landroid/content/Context;->sendBroadcastAsUser(Landroid/content/Intent;Landroid/os/UserHandle;Ljava/lang/String;Landroid/os/Bundle;)V
 Landroid/content/Context;->sendOrderedBroadcastAsUser(Landroid/content/Intent;Landroid/os/UserHandle;Ljava/lang/String;ILandroid/content/BroadcastReceiver;Landroid/os/Handler;ILjava/lang/String;Landroid/os/Bundle;)V
 Landroid/content/Context;->sendOrderedBroadcastAsUser(Landroid/content/Intent;Landroid/os/UserHandle;Ljava/lang/String;ILandroid/os/Bundle;Landroid/content/BroadcastReceiver;Landroid/os/Handler;ILjava/lang/String;Landroid/os/Bundle;)V
 Landroid/content/ContextWrapper;->createCredentialProtectedStorageContext()Landroid/content/Context;
+Landroid/content/ContextWrapper;->getDisplay()Landroid/view/Display;
 Landroid/content/ContextWrapper;->mBase:Landroid/content/Context;
 Landroid/content/CursorLoader;->mCancellationSignal:Landroid/os/CancellationSignal;
 Landroid/content/CursorLoader;->mObserver:Landroid/content/Loader$ForceLoadContentObserver;
+Landroid/content/IClipboard$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/IClipboard;
 Landroid/content/IContentService;->cancelSync(Landroid/accounts/Account;Ljava/lang/String;Landroid/content/ComponentName;)V
 Landroid/content/IContentService;->getMasterSyncAutomatically()Z
 Landroid/content/IContentService;->setMasterSyncAutomatically(Z)V
+Landroid/content/IContentService$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/content/Intent;->ACTION_ALARM_CHANGED:Ljava/lang/String;
+Landroid/content/IntentFilter;->mActions:Ljava/util/ArrayList;
 Landroid/content/IntentFilter;->setOrder(I)V
 Landroid/content/Intent;->putExtra(Ljava/lang/String;Landroid/os/IBinder;)Landroid/content/Intent;
+Landroid/content/pm/ApplicationInfo;->enabledSetting:I
+Landroid/content/pm/ApplicationInfo;->getBaseResourcePath()Ljava/lang/String;
 Landroid/content/pm/ApplicationInfo;->installLocation:I
 Landroid/content/pm/ApplicationInfo;->isForwardLocked()Z
 Landroid/content/pm/ApplicationInfo;->isInstantApp()Z
 Landroid/content/pm/ApplicationInfo;->isPrivilegedApp()Z
 Landroid/content/pm/ApplicationInfo;->primaryCpuAbi:Ljava/lang/String;
 Landroid/content/pm/ApplicationInfo;->privateFlags:I
+Landroid/content/pm/ApplicationInfo;->scanPublicSourceDir:Ljava/lang/String;
+Landroid/content/pm/ApplicationInfo;->scanSourceDir:Ljava/lang/String;
+Landroid/content/pm/ApplicationInfo;->secondaryNativeLibraryDir:Ljava/lang/String;
 Landroid/content/pm/ApplicationInfo;->targetSandboxVersion:I
 Landroid/content/pm/InstantAppIntentFilter;-><init>(Ljava/lang/String;Ljava/util/List;)V
 Landroid/content/pm/InstantAppResolveInfo;->getPackageName()Ljava/lang/String;
 Landroid/content/pm/InstantAppResolveInfo;-><init>(Landroid/content/pm/InstantAppResolveInfo$InstantAppDigest;Ljava/lang/String;Ljava/util/List;I)V
 Landroid/content/pm/InstantAppResolveInfo$InstantAppDigest;->getDigestPrefix()[I
 Landroid/content/pm/InstantAppResolveInfo$InstantAppDigest;-><init>(Ljava/lang/String;)V
+Landroid/content/pm/IPackageManager;->getInstallLocation()I
 Landroid/content/pm/IPackageManager;->getLastChosenActivity(Landroid/content/Intent;Ljava/lang/String;I)Landroid/content/pm/ResolveInfo;
+Landroid/content/pm/IPackageManager;->setApplicationEnabledSetting(Ljava/lang/String;IIILjava/lang/String;)V
+Landroid/content/pm/IPackageManager;->setComponentEnabledSetting(Landroid/content/ComponentName;III)V
 Landroid/content/pm/IPackageManager;->setLastChosenActivity(Landroid/content/Intent;Ljava/lang/String;ILandroid/content/IntentFilter;ILandroid/content/ComponentName;)V
+Landroid/content/pm/IPackageManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/pm/IPackageManager;
+Landroid/content/pm/IPackageManager$Stub$Proxy;->getPackageInfo(Ljava/lang/String;II)Landroid/content/pm/PackageInfo;
+Landroid/content/pm/IPackageManager$Stub$Proxy;->getPackagesForUid(I)[Ljava/lang/String;
+Landroid/content/pm/IPackageManager$Stub$Proxy;->getSystemSharedLibraryNames()[Ljava/lang/String;
 Landroid/content/pm/IPackageStatsObserver$Stub;-><init>()V
 Landroid/content/pm/LauncherApps;->mPm:Landroid/content/pm/PackageManager;
 Landroid/content/pm/LauncherApps;->startShortcut(Ljava/lang/String;Ljava/lang/String;Landroid/graphics/Rect;Landroid/os/Bundle;I)V
+Landroid/content/pm/PackageInstaller$SessionParams;->setAllocateAggressive(Z)V
 Landroid/content/pm/PackageInstaller$SessionParams;->setGrantedRuntimePermissions([Ljava/lang/String;)V
 Landroid/content/pm/PackageInstaller$SessionParams;->setInstallAsInstantApp(Z)V
 Landroid/content/pm/PackageManager;->addOnPermissionsChangeListener(Landroid/content/pm/PackageManager$OnPermissionsChangedListener;)V
+Landroid/content/pm/PackageManager;->buildRequestPermissionsIntent([Ljava/lang/String;)Landroid/content/Intent;
 Landroid/content/pm/PackageManager;->freeStorageAndNotify(JLandroid/content/pm/IPackageDataObserver;)V
 Landroid/content/pm/PackageManager;->freeStorageAndNotify(Ljava/lang/String;JLandroid/content/pm/IPackageDataObserver;)V
 Landroid/content/pm/PackageManager;->freeStorage(JLandroid/content/IntentSender;)V
@@ -269,27 +446,90 @@
 Landroid/content/pm/PackageManager;->getPackageSizeInfo(Ljava/lang/String;Landroid/content/pm/IPackageStatsObserver;)V
 Landroid/content/pm/PackageManager;->getResourcesForApplicationAsUser(Ljava/lang/String;I)Landroid/content/res/Resources;
 Landroid/content/pm/PackageManager;->movePackage(Ljava/lang/String;Landroid/os/storage/VolumeInfo;)I
+Landroid/content/pm/PackageManager;->NO_NATIVE_LIBRARIES:I
 Landroid/content/pm/PackageManager;->queryBroadcastReceivers(Landroid/content/Intent;II)Ljava/util/List;
 Landroid/content/pm/PackageManager;->removeOnPermissionsChangeListener(Landroid/content/pm/PackageManager$OnPermissionsChangedListener;)V
 Landroid/content/pm/PackageManager;->verifyIntentFilter(IILjava/util/List;)V
+Landroid/content/pm/PackageParser$Activity;->info:Landroid/content/pm/ActivityInfo;
+Landroid/content/pm/PackageParser$ActivityIntentInfo;->activity:Landroid/content/pm/PackageParser$Activity;
 Landroid/content/pm/PackageParser;->collectCertificates(Landroid/content/pm/PackageParser$Package;Ljava/io/File;Z)V
 Landroid/content/pm/PackageParser;->collectCertificates(Landroid/content/pm/PackageParser$Package;Z)V
+Landroid/content/pm/PackageParser$Component;->className:Ljava/lang/String;
+Landroid/content/pm/PackageParser$Component;->getComponentName()Landroid/content/ComponentName;
+Landroid/content/pm/PackageParser$Component;->intents:Ljava/util/ArrayList;
 Landroid/content/pm/PackageParser;->generatePackageInfo(Landroid/content/pm/PackageParser$Package;[IIJJLjava/util/Set;Landroid/content/pm/PackageUserState;I)Landroid/content/pm/PackageInfo;
 Landroid/content/pm/PackageParser;->generatePackageInfo(Landroid/content/pm/PackageParser$Package;[IIJJLjava/util/Set;Landroid/content/pm/PackageUserState;)Landroid/content/pm/PackageInfo;
+Landroid/content/pm/PackageParser;-><init>()V
+Landroid/content/pm/PackageParser$Package;->activities:Ljava/util/ArrayList;
+Landroid/content/pm/PackageParser$Package;->applicationInfo:Landroid/content/pm/ApplicationInfo;
+Landroid/content/pm/PackageParser$Package;->mVersionCode:I
+Landroid/content/pm/PackageParser$Package;->mVersionName:Ljava/lang/String;
+Landroid/content/pm/PackageParser$Package;->packageName:Ljava/lang/String;
+Landroid/content/pm/PackageParser$Package;->providers:Ljava/util/ArrayList;
+Landroid/content/pm/PackageParser$Package;->receivers:Ljava/util/ArrayList;
+Landroid/content/pm/PackageParser$Package;->requestedPermissions:Ljava/util/ArrayList;
+Landroid/content/pm/PackageParser$Package;->services:Ljava/util/ArrayList;
+Landroid/content/pm/PackageParser;->parseBaseApk(Ljava/lang/String;Landroid/content/res/Resources;Landroid/content/res/XmlResourceParser;I[Ljava/lang/String;)Landroid/content/pm/PackageParser$Package;
 Landroid/content/pm/PackageParser;->parseMonolithicPackage(Ljava/io/File;I)Landroid/content/pm/PackageParser$Package;
 Landroid/content/pm/PackageParser;->parsePackage(Ljava/io/File;I)Landroid/content/pm/PackageParser$Package;
 Landroid/content/pm/PackageParser;->parsePackage(Ljava/io/File;IZ)Landroid/content/pm/PackageParser$Package;
+Landroid/content/pm/PackageParser$Provider;->info:Landroid/content/pm/ProviderInfo;
+Landroid/content/pm/PackageParser$ProviderIntentInfo;->provider:Landroid/content/pm/PackageParser$Provider;
+Landroid/content/pm/PackageParser$ServiceIntentInfo;->service:Landroid/content/pm/PackageParser$Service;
+Landroid/content/pm/PackageUserState;-><init>()V
+Landroid/content/pm/ParceledListSlice;-><init>(Ljava/util/List;)V
+Landroid/content/pm/ResolveInfo;->instantAppAvailable:Z
+Landroid/content/pm/Signature;->getPublicKey()Ljava/security/PublicKey;
 Landroid/content/pm/UserInfo;->id:I
 Landroid/content/pm/UserInfo;->isPrimary()Z
+Landroid/content/pm/UserInfo;->serialNumber:I
+Landroid/content/res/AssetFileDescriptor;->mFd:Landroid/os/ParcelFileDescriptor;
+Landroid/content/res/AssetFileDescriptor;->mLength:J
+Landroid/content/res/AssetFileDescriptor;->mStartOffset:J
+Landroid/content/res/AssetManager;->addAssetPathAsSharedLibrary(Ljava/lang/String;)I
 Landroid/content/res/AssetManager;->addAssetPath(Ljava/lang/String;)I
+Landroid/content/res/AssetManager;->addAssetPathNative(Ljava/lang/String;Z)I
+Landroid/content/res/AssetManager;->addAssetPaths([Ljava/lang/String;)[I
+Landroid/content/res/AssetManager;->applyStyle(JIIJ[IIJJ)V
+Landroid/content/res/AssetManager;->ensureStringBlocks()[Landroid/content/res/StringBlock;
+Landroid/content/res/AssetManager;->getArraySize(I)I
 Landroid/content/res/AssetManager;->getAssignedPackageIdentifiers()Landroid/util/SparseArray;
+Landroid/content/res/AssetManager;->getCookieName(I)Ljava/lang/String;
+Landroid/content/res/AssetManager;->getNativeStringBlock(I)J
 Landroid/content/res/AssetManager;->getResourceBagText(II)Ljava/lang/CharSequence;
+Landroid/content/res/AssetManager;->getResourceEntryName(I)Ljava/lang/String;
+Landroid/content/res/AssetManager;->getResourceIdentifier(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I
+Landroid/content/res/AssetManager;->getResourceName(I)Ljava/lang/String;
+Landroid/content/res/AssetManager;->getResourcePackageName(I)Ljava/lang/String;
+Landroid/content/res/AssetManager;->getResourceTypeName(I)Ljava/lang/String;
+Landroid/content/res/AssetManager;->getStringBlockCount()I
+Landroid/content/res/AssetManager;-><init>()V
+Landroid/content/res/AssetManager;->isUpToDate()Z
+Landroid/content/res/AssetManager;->loadResourceBagValue(IILandroid/util/TypedValue;Z)I
+Landroid/content/res/AssetManager;->loadResourceValue(ISLandroid/util/TypedValue;Z)I
+Landroid/content/res/AssetManager;->loadThemeAttributeValue(JILandroid/util/TypedValue;Z)I
 Landroid/content/res/AssetManager;->mObject:J
+Landroid/content/res/AssetManager;->mStringBlocks:[Landroid/content/res/StringBlock;
+Landroid/content/res/AssetManager;->openNonAssetFdNative(ILjava/lang/String;[J)Landroid/os/ParcelFileDescriptor;
 Landroid/content/res/AssetManager;->openNonAsset(ILjava/lang/String;I)Ljava/io/InputStream;
 Landroid/content/res/AssetManager;->openNonAsset(ILjava/lang/String;)Ljava/io/InputStream;
 Landroid/content/res/AssetManager;->openNonAsset(Ljava/lang/String;I)Ljava/io/InputStream;
 Landroid/content/res/AssetManager;->openNonAsset(Ljava/lang/String;)Ljava/io/InputStream;
+Landroid/content/res/AssetManager;->openNonAssetNative(ILjava/lang/String;I)J
+Landroid/content/res/AssetManager;->openXmlAssetNative(ILjava/lang/String;)J
+Landroid/content/res/AssetManager;->resolveAttrs(JII[I[I[I[I)Z
+Landroid/content/res/AssetManager;->retrieveArray(I[I)I
+Landroid/content/res/AssetManager;->retrieveAttributes(J[I[I[I)Z
+Landroid/content/res/AssetManager;->setConfiguration(IILjava/lang/String;IIIIIIIIIIIIIII)V
+Landroid/content/res/AssetManager;->STYLE_NUM_ENTRIES:I
+Landroid/content/res/AssetManager;->STYLE_RESOURCE_ID:I
+Landroid/content/res/ColorStateList$ColorStateListFactory;-><init>(Landroid/content/res/ColorStateList;)V
+Landroid/content/res/ColorStateList;->mColors:[I
+Landroid/content/res/ColorStateList;->mDefaultColor:I
+Landroid/content/res/ColorStateList;->mFactory:Landroid/content/res/ColorStateList$ColorStateListFactory;
+Landroid/content/res/CompatibilityInfo;->DEFAULT_COMPATIBILITY_INFO:Landroid/content/res/CompatibilityInfo;
 Landroid/content/res/DrawableCache;->getInstance(JLandroid/content/res/Resources;Landroid/content/res/Resources$Theme;)Landroid/graphics/drawable/Drawable;
+Landroid/content/res/ObbInfo;->salt:[B
 Landroid/content/res/Resources;->getCompatibilityInfo()Landroid/content/res/CompatibilityInfo;
 Landroid/content/res/ResourcesImpl;->mAccessLock:Ljava/lang/Object;
 Landroid/content/res/ResourcesImpl;->mAssets:Landroid/content/res/AssetManager;
@@ -298,15 +538,20 @@
 Landroid/content/res/ResourcesImpl;->mDrawableCache:Landroid/content/res/DrawableCache;
 Landroid/content/res/ResourcesImpl;->mPreloading:Z
 Landroid/content/res/ResourcesImpl;->sPreloadedColorDrawables:Landroid/util/LongSparseArray;
+Landroid/content/res/ResourcesImpl;->sPreloadedComplexColors:Landroid/util/LongSparseArray;
 Landroid/content/res/ResourcesImpl;->sPreloadedDrawables:[Landroid/util/LongSparseArray;
 Landroid/content/res/ResourcesImpl;->TRACE_FOR_MISS_PRELOAD:Z
 Landroid/content/res/ResourcesImpl;->TRACE_FOR_PRELOAD:Z
+Landroid/content/res/ResourcesKey;->mSplitResDirs:[Ljava/lang/String;
 Landroid/content/res/Resources;->loadXmlResourceParser(ILjava/lang/String;)Landroid/content/res/XmlResourceParser;
 Landroid/content/res/Resources;->loadXmlResourceParser(Ljava/lang/String;IILjava/lang/String;)Landroid/content/res/XmlResourceParser;
 Landroid/content/res/Resources;->mResourcesImpl:Landroid/content/res/ResourcesImpl;
 Landroid/content/res/Resources;->mTmpValue:Landroid/util/TypedValue;
 Landroid/content/res/Resources;->mTypedArrayPool:Landroid/util/Pools$SynchronizedPool;
 Landroid/content/res/Resources;->setCompatibilityInfo(Landroid/content/res/CompatibilityInfo;)V
+Landroid/content/res/Resources;->updateSystemConfiguration(Landroid/content/res/Configuration;Landroid/util/DisplayMetrics;Landroid/content/res/CompatibilityInfo;)V
+Landroid/content/res/StringBlock;-><init>(JZ)V
+Landroid/content/res/TypedArray;->getNonConfigurationString(II)Ljava/lang/String;
 Landroid/content/res/TypedArray;->getValueAt(ILandroid/util/TypedValue;)Z
 Landroid/content/res/TypedArray;->mAssets:Landroid/content/res/AssetManager;
 Landroid/content/res/TypedArray;->mData:[I
@@ -318,18 +563,49 @@
 Landroid/content/res/TypedArray;->mTheme:Landroid/content/res/Resources$Theme;
 Landroid/content/res/TypedArray;->mValue:Landroid/util/TypedValue;
 Landroid/content/res/TypedArray;->mXml:Landroid/content/res/XmlBlock$Parser;
+Landroid/content/res/XmlBlock;->close()V
+Landroid/content/res/XmlBlock;-><init>([B)V
 Landroid/content/res/XmlBlock;->newParser()Landroid/content/res/XmlResourceParser;
 Landroid/content/res/XmlBlock$Parser;->mParseState:J
 Landroid/content/SyncStatusInfo;->lastSuccessTime:J
+Landroid/database/AbstractCursor;->mExtras:Landroid/os/Bundle;
 Landroid/database/AbstractCursor;->mNotifyUri:Landroid/net/Uri;
 Landroid/database/CursorWindow;->mWindowPtr:J
 Landroid/database/CursorWindow;->sCursorWindowSize:I
 Landroid/database/CursorWindow;->sWindowToPidMap:Landroid/util/LongSparseArray;
 Landroid/database/CursorWrapper;->mCursor:Landroid/database/Cursor;
+Landroid/database/sqlite/SQLiteCustomFunction;->dispatchCallback([Ljava/lang/String;)V
+Landroid/database/sqlite/SQLiteCustomFunction;->name:Ljava/lang/String;
+Landroid/database/sqlite/SQLiteCustomFunction;->numArgs:I
+Landroid/database/sqlite/SQLiteDatabaseConfiguration;->maxSqlCacheSize:I
+Landroid/database/sqlite/SQLiteDatabase;->mConfigurationLocked:Landroid/database/sqlite/SQLiteDatabaseConfiguration;
+Landroid/database/sqlite/SQLiteDatabase;->mConnectionPoolLocked:Landroid/database/sqlite/SQLiteConnectionPool;
+Landroid/database/sqlite/SQLiteDebug$PagerStats;->largestMemAlloc:I
+Landroid/database/sqlite/SQLiteDebug$PagerStats;->memoryUsed:I
+Landroid/database/sqlite/SQLiteDebug$PagerStats;->pageCacheOverflow:I
+Landroid/database/sqlite/SQLiteOpenHelper;->mName:Ljava/lang/String;
+Landroid/ddm/DdmHandleAppName;->getAppName()Ljava/lang/String;
+Landroid/graphics/BaseCanvas;->mNativeCanvasWrapper:J
 Landroid/graphics/Bitmap$Config;->nativeInt:I
+Landroid/graphics/Bitmap$Config;->nativeToConfig(I)Landroid/graphics/Bitmap$Config;
 Landroid/graphics/Bitmap;->createAshmemBitmap()Landroid/graphics/Bitmap;
 Landroid/graphics/Bitmap;->createAshmemBitmap(Landroid/graphics/Bitmap$Config;)Landroid/graphics/Bitmap;
+Landroid/graphics/BitmapFactory;->nativeDecodeAsset(JLandroid/graphics/Rect;Landroid/graphics/BitmapFactory$Options;)Landroid/graphics/Bitmap;
+Landroid/graphics/BitmapFactory;->nativeDecodeByteArray([BIILandroid/graphics/BitmapFactory$Options;)Landroid/graphics/Bitmap;
+Landroid/graphics/BitmapFactory;->nativeDecodeFileDescriptor(Ljava/io/FileDescriptor;Landroid/graphics/Rect;Landroid/graphics/BitmapFactory$Options;)Landroid/graphics/Bitmap;
+Landroid/graphics/BitmapFactory;->nativeDecodeStream(Ljava/io/InputStream;[BLandroid/graphics/Rect;Landroid/graphics/BitmapFactory$Options;)Landroid/graphics/Bitmap;
 Landroid/graphics/Bitmap;->getDefaultDensity()I
+Landroid/graphics/Bitmap;-><init>(JIIIZZ[BLandroid/graphics/NinePatch$InsetStruct;)V
+Landroid/graphics/Bitmap;->mNativePtr:J
+Landroid/graphics/Bitmap;->mNinePatchChunk:[B
+Landroid/graphics/Bitmap;->mNinePatchInsets:Landroid/graphics/NinePatch$InsetStruct;
+Landroid/graphics/BitmapRegionDecoder;-><init>(J)V
+Landroid/graphics/Bitmap;->reinit(IIZ)V
+Landroid/graphics/Camera;->native_instance:J
+Landroid/graphics/Canvas;-><init>(J)V
+Landroid/graphics/Canvas;->release()V
+Landroid/graphics/drawable/AnimatedImageDrawable;->onAnimationEnd()V
+Landroid/graphics/drawable/AnimatedVectorDrawable$VectorDrawableAnimatorRT;->callOnFinished(Landroid/graphics/drawable/AnimatedVectorDrawable$VectorDrawableAnimatorRT;I)V
 Landroid/graphics/drawable/AnimationDrawable;->mCurFrame:I
 Landroid/graphics/drawable/BitmapDrawable;->getTint()Landroid/content/res/ColorStateList;
 Landroid/graphics/drawable/BitmapDrawable;->getTintMode()Landroid/graphics/PorterDuff$Mode;
@@ -339,6 +615,11 @@
 Landroid/graphics/drawable/DrawableContainer;->mDrawableContainerState:Landroid/graphics/drawable/DrawableContainer$DrawableContainerState;
 Landroid/graphics/drawable/Drawable;->inflateWithAttributes(Landroid/content/res/Resources;Lorg/xmlpull/v1/XmlPullParser;Landroid/content/res/TypedArray;I)V
 Landroid/graphics/drawable/Drawable;->mCallback:Ljava/lang/ref/WeakReference;
+Landroid/graphics/drawable/GradientDrawable$GradientState;->mAngle:I
+Landroid/graphics/drawable/GradientDrawable$GradientState;->mPadding:Landroid/graphics/Rect;
+Landroid/graphics/drawable/GradientDrawable$GradientState;->mPositions:[F
+Landroid/graphics/drawable/GradientDrawable;->mPadding:Landroid/graphics/Rect;
+Landroid/graphics/drawable/Icon;->getResPackage()Ljava/lang/String;
 Landroid/graphics/drawable/NinePatchDrawable;->mNinePatchState:Landroid/graphics/drawable/NinePatchDrawable$NinePatchState;
 Landroid/graphics/drawable/NinePatchDrawable$NinePatchState;->mNinePatch:Landroid/graphics/NinePatch;
 Landroid/graphics/drawable/StateListDrawable;->extractStateSet(Landroid/util/AttributeSet;)[I
@@ -352,18 +633,45 @@
 Landroid/graphics/FontFamily;->addFontFromBuffer(Ljava/nio/ByteBuffer;I[Landroid/graphics/fonts/FontVariationAxis;II)Z
 Landroid/graphics/FontFamily;->freeze()Z
 Landroid/graphics/FontFamily;-><init>()V
+Landroid/graphics/fonts/FontVariationAxis;->mStyleValue:F
+Landroid/graphics/fonts/FontVariationAxis;->mTag:I
+Landroid/graphics/GraphicBuffer;->createFromExisting(IIIIJ)Landroid/graphics/GraphicBuffer;
+Landroid/graphics/GraphicBuffer;-><init>(IIIIJ)V
+Landroid/graphics/GraphicBuffer;->mNativeObject:J
+Landroid/graphics/ImageDecoder;-><init>(JIIZ)V
+Landroid/graphics/ImageDecoder;->onPartialImage(I)Z
+Landroid/graphics/ImageDecoder;->postProcessAndRelease(Landroid/graphics/Canvas;)I
 Landroid/graphics/LinearGradient;->mColors:[I
+Landroid/graphics/Matrix;->native_instance:J
+Landroid/graphics/Movie;-><init>(J)V
+Landroid/graphics/Movie;->mNativeMovie:J
+Landroid/graphics/NinePatch$InsetStruct;-><init>(IIIIIIIIFIF)V
 Landroid/graphics/NinePatch;->mBitmap:Landroid/graphics/Bitmap;
+Landroid/graphics/Picture;->mNativePicture:J
+Landroid/graphics/Region;-><init>(JI)V
+Landroid/graphics/Region;->mNativeRegion:J
+Landroid/graphics/SurfaceTexture;->mFrameAvailableListener:J
+Landroid/graphics/SurfaceTexture;->mProducer:J
+Landroid/graphics/SurfaceTexture;->mSurfaceTexture:J
 Landroid/graphics/SurfaceTexture;->nativeDetachFromGLContext()I
+Landroid/graphics/SurfaceTexture;->postEventFromNative(Ljava/lang/ref/WeakReference;)V
 Landroid/graphics/Typeface;->mStyle:I
 Landroid/graphics/Typeface;->sDefaults:[Landroid/graphics/Typeface;
 Landroid/graphics/Typeface;->setDefault(Landroid/graphics/Typeface;)V
 Landroid/graphics/Typeface;->sSystemFontMap:Ljava/util/Map;
+Landroid/hardware/camera2/CameraCharacteristics$Key;-><init>(Ljava/lang/String;Ljava/lang/Class;J)V
+Landroid/hardware/camera2/CaptureRequest$Key;-><init>(Ljava/lang/String;Ljava/lang/Class;J)V
+Landroid/hardware/camera2/CaptureResult$Key;-><init>(Ljava/lang/String;Ljava/lang/Class;J)V
+Landroid/hardware/camera2/impl/CameraMetadataNative;->mMetadataPtr:J
 Landroid/hardware/Camera;->addCallbackBuffer([BI)V
+Landroid/hardware/Camera;->mNativeContext:J
 Landroid/hardware/Camera;->openLegacy(II)Landroid/hardware/Camera;
+Landroid/hardware/Camera;->postEventFromNative(Ljava/lang/Object;IIILjava/lang/Object;)V
 Landroid/hardware/display/DisplayManager;->getStableDisplaySize()Landroid/graphics/Point;
 Landroid/hardware/display/WifiDisplayStatus;->mActiveDisplay:Landroid/hardware/display/WifiDisplay;
 Landroid/hardware/display/WifiDisplayStatus;->mDisplays:[Landroid/hardware/display/WifiDisplay;
+Landroid/hardware/HardwareBuffer;-><init>(J)V
+Landroid/hardware/HardwareBuffer;->mNativeObject:J
 Landroid/hardware/input/IInputManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/hardware/input/IInputManager;
 Landroid/hardware/input/InputManager;->getInstance()Landroid/hardware/input/InputManager;
 Landroid/hardware/input/InputManager;->mIm:Landroid/hardware/input/IInputManager;
@@ -404,19 +712,113 @@
 Landroid/hardware/location/NanoAppInstanceInfo;->getAppVersion()I
 Landroid/hardware/location/NanoAppInstanceInfo;->getHandle()I
 Landroid/hardware/location/NanoAppInstanceInfo;->getName()Ljava/lang/String;
+Landroid/hardware/SerialPort;->mNativeContext:I
+Landroid/hardware/soundtrigger/SoundTrigger$ConfidenceLevel;->confidenceLevel:I
+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$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
+Landroid/hardware/soundtrigger/SoundTrigger$KeyphraseRecognitionExtra;->coarseConfidenceLevel:I
+Landroid/hardware/soundtrigger/SoundTrigger$KeyphraseRecognitionExtra;->confidenceLevels:[Landroid/hardware/soundtrigger/SoundTrigger$ConfidenceLevel;
+Landroid/hardware/soundtrigger/SoundTrigger$KeyphraseRecognitionExtra;->id:I
+Landroid/hardware/soundtrigger/SoundTrigger$KeyphraseRecognitionExtra;-><init>(III[Landroid/hardware/soundtrigger/SoundTrigger$ConfidenceLevel;)V
+Landroid/hardware/soundtrigger/SoundTrigger$KeyphraseRecognitionExtra;->recognitionModes:I
+Landroid/hardware/soundtrigger/SoundTrigger$Keyphrase;->recognitionModes:I
+Landroid/hardware/soundtrigger/SoundTrigger$KeyphraseSoundModel;->keyphrases:[Landroid/hardware/soundtrigger/SoundTrigger$Keyphrase;
+Landroid/hardware/soundtrigger/SoundTrigger$Keyphrase;->text:Ljava/lang/String;
+Landroid/hardware/soundtrigger/SoundTrigger$Keyphrase;->users:[I
+Landroid/hardware/soundtrigger/SoundTriggerModule;->mId:I
+Landroid/hardware/soundtrigger/SoundTriggerModule;->mNativeContext:J
+Landroid/hardware/soundtrigger/SoundTriggerModule;->postEventFromNative(Ljava/lang/Object;IIILjava/lang/Object;)V
+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;->keyphrases:[Landroid/hardware/soundtrigger/SoundTrigger$KeyphraseRecognitionExtra;
+Landroid/hardware/soundtrigger/SoundTrigger$RecognitionEvent;-><init>(IIZIIIZLandroid/media/AudioFormat;[B)V
+Landroid/hardware/soundtrigger/SoundTrigger$SoundModel;->data:[B
+Landroid/hardware/soundtrigger/SoundTrigger$SoundModelEvent;-><init>(II[B)V
+Landroid/hardware/soundtrigger/SoundTrigger$SoundModel;->uuid:Ljava/util/UUID;
+Landroid/hardware/soundtrigger/SoundTrigger$SoundModel;->vendorUuid:Ljava/util/UUID;
+Landroid/hardware/SystemSensorManager$BaseEventQueue;->dispatchAdditionalInfoEvent(III[F[I)V
+Landroid/hardware/SystemSensorManager$BaseEventQueue;->dispatchFlushCompleteEvent(I)V
+Landroid/hardware/SystemSensorManager$BaseEventQueue;->dispatchSensorEvent(I[FIJ)V
+Landroid/hardware/usb/UsbDeviceConnection;->mNativeContext:J
 Landroid/hardware/usb/UsbManager;->setCurrentFunction(Ljava/lang/String;Z)V
+Landroid/hardware/usb/UsbRequest;->mNativeContext:J
+Landroid/icu/impl/number/DecimalFormatProperties;->readObject(Ljava/io/ObjectInputStream;)V
+Landroid/icu/impl/number/DecimalFormatProperties;->writeObject(Ljava/io/ObjectOutputStream;)V
+Landroid/icu/impl/TimeZoneGenericNames;->readObject(Ljava/io/ObjectInputStream;)V
+Landroid/icu/text/DateFormat;->readObject(Ljava/io/ObjectInputStream;)V
+Landroid/icu/text/DateFormatSymbols;->readObject(Ljava/io/ObjectInputStream;)V
+Landroid/icu/text/DateIntervalFormat;->readObject(Ljava/io/ObjectInputStream;)V
+Landroid/icu/text/DecimalFormat_ICU58_Android;->readObject(Ljava/io/ObjectInputStream;)V
+Landroid/icu/text/DecimalFormat_ICU58_Android;->writeObject(Ljava/io/ObjectOutputStream;)V
+Landroid/icu/text/DecimalFormat;->readObject(Ljava/io/ObjectInputStream;)V
+Landroid/icu/text/DecimalFormatSymbols;->readObject(Ljava/io/ObjectInputStream;)V
+Landroid/icu/text/DecimalFormat;->writeObject(Ljava/io/ObjectOutputStream;)V
+Landroid/icu/text/MessageFormat;->readObject(Ljava/io/ObjectInputStream;)V
+Landroid/icu/text/MessageFormat;->writeObject(Ljava/io/ObjectOutputStream;)V
+Landroid/icu/text/NumberFormat;->readObject(Ljava/io/ObjectInputStream;)V
+Landroid/icu/text/NumberFormat;->writeObject(Ljava/io/ObjectOutputStream;)V
+Landroid/icu/text/PluralFormat;->readObject(Ljava/io/ObjectInputStream;)V
+Landroid/icu/text/PluralRules$FixedDecimal;->readObject(Ljava/io/ObjectInputStream;)V
+Landroid/icu/text/PluralRules$FixedDecimal;->writeObject(Ljava/io/ObjectOutputStream;)V
+Landroid/icu/text/PluralRules;->readObject(Ljava/io/ObjectInputStream;)V
+Landroid/icu/text/PluralRules;->writeObject(Ljava/io/ObjectOutputStream;)V
+Landroid/icu/text/RuleBasedNumberFormat;->readObject(Ljava/io/ObjectInputStream;)V
+Landroid/icu/text/RuleBasedNumberFormat;->writeObject(Ljava/io/ObjectOutputStream;)V
+Landroid/icu/text/SelectFormat;->readObject(Ljava/io/ObjectInputStream;)V
+Landroid/icu/text/SimpleDateFormat;->readObject(Ljava/io/ObjectInputStream;)V
+Landroid/icu/text/SimpleDateFormat;->writeObject(Ljava/io/ObjectOutputStream;)V
+Landroid/icu/text/TimeZoneFormat;->readObject(Ljava/io/ObjectInputStream;)V
+Landroid/icu/text/TimeZoneFormat;->writeObject(Ljava/io/ObjectOutputStream;)V
+Landroid/icu/util/Calendar;->readObject(Ljava/io/ObjectInputStream;)V
+Landroid/icu/util/Calendar;->writeObject(Ljava/io/ObjectOutputStream;)V
+Landroid/icu/util/ChineseCalendar;->readObject(Ljava/io/ObjectInputStream;)V
+Landroid/icu/util/IslamicCalendar;->readObject(Ljava/io/ObjectInputStream;)V
+Landroid/icu/util/SimpleTimeZone;->readObject(Ljava/io/ObjectInputStream;)V
+Landroid/location/CountryDetector;->detectCountry()Landroid/location/Country;
+Landroid/location/Country;->getCountryIso()Ljava/lang/String;
+Landroid/location/Country;->getSource()I
 Landroid/location/GeocoderParams;->getClientPackage()Ljava/lang/String;
 Landroid/location/GeocoderParams;->getLocale()Ljava/util/Locale;
+Landroid/location/ILocationManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
+Landroid/location/LocationManager;->mService:Landroid/location/ILocationManager;
 Landroid/location/LocationManager;->requestLocationUpdates(Landroid/location/LocationRequest;Landroid/location/LocationListener;Landroid/os/Looper;)V
 Landroid/location/LocationRequest;->createFromDeprecatedProvider(Ljava/lang/String;JFZ)Landroid/location/LocationRequest;
 Landroid/location/LocationRequest;->setHideFromAppOps(Z)V
 Landroid/location/LocationRequest;->setWorkSource(Landroid/os/WorkSource;)V
 Landroid/location/Location;->setIsFromMockProvider(Z)V
+Landroid/Manifest$permission;->REAL_GET_TASKS:Ljava/lang/String;
 Landroid/media/AudioAttributes$Builder;->setInternalCapturePreset(I)Landroid/media/AudioAttributes$Builder;
+Landroid/media/AudioAttributes;->mContentType:I
+Landroid/media/AudioAttributes;->mFlags:I
+Landroid/media/AudioAttributes;->mFormattedTags:Ljava/lang/String;
+Landroid/media/AudioAttributes;->mSource:I
+Landroid/media/AudioAttributes;->mUsage:I
+Landroid/media/AudioDevicePortConfig;-><init>(Landroid/media/AudioDevicePort;IIILandroid/media/AudioGainConfig;)V
+Landroid/media/AudioDevicePort;-><init>(Landroid/media/AudioHandle;Ljava/lang/String;[I[I[I[I[Landroid/media/AudioGain;ILjava/lang/String;)V
 Landroid/media/AudioFocusInfo;->getClientId()Ljava/lang/String;
 Landroid/media/AudioFocusInfo;->getClientUid()I
 Landroid/media/AudioFocusInfo;->getLossReceived()I
+Landroid/media/AudioFormat;-><init>(IIII)V
+Landroid/media/AudioFormat;->mChannelMask:I
+Landroid/media/AudioFormat;->mEncoding:I
+Landroid/media/AudioFormat;->mSampleRate:I
+Landroid/media/audiofx/AudioEffect;-><init>(Ljava/util/UUID;Ljava/util/UUID;II)V
+Landroid/media/AudioGainConfig;-><init>(ILandroid/media/AudioGain;II[II)V
+Landroid/media/AudioGainConfig;->mChannelMask:I
+Landroid/media/AudioGainConfig;->mIndex:I
+Landroid/media/AudioGainConfig;->mMode:I
+Landroid/media/AudioGainConfig;->mRampDurationMs:I
+Landroid/media/AudioGainConfig;->mValues:[I
+Landroid/media/AudioGain;-><init>(IIIIIIIII)V
+Landroid/media/AudioHandle;-><init>(I)V
+Landroid/media/AudioHandle;->mId:I
 Landroid/media/AudioManager;->abandonAudioFocus(Landroid/media/AudioManager$OnAudioFocusChangeListener;Landroid/media/AudioAttributes;)I
+Landroid/media/AudioManager;->getService()Landroid/media/IAudioService;
 Landroid/media/AudioManager;->mAudioFocusIdListenerMap:Ljava/util/concurrent/ConcurrentHashMap;
 Landroid/media/AudioManager;->registerAudioPolicy(Landroid/media/audiopolicy/AudioPolicy;)I
 Landroid/media/AudioManager;->requestAudioFocus(Landroid/media/AudioFocusRequest;Landroid/media/audiopolicy/AudioPolicy;)I
@@ -427,13 +829,28 @@
 Landroid/media/AudioManager;->STREAM_SYSTEM_ENFORCED:I
 Landroid/media/AudioManager;->STREAM_TTS:I
 Landroid/media/AudioManager;->unregisterAudioPolicyAsync(Landroid/media/audiopolicy/AudioPolicy;)V
+Landroid/media/AudioMixPortConfig;-><init>(Landroid/media/AudioMixPort;IIILandroid/media/AudioGainConfig;)V
+Landroid/media/AudioMixPort;-><init>(Landroid/media/AudioHandle;IILjava/lang/String;[I[I[I[I[Landroid/media/AudioGain;)V
+Landroid/media/AudioPatch;-><init>(Landroid/media/AudioHandle;[Landroid/media/AudioPortConfig;[Landroid/media/AudioPortConfig;)V
+Landroid/media/AudioPatch;->mHandle:Landroid/media/AudioHandle;
 Landroid/media/audiopolicy/AudioMix$Builder;->build()Landroid/media/audiopolicy/AudioMix;
 Landroid/media/audiopolicy/AudioMix$Builder;-><init>(Landroid/media/audiopolicy/AudioMixingRule;)V
 Landroid/media/audiopolicy/AudioMix$Builder;->setFormat(Landroid/media/AudioFormat;)Landroid/media/audiopolicy/AudioMix$Builder;
 Landroid/media/audiopolicy/AudioMix$Builder;->setRouteFlags(I)Landroid/media/audiopolicy/AudioMix$Builder;
+Landroid/media/audiopolicy/AudioMixingRule$AudioMixMatchCriterion;->mAttr:Landroid/media/AudioAttributes;
+Landroid/media/audiopolicy/AudioMixingRule$AudioMixMatchCriterion;->mIntProp:I
+Landroid/media/audiopolicy/AudioMixingRule$AudioMixMatchCriterion;->mRule:I
 Landroid/media/audiopolicy/AudioMixingRule$Builder;->addRule(Landroid/media/AudioAttributes;I)Landroid/media/audiopolicy/AudioMixingRule$Builder;
 Landroid/media/audiopolicy/AudioMixingRule$Builder;->build()Landroid/media/audiopolicy/AudioMixingRule;
 Landroid/media/audiopolicy/AudioMixingRule$Builder;-><init>()V
+Landroid/media/audiopolicy/AudioMixingRule;->mCriteria:Ljava/util/ArrayList;
+Landroid/media/audiopolicy/AudioMix;->mCallbackFlags:I
+Landroid/media/audiopolicy/AudioMix;->mDeviceAddress:Ljava/lang/String;
+Landroid/media/audiopolicy/AudioMix;->mDeviceSystemType:I
+Landroid/media/audiopolicy/AudioMix;->mFormat:Landroid/media/AudioFormat;
+Landroid/media/audiopolicy/AudioMix;->mMixType:I
+Landroid/media/audiopolicy/AudioMix;->mRouteFlags:I
+Landroid/media/audiopolicy/AudioMix;->mRule:Landroid/media/audiopolicy/AudioMixingRule;
 Landroid/media/audiopolicy/AudioPolicy$AudioPolicyFocusListener;-><init>()V
 Landroid/media/audiopolicy/AudioPolicy$Builder;->addMix(Landroid/media/audiopolicy/AudioMix;)Landroid/media/audiopolicy/AudioPolicy$Builder;
 Landroid/media/audiopolicy/AudioPolicy$Builder;->build()Landroid/media/audiopolicy/AudioPolicy;
@@ -441,18 +858,54 @@
 Landroid/media/audiopolicy/AudioPolicy$Builder;->setAudioPolicyFocusListener(Landroid/media/audiopolicy/AudioPolicy$AudioPolicyFocusListener;)V
 Landroid/media/audiopolicy/AudioPolicy$Builder;->setLooper(Landroid/os/Looper;)Landroid/media/audiopolicy/AudioPolicy$Builder;
 Landroid/media/audiopolicy/AudioPolicy;->createAudioRecordSink(Landroid/media/audiopolicy/AudioMix;)Landroid/media/AudioRecord;
+Landroid/media/AudioPortConfig;-><init>(Landroid/media/AudioPort;IIILandroid/media/AudioGainConfig;)V
+Landroid/media/AudioPortConfig;->mChannelMask:I
+Landroid/media/AudioPortConfig;->mConfigMask:I
+Landroid/media/AudioPortConfig;->mFormat:I
+Landroid/media/AudioPortConfig;->mGain:Landroid/media/AudioGainConfig;
+Landroid/media/AudioPortConfig;->mPort:Landroid/media/AudioPort;
+Landroid/media/AudioPortConfig;->mSamplingRate:I
+Landroid/media/AudioPortEventHandler;->mJniCallback:J
+Landroid/media/AudioPortEventHandler;->postEventFromNative(Ljava/lang/Object;IIILjava/lang/Object;)V
+Landroid/media/AudioPort;-><init>(Landroid/media/AudioHandle;ILjava/lang/String;[I[I[I[I[Landroid/media/AudioGain;)V
+Landroid/media/AudioPort;->mActiveConfig:Landroid/media/AudioPortConfig;
+Landroid/media/AudioPort;->mGains:[Landroid/media/AudioGain;
+Landroid/media/AudioPort;->mHandle:Landroid/media/AudioHandle;
+Landroid/media/AudioPort;->mRole:I
+Landroid/media/AudioRecord;->mNativeCallbackCookie:J
+Landroid/media/AudioRecord;->mNativeDeviceCallback:J
+Landroid/media/AudioRecord;->mNativeRecorderInJavaObj:J
+Landroid/media/AudioRecord;->postEventFromNative(Ljava/lang/Object;IIILjava/lang/Object;)V
+Landroid/media/AudioSystem;->dynamicPolicyCallbackFromNative(ILjava/lang/String;I)V
+Landroid/media/AudioSystem;->errorCallbackFromNative(I)V
+Landroid/media/AudioSystem;->getPrimaryOutputFrameCount()I
+Landroid/media/AudioSystem;->getPrimaryOutputSamplingRate()I
+Landroid/media/AudioSystem;->recordingCallbackFromNative(IIII[I)V
 Landroid/media/AudioSystem;->setDeviceConnectionState(IILjava/lang/String;Ljava/lang/String;)I
 Landroid/media/AudioTrack;->getLatency()I
+Landroid/media/AudioTrack;->mJniData:J
+Landroid/media/AudioTrack;->mNativeTrackInJavaObj:J
+Landroid/media/AudioTrack;->mStreamType:I
+Landroid/media/AudioTrack;->postEventFromNative(Ljava/lang/Object;IIILjava/lang/Object;)V
 Landroid/media/IAudioService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/media/IAudioService;
+Landroid/media/JetPlayer;->mNativePlayerInJavaObj:J
+Landroid/media/JetPlayer;->postEventFromNative(Ljava/lang/Object;III)V
 Landroid/media/MediaCodec;->releaseOutputBuffer(IZZJ)V
+Landroid/media/MediaFile;->FIRST_AUDIO_FILE_TYPE:I
 Landroid/media/MediaFile;->getFileType(Ljava/lang/String;)Landroid/media/MediaFile$MediaFileType;
 Landroid/media/MediaFile;->getMimeTypeForFile(Ljava/lang/String;)Ljava/lang/String;
+Landroid/media/MediaFile;-><init>()V
+Landroid/media/MediaFile;->isAudioFileType(I)Z
+Landroid/media/MediaFile;->isImageFileType(I)Z
 Landroid/media/MediaFile;->isVideoFileType(I)Z
+Landroid/media/MediaFile;->LAST_AUDIO_FILE_TYPE:I
 Landroid/media/MediaFile$MediaFileType;->fileType:I
+Landroid/media/MediaFile$MediaFileType;->mimeType:Ljava/lang/String;
 Landroid/media/MediaFile;->sFileTypeMap:Ljava/util/HashMap;
 Landroid/media/MediaMetadataRetriever;->getEmbeddedPicture(I)[B
 Landroid/media/MediaPlayer;->getMetadata(ZZ)Landroid/media/Metadata;
 Landroid/media/MediaPlayer;->invoke(Landroid/os/Parcel;Landroid/os/Parcel;)V
+Landroid/media/MediaPlayer;->mEventHandler:Landroid/media/MediaPlayer$EventHandler;
 Landroid/media/MediaPlayer;->newRequest()Landroid/os/Parcel;
 Landroid/media/MediaPlayer;->setDataSource(Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/String;Ljava/util/List;)V
 Landroid/media/MediaPlayer;->setDataSource(Ljava/lang/String;Ljava/util/Map;Ljava/util/List;)V
@@ -464,12 +917,47 @@
 Landroid/media/MediaRouter;->selectRouteInt(ILandroid/media/MediaRouter$RouteInfo;Z)V
 Landroid/media/MediaScanner;->mClient:Landroid/media/MediaScanner$MyMediaScannerClient;
 Landroid/media/MediaScanner;->scanSingleFile(Ljava/lang/String;Ljava/lang/String;)Landroid/net/Uri;
+Landroid/media/Metadata;->getBoolean(I)Z
+Landroid/media/Metadata;->has(I)Z
+Landroid/media/Metadata;->PAUSE_AVAILABLE:I
+Landroid/media/Metadata;->SEEK_BACKWARD_AVAILABLE:I
+Landroid/media/Metadata;->SEEK_FORWARD_AVAILABLE:I
+Landroid/media/MicrophoneInfo;-><init>(Ljava/lang/String;ILjava/lang/String;IIILandroid/media/MicrophoneInfo$Coordinate3F;Landroid/media/MicrophoneInfo$Coordinate3F;Ljava/util/List;Ljava/util/List;FFFI)V
 Landroid/media/MiniThumbFile;->reset()V
+Landroid/media/PlaybackParams;->mAudioFallbackMode:I
+Landroid/media/PlaybackParams;->mAudioStretchMode:I
+Landroid/media/PlaybackParams;->mPitch:F
+Landroid/media/PlaybackParams;->mSet:I
+Landroid/media/PlaybackParams;->mSpeed:F
+Landroid/media/PlaybackParams;->SET_AUDIO_FALLBACK_MODE:I
+Landroid/media/PlaybackParams;->SET_AUDIO_STRETCH_MODE:I
+Landroid/media/PlaybackParams;->SET_PITCH:I
+Landroid/media/PlaybackParams;->SET_SPEED:I
+Landroid/media/RemoteDisplay;->notifyDisplayConnected(Landroid/view/Surface;IIII)V
+Landroid/media/RemoteDisplay;->notifyDisplayDisconnected()V
+Landroid/media/RemoteDisplay;->notifyDisplayError(I)V
 Landroid/media/RingtoneManager;->getRingtone(Landroid/content/Context;Landroid/net/Uri;I)Landroid/media/Ringtone;
 Landroid/media/Ringtone;->setLooping(Z)V
 Landroid/media/Ringtone;->setVolume(F)V
+Landroid/media/session/MediaSessionLegacyHelper;->getHelper(Landroid/content/Context;)Landroid/media/session/MediaSessionLegacyHelper;
 Landroid/media/SubtitleController;->mHandler:Landroid/os/Handler;
 Landroid/media/ThumbnailUtils;->createImageThumbnail(Ljava/lang/String;I)Landroid/graphics/Bitmap;
+Landroid/media/ToneGenerator;->mNativeContext:J
+Landroid/media/VolumeShaper$Configuration;-><init>(IIIDI[F[F)V
+Landroid/media/VolumeShaper$Configuration;->mDurationMs:D
+Landroid/media/VolumeShaper$Configuration;->mId:I
+Landroid/media/VolumeShaper$Configuration;->mInterpolatorType:I
+Landroid/media/VolumeShaper$Configuration;->mOptionFlags:I
+Landroid/media/VolumeShaper$Configuration;->mTimes:[F
+Landroid/media/VolumeShaper$Configuration;->mType:I
+Landroid/media/VolumeShaper$Configuration;->mVolumes:[F
+Landroid/media/VolumeShaper$Operation;-><init>(IIF)V
+Landroid/media/VolumeShaper$Operation;->mFlags:I
+Landroid/media/VolumeShaper$Operation;->mReplaceId:I
+Landroid/media/VolumeShaper$Operation;->mXOffset:F
+Landroid/media/VolumeShaper$State;-><init>(FF)V
+Landroid/media/VolumeShaper$State;->mVolume:F
+Landroid/media/VolumeShaper$State;->mXOffset:F
 Landroid/metrics/LogMaker;->getCategory()I
 Landroid/metrics/LogMaker;->getCounterBucket()J
 Landroid/metrics/LogMaker;->getCounterName()Ljava/lang/String;
@@ -501,8 +989,23 @@
 Landroid/net/ConnectivityManager;->startTethering(IZLandroid/net/ConnectivityManager$OnStartTetheringCallback;Landroid/os/Handler;)V
 Landroid/net/ConnectivityManager;->startTethering(IZLandroid/net/ConnectivityManager$OnStartTetheringCallback;)V
 Landroid/net/ConnectivityManager;->stopTethering(I)V
+Landroid/net/ConnectivityManager;->TYPE_MOBILE_CBS:I
+Landroid/net/ConnectivityManager;->TYPE_MOBILE_EMERGENCY:I
+Landroid/net/ConnectivityManager;->TYPE_MOBILE_FOTA:I
+Landroid/net/ConnectivityManager;->TYPE_MOBILE_IA:I
+Landroid/net/ConnectivityManager;->TYPE_MOBILE_IMS:I
+Landroid/net/ConnectivityManager;->TYPE_NONE:I
+Landroid/net/ConnectivityManager;->TYPE_PROXY:I
+Landroid/net/ConnectivityManager;->TYPE_WIFI_P2P:I
+Landroid/net/IConnectivityManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/net/IConnectivityManager;
+Landroid/net/IConnectivityManager$Stub$Proxy;->getAllNetworks()[Landroid/net/Network;
+Landroid/net/IConnectivityManager$Stub$Proxy;->getTetherableIfaces()[Ljava/lang/String;
+Landroid/net/IConnectivityManager$Stub$Proxy;->getTetherableUsbRegexs()[Ljava/lang/String;
+Landroid/net/IConnectivityManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/net/INetworkStatsService$Stub$Proxy;->getMobileIfaces()[Ljava/lang/String;
 Landroid/net/LinkProperties;->setHttpProxy(Landroid/net/ProxyInfo;)V
+Landroid/net/LocalSocketImpl;->inboundFileDescriptors:[Ljava/io/FileDescriptor;
+Landroid/net/LocalSocketImpl;->outboundFileDescriptors:[Ljava/io/FileDescriptor;
 Landroid/net/NetworkKey;-><init>(Landroid/net/WifiKey;)V
 Landroid/net/NetworkPolicyManager;->mService:Landroid/net/INetworkPolicyManager;
 Landroid/net/NetworkRecommendationProvider;-><init>(Landroid/content/Context;Ljava/util/concurrent/Executor;)V
@@ -523,6 +1026,7 @@
 Landroid/net/NetworkStats;->txBytes:[J
 Landroid/net/NetworkStats;->txPackets:[J
 Landroid/net/NetworkStats;->uid:[I
+Landroid/net/ProxyInfo;-><init>(Ljava/lang/String;ILjava/lang/String;)V
 Landroid/net/RssiCurve;-><init>(II[BI)V
 Landroid/net/RssiCurve;-><init>(II[B)V
 Landroid/net/RssiCurve;->lookupScore(IZ)B
@@ -553,10 +1057,17 @@
 Landroid/net/SSLCertificateSocketFactory;->TAG:Ljava/lang/String;
 Landroid/net/SSLCertificateSocketFactory;->toLengthPrefixedList([[[B)[B
 Landroid/net/SSLCertificateSocketFactory;->verifyHostname(Ljava/net/Socket;Ljava/lang/String;)V
+Landroid/net/SSLSessionCache;->mSessionCache:Lcom/android/org/conscrypt/SSLClientSessionCache;
+Landroid/net/TrafficStats;->getRxBytes(Ljava/lang/String;)J
 Landroid/net/TrafficStats;->getStatsService()Landroid/net/INetworkStatsService;
+Landroid/net/TrafficStats;->getTxBytes(Ljava/lang/String;)J
 Landroid/net/TrafficStats;->setThreadStatsTagBackup()V
 Landroid/net/TrafficStats;->setThreadStatsTagRestore()V
 Landroid/net/TrafficStats;->setThreadStatsUid(I)V
+Landroid/net/Uri;-><init>()V
+Landroid/net/WebAddress;-><init>(Ljava/lang/String;)V
+Landroid/net/wifi/IWifiManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/net/wifi/IWifiManager;
+Landroid/net/wifi/IWifiManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/net/WifiKey;-><init>(Ljava/lang/String;Ljava/lang/String;)V
 Landroid/net/wifi/p2p/WifiP2pGroup;->getNetworkId()I
 Landroid/net/wifi/p2p/WifiP2pGroupList;->getGroupList()Ljava/util/Collection;
@@ -566,13 +1077,30 @@
 Landroid/net/wifi/RttManager;->getRttCapabilities()Landroid/net/wifi/RttManager$RttCapabilities;
 Landroid/net/wifi/RttManager$RttParams;-><init>()V
 Landroid/net/wifi/RttManager;->startRanging([Landroid/net/wifi/RttManager$RttParams;Landroid/net/wifi/RttManager$RttListener;)V
+Landroid/net/wifi/ScanResult;->anqpDomainId:I
+Landroid/net/wifi/ScanResult;->anqpLines:Ljava/util/List;
+Landroid/net/wifi/ScanResult;->distanceCm:I
+Landroid/net/wifi/ScanResult;->distanceSdCm:I
+Landroid/net/wifi/ScanResult;->flags:J
+Landroid/net/wifi/ScanResult;->hessid:J
+Landroid/net/wifi/ScanResult;->numUsage:I
+Landroid/net/wifi/ScanResult;->seen:J
+Landroid/net/wifi/ScanResult;->untrusted:Z
+Landroid/net/wifi/ScanResult;->wifiSsid:Landroid/net/wifi/WifiSsid;
 Landroid/net/wifi/WifiConfiguration;->apBand:I
 Landroid/net/wifi/WifiConfiguration;->apChannel:I
+Landroid/net/wifi/WifiConfiguration;->creatorUid:I
 Landroid/net/wifi/WifiConfiguration;->hasNoInternetAccess()Z
 Landroid/net/wifi/WifiConfiguration;->isEphemeral()Z
 Landroid/net/wifi/WifiConfiguration;->isNoInternetAccessExpected()Z
+Landroid/net/wifi/WifiConfiguration;->lastUpdateUid:I
 Landroid/net/wifi/WifiConfiguration;->mIpConfiguration:Landroid/net/IpConfiguration;
+Landroid/net/wifi/WifiConfiguration;->numAssociation:I
 Landroid/net/wifi/WifiConfiguration;->validatedInternetAccess:Z
+Landroid/net/wifi/WifiEnterpriseConfig;->getCaCertificateAlias()Ljava/lang/String;
+Landroid/net/wifi/WifiEnterpriseConfig;->getClientCertificateAlias()Ljava/lang/String;
+Landroid/net/wifi/WifiInfo;->getMeteredHint()Z
+Landroid/net/wifi/WifiManager;->cancelLocalOnlyHotspotRequest()V
 Landroid/net/wifi/WifiManager;->connect(ILandroid/net/wifi/WifiManager$ActionListener;)V
 Landroid/net/wifi/WifiManager;->connect(Landroid/net/wifi/WifiConfiguration;Landroid/net/wifi/WifiManager$ActionListener;)V
 Landroid/net/wifi/WifiManager;->EXTRA_WIFI_AP_STATE:Ljava/lang/String;
@@ -600,6 +1128,7 @@
 Landroid/net/wifi/WifiScanner;->startScan(Landroid/net/wifi/WifiScanner$ScanSettings;Landroid/net/wifi/WifiScanner$ScanListener;Landroid/os/WorkSource;)V
 Landroid/net/wifi/WifiScanner;->startScan(Landroid/net/wifi/WifiScanner$ScanSettings;Landroid/net/wifi/WifiScanner$ScanListener;)V
 Landroid/net/wifi/WifiScanner;->stopBackgroundScan(Landroid/net/wifi/WifiScanner$ScanListener;)V
+Landroid/net/wifi/WifiSsid;->NONE:Ljava/lang/String;
 Landroid/nfc/NfcAdapter;->addNfcUnlockHandler(Landroid/nfc/NfcAdapter$NfcUnlockHandler;[Ljava/lang/String;)Z
 Landroid/nfc/NfcAdapter;->disable()Z
 Landroid/nfc/NfcAdapter;->enable()Z
@@ -616,6 +1145,7 @@
 Landroid/os/AsyncTask;->mWorker:Landroid/os/AsyncTask$WorkerRunnable;
 Landroid/os/AsyncTask;->sDefaultExecutor:Ljava/util/concurrent/Executor;
 Landroid/os/AsyncTask;->setDefaultExecutor(Ljava/util/concurrent/Executor;)V
+Landroid/os/BatteryStats;->getUidStats()Landroid/util/SparseArray;
 Landroid/os/BatteryStats$HistoryItem;->states2:I
 Landroid/os/BatteryStats;->NUM_DATA_CONNECTION_TYPES:I
 Landroid/os/BatteryStats$Timer;->getTotalTimeLocked(JI)J
@@ -630,18 +1160,45 @@
 Landroid/os/BatteryStats$Uid$Proc;->getUserTime(I)J
 Landroid/os/BatteryStats$Uid$Sensor;->getHandle()I
 Landroid/os/BatteryStats$Uid$Sensor;->getSensorTime()Landroid/os/BatteryStats$Timer;
+Landroid/os/Binder;->execTransact(IJJI)Z
+Landroid/os/Binder;->mObject:J
 Landroid/os/Build;->getString(Ljava/lang/String;)Ljava/lang/String;
+Landroid/os/Build$VERSION;->ACTIVE_CODENAMES:[Ljava/lang/String;
+Landroid/os/Build$VERSION;->RESOURCES_SDK_INT:I
 Landroid/os/Bundle;->getIBinder(Ljava/lang/String;)Landroid/os/IBinder;
 Landroid/os/Bundle;->putIBinder(Ljava/lang/String;Landroid/os/IBinder;)V
 Landroid/os/Debug;->countInstancesOfClass(Ljava/lang/Class;)J
 Landroid/os/Debug;->dumpReferenceTables()V
+Landroid/os/Debug$MemoryInfo;->dalvikPrivateClean:I
+Landroid/os/Debug$MemoryInfo;->dalvikRss:I
+Landroid/os/Debug$MemoryInfo;->dalvikSharedClean:I
+Landroid/os/Debug$MemoryInfo;->dalvikSwappablePss:I
+Landroid/os/Debug$MemoryInfo;->dalvikSwappedOut:I
+Landroid/os/Debug$MemoryInfo;->dalvikSwappedOutPss:I
 Landroid/os/Debug$MemoryInfo;->getOtherLabel(I)Ljava/lang/String;
 Landroid/os/Debug$MemoryInfo;->getOtherPrivateDirty(I)I
+Landroid/os/Debug$MemoryInfo;->getOtherPrivate(I)I
 Landroid/os/Debug$MemoryInfo;->getOtherPss(I)I
 Landroid/os/Debug$MemoryInfo;->getOtherSharedDirty(I)I
+Landroid/os/Debug$MemoryInfo;->getTotalUss()I
+Landroid/os/Debug$MemoryInfo;->hasSwappedOutPss:Z
+Landroid/os/Debug$MemoryInfo;->nativePrivateClean:I
+Landroid/os/Debug$MemoryInfo;->nativeRss:I
+Landroid/os/Debug$MemoryInfo;->nativeSharedClean:I
+Landroid/os/Debug$MemoryInfo;->nativeSwappablePss:I
+Landroid/os/Debug$MemoryInfo;->nativeSwappedOut:I
+Landroid/os/Debug$MemoryInfo;->nativeSwappedOutPss:I
 Landroid/os/Debug$MemoryInfo;->NUM_DVK_STATS:I
 Landroid/os/Debug$MemoryInfo;->NUM_OTHER_STATS:I
+Landroid/os/Debug$MemoryInfo;->otherPrivateClean:I
+Landroid/os/Debug$MemoryInfo;->otherRss:I
+Landroid/os/Debug$MemoryInfo;->otherSharedClean:I
+Landroid/os/Debug$MemoryInfo;->otherStats:[I
+Landroid/os/Debug$MemoryInfo;->otherSwappablePss:I
+Landroid/os/Debug$MemoryInfo;->otherSwappedOut:I
+Landroid/os/Debug$MemoryInfo;->otherSwappedOutPss:I
 Landroid/os/Environment;->buildExternalStorageAppDataDirs(Ljava/lang/String;)[Ljava/io/File;
+Landroid/os/FileObserver$ObserverThread;->onEvent(IILjava/lang/String;)V
 Landroid/os/FileUtils;->checksumCrc32(Ljava/io/File;)J
 Landroid/os/FileUtils;->copyFile(Ljava/io/File;Ljava/io/File;)Z
 Landroid/os/FileUtils;->copyToFile(Ljava/io/InputStream;Ljava/io/File;)Z
@@ -656,21 +1213,40 @@
 Landroid/os/Handler;->hasCallbacks(Ljava/lang/Runnable;)Z
 Landroid/os/Handler;->mCallback:Landroid/os/Handler$Callback;
 Landroid/os/Handler;->mMessenger:Landroid/os/IMessenger;
+Landroid/os/HwParcel;-><init>(Z)V
+Landroid/os/IPermissionController$Stub;->asInterface(Landroid/os/IBinder;)Landroid/os/IPermissionController;
+Landroid/os/IPermissionController$Stub$Proxy;->checkPermission(Ljava/lang/String;II)Z
 Landroid/os/IPowerManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/os/IPowerManager;
+Landroid/os/IPowerManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
+Landroid/os/IPowerManager$Stub$Proxy;->isLightDeviceIdleMode()Z
 Landroid/os/IPowerManager;->userActivity(JII)V
+Landroid/os/IServiceManager;->getService(Ljava/lang/String;)Landroid/os/IBinder;
+Landroid/os/IUserManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/os/Looper;->mQueue:Landroid/os/MessageQueue;
+Landroid/os/Looper;->setTraceTag(J)V
+Landroid/os/Looper;->sThreadLocal:Ljava/lang/ThreadLocal;
 Landroid/os/MemoryFile;->getFileDescriptor()Ljava/io/FileDescriptor;
 Landroid/os/Message;->callback:Ljava/lang/Runnable;
 Landroid/os/Message;->flags:I
+Landroid/os/Message;->markInUse()V
 Landroid/os/Message;->next:Landroid/os/Message;
+Landroid/os/MessageQueue;->dispatchEvents(II)I
 Landroid/os/MessageQueue;->mIdleHandlers:Ljava/util/ArrayList;
 Landroid/os/MessageQueue;->mMessages:Landroid/os/Message;
+Landroid/os/MessageQueue;->mPtr:J
 Landroid/os/MessageQueue;->mQuitAllowed:Z
+Landroid/os/MessageQueue;->nativePollOnce(JI)V
 Landroid/os/MessageQueue;->next()Landroid/os/Message;
+Landroid/os/Message;->recycleUnchecked()V
 Landroid/os/Message;->target:Landroid/os/Handler;
+Landroid/os/Message;->when:J
+Landroid/os/ParcelFileDescriptor;-><init>(Ljava/io/FileDescriptor;)V
+Landroid/os/Parcel;->mNativePtr:J
+Landroid/os/Parcel$ReadWriteHelper;-><init>()V
 Landroid/os/PowerManager;->getMaximumScreenBrightnessSetting()I
 Landroid/os/PowerManager;->getMinimumScreenBrightnessSetting()I
 Landroid/os/PowerManager;->isLightDeviceIdleMode()Z
+Landroid/os/PowerManager;->mService:Landroid/os/IPowerManager;
 Landroid/os/PowerManager;->userActivity(JII)V
 Landroid/os/PowerManager;->userActivity(JZ)V
 Landroid/os/PowerManager;->validateWakeLockParameters(ILjava/lang/String;)V
@@ -678,6 +1254,7 @@
 Landroid/os/PowerManager;->wakeUp(J)V
 Landroid/os/Process;->getParentPid(I)I
 Landroid/os/Process;->getPids(Ljava/lang/String;[I)[I
+Landroid/os/Process;->getTotalMemory()J
 Landroid/os/Process;->getUidForPid(I)I
 Landroid/os/Process;->isIsolated(I)Z
 Landroid/os/Process;->isIsolated()Z
@@ -691,18 +1268,30 @@
 Landroid/os/RecoverySystem;->scheduleUpdateOnBoot(Landroid/content/Context;Ljava/io/File;)V
 Landroid/os/SELinux;->isSELinuxEnabled()Z
 Landroid/os/SELinux;->isSELinuxEnforced()Z
+Landroid/os/ServiceManager;->addService(Ljava/lang/String;Landroid/os/IBinder;)V
 Landroid/os/ServiceManager;->checkService(Ljava/lang/String;)Landroid/os/IBinder;
+Landroid/os/ServiceManager;->getIServiceManager()Landroid/os/IServiceManager;
 Landroid/os/ServiceManager;->getService(Ljava/lang/String;)Landroid/os/IBinder;
+Landroid/os/ServiceManager;-><init>()V
+Landroid/os/ServiceManager;->listServices()[Ljava/lang/String;
+Landroid/os/ServiceManagerNative;->asInterface(Landroid/os/IBinder;)Landroid/os/IServiceManager;
+Landroid/os/ServiceManager;->sCache:Ljava/util/HashMap;
+Landroid/os/ServiceManager;->sServiceManager:Landroid/os/IServiceManager;
 Landroid/os/storage/DiskInfo;->getDescription()Ljava/lang/String;
+Landroid/os/storage/IStorageManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/os/storage/IStorageManager;
+Landroid/os/storage/IStorageManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/os/storage/StorageManager;->findVolumeByUuid(Ljava/lang/String;)Landroid/os/storage/VolumeInfo;
 Landroid/os/storage/StorageManager;->getBestVolumeDescription(Landroid/os/storage/VolumeInfo;)Ljava/lang/String;
 Landroid/os/storage/StorageManager;->getDisks()Ljava/util/List;
 Landroid/os/storage/StorageManager;->getStorageBytesUntilLow(Ljava/io/File;)J
+Landroid/os/storage/StorageManager;->getStorageLowBytes(Ljava/io/File;)J
 Landroid/os/storage/StorageManager;->getVolumeList(II)[Landroid/os/storage/StorageVolume;
 Landroid/os/storage/StorageManager;->getVolumeList()[Landroid/os/storage/StorageVolume;
 Landroid/os/storage/StorageManager;->getVolumePaths()[Ljava/lang/String;
 Landroid/os/storage/StorageManager;->getVolumes()Ljava/util/List;
 Landroid/os/storage/StorageManager;->getVolumeState(Ljava/lang/String;)Ljava/lang/String;
+Landroid/os/storage/StorageVolume;->allowMassStorage()Z
+Landroid/os/storage/StorageVolume;->getMaxFileSize()J
 Landroid/os/storage/StorageVolume;->getPathFile()Ljava/io/File;
 Landroid/os/storage/StorageVolume;->getPath()Ljava/lang/String;
 Landroid/os/storage/StorageVolume;->getUserLabel()Ljava/lang/String;
@@ -713,6 +1302,9 @@
 Landroid/os/storage/VolumeInfo;->getType()I
 Landroid/os/storage/VolumeInfo;->isPrimary()Z
 Landroid/os/storage/VolumeInfo;->isVisible()Z
+Landroid/os/StrictMode;->disableDeathOnFileUriExposure()V
+Landroid/os/StrictMode;->getThreadPolicyMask()I
+Landroid/os/StrictMode;->onBinderStrictModePolicyChange(I)V
 Landroid/os/StrictMode;->violationsBeingTimed:Ljava/lang/ThreadLocal;
 Landroid/os/SystemProperties;->addChangeCallback(Ljava/lang/Runnable;)V
 Landroid/os/SystemProperties;->getBoolean(Ljava/lang/String;Z)Z
@@ -720,6 +1312,8 @@
 Landroid/os/SystemProperties;->get(Ljava/lang/String;)Ljava/lang/String;
 Landroid/os/SystemProperties;->get(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
 Landroid/os/SystemProperties;->getLong(Ljava/lang/String;J)J
+Landroid/os/SystemProperties;-><init>()V
+Landroid/os/SystemProperties;->native_get(Ljava/lang/String;)Ljava/lang/String;
 Landroid/os/SystemProperties;->PROP_NAME_MAX:I
 Landroid/os/SystemProperties;->set(Ljava/lang/String;Ljava/lang/String;)V
 Landroid/os/Trace;->asyncTraceBegin(JLjava/lang/String;I)V
@@ -744,16 +1338,19 @@
 Landroid/os/UpdateLock;->isHeld()Z
 Landroid/os/UpdateLock;->NOW_IS_CONVENIENT:Ljava/lang/String;
 Landroid/os/UpdateLock;->release()V
+Landroid/os/UpdateLock;->TIMESTAMP:Ljava/lang/String;
 Landroid/os/UpdateLock;->UPDATE_LOCK_CHANGED:Ljava/lang/String;
 Landroid/os/UserHandle;->ALL:Landroid/os/UserHandle;
 Landroid/os/UserHandle;->getAppIdFromSharedAppGid(I)I
 Landroid/os/UserHandle;->getCallingUserId()I
 Landroid/os/UserHandle;->getIdentifier()I
+Landroid/os/UserHandle;->getUid(II)I
 Landroid/os/UserHandle;->getUserId(I)I
 Landroid/os/UserHandle;-><init>(I)V
 Landroid/os/UserHandle;->isOwner()Z
 Landroid/os/UserHandle;->myUserId()I
 Landroid/os/UserHandle;->of(I)Landroid/os/UserHandle;
+Landroid/os/UserHandle;->PER_USER_RANGE:I
 Landroid/os/UserHandle;->USER_OWNER:I
 Landroid/os/UserManager;->getBadgedLabelForUser(Ljava/lang/CharSequence;Landroid/os/UserHandle;)Ljava/lang/CharSequence;
 Landroid/os/UserManager;->get(Landroid/content/Context;)Landroid/os/UserManager;
@@ -769,10 +1366,14 @@
 Landroid/os/UserManager;->isLinkedUser()Z
 Landroid/os/UserManager;->isManagedProfile()Z
 Landroid/os/UserManager;->isUserUnlocked(I)Z
+Landroid/os/VintfObject;->report()[Ljava/lang/String;
 Landroid/os/WorkSource;->add(ILjava/lang/String;)Z
 Landroid/os/WorkSource;->add(I)Z
 Landroid/os/WorkSource;->get(I)I
 Landroid/os/WorkSource;->getName(I)Ljava/lang/String;
+Landroid/os/WorkSource;->mNames:[Ljava/lang/String;
+Landroid/os/WorkSource;->mNum:I
+Landroid/os/WorkSource;->mUids:[I
 Landroid/os/WorkSource;->size()I
 Landroid/preference/DialogPreference;->mBuilder:Landroid/app/AlertDialog$Builder;
 Landroid/preference/DialogPreference;->mDialogIcon:Landroid/graphics/drawable/Drawable;
@@ -792,6 +1393,7 @@
 Landroid/preference/PreferenceManager;->getPreferenceScreen()Landroid/preference/PreferenceScreen;
 Landroid/preference/PreferenceManager;->inflateFromIntent(Landroid/content/Intent;Landroid/preference/PreferenceScreen;)Landroid/preference/PreferenceScreen;
 Landroid/preference/PreferenceManager;->inflateFromResource(Landroid/content/Context;ILandroid/preference/PreferenceScreen;)Landroid/preference/PreferenceScreen;
+Landroid/preference/PreferenceManager;-><init>(Landroid/app/Activity;I)V
 Landroid/preference/PreferenceManager;->mActivityDestroyListeners:Ljava/util/List;
 Landroid/preference/PreferenceManager;->mOnPreferenceTreeClickListener:Landroid/preference/PreferenceManager$OnPreferenceTreeClickListener;
 Landroid/preference/PreferenceManager;->mSharedPreferences:Landroid/content/SharedPreferences;
@@ -808,20 +1410,34 @@
 Landroid/print/PrinterId;->getServiceName()Landroid/content/ComponentName;
 Landroid/print/PrintJobInfo;->getAdvancedOptions()Landroid/os/Bundle;
 Landroid/print/PrintJobInfo;->getDocumentInfo()Landroid/print/PrintDocumentInfo;
+Landroid/provider/Browser;->BOOKMARKS_URI:Landroid/net/Uri;
 Landroid/provider/Browser;->canClearHistory(Landroid/content/ContentResolver;)Z
 Landroid/provider/Browser;->clearHistory(Landroid/content/ContentResolver;)V
 Landroid/provider/Browser;->clearSearches(Landroid/content/ContentResolver;)V
 Landroid/provider/Browser;->deleteFromHistory(Landroid/content/ContentResolver;Ljava/lang/String;)V
 Landroid/provider/Browser;->getVisitedHistory(Landroid/content/ContentResolver;)[Ljava/lang/String;
 Landroid/provider/Browser;->sendString(Landroid/content/Context;Ljava/lang/String;Ljava/lang/String;)V
+Landroid/provider/Settings$ContentProviderHolder;->mContentProvider:Landroid/content/IContentProvider;
+Landroid/provider/Settings$Global;->ENABLE_ACCESSIBILITY_GLOBAL_GESTURE_ENABLED:Ljava/lang/String;
 Landroid/provider/Settings$Global;->OTA_DISABLE_AUTOMATIC_UPDATE:Ljava/lang/String;
 Landroid/provider/Settings$Global;->PACKAGE_VERIFIER_ENABLE:Ljava/lang/String;
+Landroid/provider/Settings$Global;->sNameValueCache:Landroid/provider/Settings$NameValueCache;
+Landroid/provider/Settings$NameValueCache;->mProviderHolder:Landroid/provider/Settings$ContentProviderHolder;
+Landroid/provider/Settings$Secure;->ACCESSIBILITY_AUTOCLICK_ENABLED:Ljava/lang/String;
+Landroid/provider/Settings$Secure;->ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED:Ljava/lang/String;
 Landroid/provider/Settings$Secure;->ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED:Ljava/lang/String;
+Landroid/provider/Settings$Secure;->ACCESSIBILITY_LARGE_POINTER_ICON:Ljava/lang/String;
+Landroid/provider/Settings$Secure;->INCALL_POWER_BUTTON_BEHAVIOR:Ljava/lang/String;
+Landroid/provider/Settings$Secure;->LONG_PRESS_TIMEOUT:Ljava/lang/String;
 Landroid/provider/Settings$Secure;->PACKAGE_VERIFIER_USER_CONSENT:Ljava/lang/String;
+Landroid/provider/Settings$Secure;->sNameValueCache:Landroid/provider/Settings$NameValueCache;
 Landroid/provider/Settings$Secure;->USER_SETUP_COMPLETE:Ljava/lang/String;
 Landroid/provider/Settings$System;->AIRPLANE_MODE_TOGGLEABLE_RADIOS:Ljava/lang/String;
 Landroid/provider/Settings$System;->getStringForUser(Landroid/content/ContentResolver;Ljava/lang/String;I)Ljava/lang/String;
+Landroid/provider/Settings$System;->HEARING_AID:Ljava/lang/String;
+Landroid/provider/Settings$System;->MASTER_MONO:Ljava/lang/String;
 Landroid/provider/Settings$System;->putStringForUser(Landroid/content/ContentResolver;Ljava/lang/String;Ljava/lang/String;I)Z
+Landroid/provider/Settings$System;->sNameValueCache:Landroid/provider/Settings$NameValueCache;
 Landroid/provider/Telephony$Sms;->addMessageToUri(ILandroid/content/ContentResolver;Landroid/net/Uri;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Long;ZZJ)Landroid/net/Uri;
 Landroid/provider/Telephony$Sms;->addMessageToUri(ILandroid/content/ContentResolver;Landroid/net/Uri;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Long;ZZ)Landroid/net/Uri;
 Landroid/provider/Telephony$Sms;->addMessageToUri(Landroid/content/ContentResolver;Landroid/net/Uri;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Long;ZZJ)Landroid/net/Uri;
@@ -830,6 +1446,7 @@
 Landroid/provider/Telephony$Sms$Inbox;->addMessage(Landroid/content/ContentResolver;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Long;Z)Landroid/net/Uri;
 Landroid/provider/Telephony$Sms$Sent;->addMessage(ILandroid/content/ContentResolver;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Long;)Landroid/net/Uri;
 Landroid/provider/Telephony$Sms$Sent;->addMessage(Landroid/content/ContentResolver;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Long;)Landroid/net/Uri;
+Landroid/renderscript/RenderScriptCacheDir;->mCacheDir:Ljava/io/File;
 Landroid/renderscript/RenderScript;->create(Landroid/content/Context;I)Landroid/renderscript/RenderScript;
 Landroid/renderscript/RenderScript;->create(Landroid/content/Context;ILandroid/renderscript/RenderScript$ContextType;I)Landroid/renderscript/RenderScript;
 Landroid/renderscript/RenderScript;->getMinorID()J
@@ -837,14 +1454,17 @@
 Landroid/R$styleable;->TextAppearance_textColor:I
 Landroid/R$styleable;->TextAppearance_textSize:I
 Landroid/security/KeyStore;->getInstance()Landroid/security/KeyStore;
+Landroid/security/net/config/RootTrustManager;->checkServerTrusted([Ljava/security/cert/X509Certificate;Ljava/lang/String;Ljava/lang/String;)Ljava/util/List;
 Landroid/service/media/IMediaBrowserServiceCallbacks;->onConnectFailed()V
 Landroid/service/media/IMediaBrowserServiceCallbacks;->onConnect(Ljava/lang/String;Landroid/media/session/MediaSession$Token;Landroid/os/Bundle;)V
 Landroid/service/media/IMediaBrowserServiceCallbacks;->onLoadChildren(Ljava/lang/String;Landroid/content/pm/ParceledListSlice;)V
 Landroid/service/media/IMediaBrowserServiceCallbacks;->onLoadChildrenWithOptions(Ljava/lang/String;Landroid/content/pm/ParceledListSlice;Landroid/os/Bundle;)V
+Landroid/service/media/IMediaBrowserServiceCallbacks$Stub;->asInterface(Landroid/os/IBinder;)Landroid/service/media/IMediaBrowserServiceCallbacks;
 Landroid/service/media/MediaBrowserService;->KEY_MEDIA_ITEM:Ljava/lang/String;
 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/persistentdata/PersistentDataBlockManager;->getFlashLockState()I
 Landroid/service/persistentdata/PersistentDataBlockManager;->getMaximumDataBlockSize()J
 Landroid/service/persistentdata/PersistentDataBlockManager;->read()[B
 Landroid/service/persistentdata/PersistentDataBlockManager;->write([B)I
@@ -859,6 +1479,8 @@
 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;
+Landroid/system/Int32Ref;->value:I
+Landroid/system/StructTimeval;->fromMillis(J)Landroid/system/StructTimeval;
 Landroid/telecom/AudioState;->getRoute()I
 Landroid/telecom/AudioState;->getSupportedRouteMask()I
 Landroid/telecom/AudioState;->isMuted()Z
@@ -875,16 +1497,32 @@
 Landroid/telecom/Phone;->setMuted(Z)V
 Landroid/telecom/TelecomManager;->endCall()Z
 Landroid/telecom/TelecomManager;->EXTRA_IS_HANDOVER:Ljava/lang/String;
+Landroid/telecom/TelecomManager;->getUserSelectedOutgoingPhoneAccount()Landroid/telecom/PhoneAccountHandle;
+Landroid/telecom/TelecomManager;->setUserSelectedOutgoingPhoneAccount(Landroid/telecom/PhoneAccountHandle;)V
+Landroid/telephony/CellSignalStrengthLte;->mCqi:I
+Landroid/telephony/CellSignalStrengthLte;->mRsrp:I
+Landroid/telephony/CellSignalStrengthLte;->mRsrq:I
+Landroid/telephony/CellSignalStrengthLte;->mRssnr:I
 Landroid/telephony/PhoneStateListener;->mSubId:Ljava/lang/Integer;
 Landroid/telephony/ServiceState;->newFromBundle(Landroid/os/Bundle;)Landroid/telephony/ServiceState;
+Landroid/telephony/SignalStrength;->getAsuLevel()I
 Landroid/telephony/SignalStrength;->getCdmaLevel()I
+Landroid/telephony/SignalStrength;->getDbm()I
 Landroid/telephony/SignalStrength;->getLteDbm()I
 Landroid/telephony/SignalStrength;->getLteRsrp()I
+Landroid/telephony/SignalStrength;->getLteRsrq()I
 Landroid/telephony/SignalStrength;->getLteRssnr()I
 Landroid/telephony/SignalStrength;->getLteSignalStrength()I
+Landroid/telephony/SignalStrength;->SIGNAL_STRENGTH_GOOD:I
+Landroid/telephony/SignalStrength;->SIGNAL_STRENGTH_GREAT:I
+Landroid/telephony/SignalStrength;->SIGNAL_STRENGTH_MODERATE:I
+Landroid/telephony/SignalStrength;->SIGNAL_STRENGTH_NONE_OR_UNKNOWN:I
+Landroid/telephony/SignalStrength;->SIGNAL_STRENGTH_POOR:I
 Landroid/telephony/SmsManager;->RESULT_ERROR_FDN_CHECK_FAILURE:I
 Landroid/telephony/SmsMessage;->getSubId()I
 Landroid/telephony/SmsMessage;->mWrappedSmsMessage:Lcom/android/internal/telephony/SmsMessageBase;
+Landroid/telephony/SubscriptionManager;->getAllSubscriptionInfoCount()I
+Landroid/telephony/SubscriptionManager;->getDefaultDataSubscriptionInfo()Landroid/telephony/SubscriptionInfo;
 Landroid/telephony/SubscriptionManager;->getDefaultSmsPhoneId()I
 Landroid/telephony/SubscriptionManager;->getPhoneId(I)I
 Landroid/telephony/SubscriptionManager;->getSlotIndex(I)I
@@ -892,26 +1530,43 @@
 Landroid/telephony/SubscriptionManager;->setDefaultSmsSubId(I)V
 Landroid/telephony/TelephonyManager;->checkCarrierPrivilegesForPackage(Ljava/lang/String;)I
 Landroid/telephony/TelephonyManager;->from(Landroid/content/Context;)Landroid/telephony/TelephonyManager;
+Landroid/telephony/TelephonyManager;->getCallState(I)I
 Landroid/telephony/TelephonyManager;->getCarrierPackageNamesForIntent(Landroid/content/Intent;)Ljava/util/List;
 Landroid/telephony/TelephonyManager;->getCurrentPhoneType()I
 Landroid/telephony/TelephonyManager;->getCurrentPhoneType(I)I
 Landroid/telephony/TelephonyManager;->getDataEnabled(I)Z
 Landroid/telephony/TelephonyManager;->getDataEnabled()Z
+Landroid/telephony/TelephonyManager;->getDataNetworkType(I)I
 Landroid/telephony/TelephonyManager;->getDefault()Landroid/telephony/TelephonyManager;
+Landroid/telephony/TelephonyManager;->getGroupIdLevel1(I)Ljava/lang/String;
 Landroid/telephony/TelephonyManager;->getITelephony()Lcom/android/internal/telephony/ITelephony;
 Landroid/telephony/TelephonyManager;->getLine1Number(I)Ljava/lang/String;
+Landroid/telephony/TelephonyManager;->getMultiSimConfiguration()Landroid/telephony/TelephonyManager$MultiSimVariants;
 Landroid/telephony/TelephonyManager;->getNetworkClass(I)I
 Landroid/telephony/TelephonyManager;->getNetworkCountryIso(I)Ljava/lang/String;
+Landroid/telephony/TelephonyManager;->getNetworkOperatorForPhone(I)Ljava/lang/String;
 Landroid/telephony/TelephonyManager;->getNetworkOperator(I)Ljava/lang/String;
 Landroid/telephony/TelephonyManager;->getNetworkOperatorName(I)Ljava/lang/String;
 Landroid/telephony/TelephonyManager;->getNetworkType(I)I
+Landroid/telephony/TelephonyManager;->getNetworkTypeName(I)Ljava/lang/String;
+Landroid/telephony/TelephonyManager;->getPhoneType(I)I
+Landroid/telephony/TelephonyManager;->getSimCount()I
 Landroid/telephony/TelephonyManager;->getSimOperator(I)Ljava/lang/String;
+Landroid/telephony/TelephonyManager;->getSimOperatorNameForPhone(I)Ljava/lang/String;
 Landroid/telephony/TelephonyManager;->getSimOperatorName(I)Ljava/lang/String;
+Landroid/telephony/TelephonyManager;->getSimOperatorNumericForPhone(I)Ljava/lang/String;
 Landroid/telephony/TelephonyManager;->getSimSerialNumber(I)Ljava/lang/String;
+Landroid/telephony/TelephonyManager;->getSubIdForPhoneAccount(Landroid/telecom/PhoneAccount;)I
 Landroid/telephony/TelephonyManager;->getSubscriberId(I)Ljava/lang/String;
+Landroid/telephony/TelephonyManager;->getSubscriberInfo()Lcom/android/internal/telephony/IPhoneSubInfo;
+Landroid/telephony/TelephonyManager;->hasIccCard(I)Z
+Landroid/telephony/TelephonyManager;-><init>(Landroid/content/Context;)V
+Landroid/telephony/TelephonyManager;-><init>()V
 Landroid/telephony/TelephonyManager;->isMultiSimEnabled()Z
+Landroid/telephony/TelephonyManager;->isNetworkRoaming(I)Z
 Landroid/telephony/TelephonyManager;->setDataEnabled(IZ)V
 Landroid/text/AndroidBidi;->bidi(I[C[B)I
+Landroid/text/DynamicLayout;-><init>(Ljava/lang/CharSequence;Ljava/lang/CharSequence;Landroid/text/TextPaint;ILandroid/text/Layout$Alignment;Landroid/text/TextDirectionHeuristic;FFZIIILandroid/text/TextUtils$TruncateAt;I)V
 Landroid/text/DynamicLayout;->sStaticLayout:Landroid/text/StaticLayout;
 Landroid/text/Html;->withinStyle(Ljava/lang/StringBuilder;Ljava/lang/CharSequence;II)V
 Landroid/text/Layout;->DIRS_ALL_LEFT_TO_RIGHT:Landroid/text/Layout$Directions;
@@ -953,63 +1608,159 @@
 Landroid/text/SpannableStringInternal;->setSpan(Ljava/lang/Object;III)V
 Landroid/text/SpannableStringInternal;->setSpan(Ljava/lang/Object;IIIZ)V
 Landroid/text/SpannableStringInternal;->START:I
+Landroid/text/StaticLayout;-><init>(Ljava/lang/CharSequence;IILandroid/text/TextPaint;ILandroid/text/Layout$Alignment;Landroid/text/TextDirectionHeuristic;FFZLandroid/text/TextUtils$TruncateAt;II)V
+Landroid/text/StaticLayout$LineBreaks;->ascents:[F
+Landroid/text/StaticLayout$LineBreaks;->breaks:[I
+Landroid/text/StaticLayout$LineBreaks;->descents:[F
+Landroid/text/StaticLayout$LineBreaks;->flags:[I
+Landroid/text/StaticLayout$LineBreaks;->widths:[F
 Landroid/text/StaticLayout;->mColumns:I
 Landroid/text/StaticLayout;->mLineCount:I
 Landroid/text/StaticLayout;->mLines:[I
 Landroid/text/TextLine;->obtain()Landroid/text/TextLine;
 Landroid/text/TextLine;->sCached:[Landroid/text/TextLine;
 Landroid/text/TextPaint;->setUnderlineText(IF)V
+Landroid/transition/ChangeBounds;->BOTTOM_RIGHT_ONLY_PROPERTY:Landroid/util/Property;
+Landroid/transition/ChangeBounds;->POSITION_PROPERTY:Landroid/util/Property;
+Landroid/util/ArrayMap;->mBaseCacheSize:I
+Landroid/util/ArrayMap;->mTwiceBaseCacheSize:I
+Landroid/util/DisplayMetrics;->noncompatHeightPixels:I
+Landroid/util/DisplayMetrics;->noncompatWidthPixels:I
+Landroid/util/EventLog$Event;-><init>([B)V
 Landroid/util/Log;->wtf(ILjava/lang/String;Ljava/lang/String;Ljava/lang/Throwable;ZZ)I
 Landroid/util/Pools$SynchronizedPool;->acquire()Ljava/lang/Object;
+Landroid/util/Rational;->readObject(Ljava/io/ObjectInputStream;)V
+Landroid/util/Singleton;->mInstance:Ljava/lang/Object;
 Landroid/view/accessibility/AccessibilityManager;->getInstance(Landroid/content/Context;)Landroid/view/accessibility/AccessibilityManager;
 Landroid/view/accessibility/AccessibilityManager;->isHighTextContrastEnabled()Z
+Landroid/view/accessibility/AccessibilityManager;->mIsHighTextContrastEnabled:Z
 Landroid/view/accessibility/AccessibilityManager;->sInstance:Landroid/view/accessibility/AccessibilityManager;
 Landroid/view/accessibility/AccessibilityManager;->sInstanceSync:Ljava/lang/Object;
 Landroid/view/accessibility/AccessibilityNodeInfo;->refresh(Landroid/os/Bundle;Z)Z
+Landroid/view/accessibility/IAccessibilityManager;->getEnabledAccessibilityServiceList(II)Ljava/util/List;
+Landroid/view/accessibility/IAccessibilityManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/view/accessibility/IAccessibilityManager;
+Landroid/view/accessibility/IAccessibilityManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/view/ActionMode;->isUiFocusable()Z
 Landroid/view/animation/Animation;->mListener:Landroid/view/animation/Animation$AnimationListener;
 Landroid/view/Choreographer;->doFrame(JI)V
 Landroid/view/Choreographer;->getFrameTime()J
 Landroid/view/Choreographer;->mCallbackQueues:[Landroid/view/Choreographer$CallbackQueue;
+Landroid/view/Choreographer;->mLastFrameTimeNanos:J
 Landroid/view/Choreographer;->postCallback(ILjava/lang/Runnable;Ljava/lang/Object;)V
 Landroid/view/Choreographer;->removeCallbacks(ILjava/lang/Runnable;Ljava/lang/Object;)V
 Landroid/view/Choreographer;->scheduleVsyncLocked()V
+Landroid/view/Choreographer;->USE_VSYNC:Z
 Landroid/view/ContextThemeWrapper;->mResources:Landroid/content/res/Resources;
 Landroid/view/ContextThemeWrapper;->mTheme:Landroid/content/res/Resources$Theme;
 Landroid/view/ContextThemeWrapper;->mThemeResource:I
+Landroid/view/DisplayEventReceiver;->dispatchHotplug(JIZ)V
+Landroid/view/DisplayEventReceiver;->dispatchVsync(JII)V
+Landroid/view/Display$HdrCapabilities;-><init>([IFFF)V
+Landroid/view/DisplayListCanvas;->callDrawGLFunction2(J)V
+Landroid/view/DisplayListCanvas;->drawGLFunctor2(JLjava/lang/Runnable;)V
+Landroid/view/FrameMetrics;->mTimingData:[J
+Landroid/view/FrameMetricsObserver;->mFrameMetrics:Landroid/view/FrameMetrics;
+Landroid/view/FrameMetricsObserver;->mMessageQueue:Landroid/os/MessageQueue;
+Landroid/view/FrameMetricsObserver;->notifyDataAvailable(I)V
+Landroid/view/GestureDetector;->mMinimumFlingVelocity:I
+Landroid/view/GestureDetector;->mTouchSlopSquare:I
+Landroid/view/GhostView;->addGhost(Landroid/view/View;Landroid/view/ViewGroup;Landroid/graphics/Matrix;)Landroid/view/GhostView;
+Landroid/view/GhostView;->removeGhost(Landroid/view/View;)V
+Landroid/view/IGraphicsStats$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
+Landroid/view/InputChannel;-><init>()V
+Landroid/view/InputChannel;->mPtr:J
+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/InputEventReceiver;->dispatchBatchedInputEventPending()V
+Landroid/view/InputEventReceiver;->dispatchInputEvent(ILandroid/view/InputEvent;I)V
+Landroid/view/InputEventSender;->dispatchInputEventFinished(IZ)V
 Landroid/view/inputmethod/InputMethodManager;->finishInputLocked()V
 Landroid/view/inputmethod/InputMethodManager;->focusIn(Landroid/view/View;)V
 Landroid/view/inputmethod/InputMethodManager;->getInputMethodWindowVisibleHeight()I
 Landroid/view/inputmethod/InputMethodManager;->mCurId:Ljava/lang/String;
 Landroid/view/inputmethod/InputMethodManager;->mCurRootView:Landroid/view/View;
+Landroid/view/inputmethod/InputMethodManager;->mH:Landroid/view/inputmethod/InputMethodManager$H;
 Landroid/view/inputmethod/InputMethodManager;->mNextServedView:Landroid/view/View;
 Landroid/view/inputmethod/InputMethodManager;->mServedView:Landroid/view/View;
+Landroid/view/inputmethod/InputMethodManager;->mService:Lcom/android/internal/view/IInputMethodManager;
 Landroid/view/inputmethod/InputMethodManager;->notifyUserAction()V
 Landroid/view/inputmethod/InputMethodManager;->showSoftInputUnchecked(ILandroid/os/ResultReceiver;)V
+Landroid/view/inputmethod/InputMethodManager;->sInstance:Landroid/view/inputmethod/InputMethodManager;
 Landroid/view/inputmethod/InputMethodManager;->windowDismissed(Landroid/os/IBinder;)V
+Landroid/view/InputQueue;->finishInputEvent(JZ)V
 Landroid/view/IWindowManager;->getAnimationScale(I)F
 Landroid/view/IWindowManager;->hasNavigationBar()Z
 Landroid/view/IWindowManager;->setAnimationScale(IF)V
 Landroid/view/IWindowManager;->setStrictModeVisualIndicatorPreference(Ljava/lang/String;)V
 Landroid/view/IWindowManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/view/IWindowManager;
+Landroid/view/IWindowManager$Stub$Proxy;->getBaseDisplayDensity(I)I
+Landroid/view/IWindowManager$Stub$Proxy;->getInitialDisplayDensity(I)I
+Landroid/view/IWindowManager$Stub$Proxy;->hasNavigationBar()Z
+Landroid/view/IWindowManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/view/IWindowSession$Stub$Proxy;->relayout(Landroid/view/IWindow;ILandroid/view/WindowManager$LayoutParams;IIIILandroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/view/DisplayCutout$ParcelableWrapper;Landroid/util/MergedConfiguration;Landroid/view/Surface;)I
+Landroid/view/KeyCharacterMap$FallbackAction;->keyCode:I
+Landroid/view/KeyCharacterMap$FallbackAction;->metaState:I
+Landroid/view/KeyCharacterMap;-><init>(J)V
+Landroid/view/KeyEvent;->mAction:I
+Landroid/view/KeyEvent;->mCharacters:Ljava/lang/String;
+Landroid/view/KeyEvent;->mDeviceId:I
+Landroid/view/KeyEvent;->mDownTime:J
+Landroid/view/KeyEvent;->mEventTime:J
+Landroid/view/KeyEvent;->mFlags:I
+Landroid/view/KeyEvent;->mKeyCode:I
+Landroid/view/KeyEvent;->mMetaState:I
+Landroid/view/KeyEvent;->mRepeatCount:I
+Landroid/view/KeyEvent;->mScanCode:I
+Landroid/view/KeyEvent;->mSource:I
+Landroid/view/KeyEvent;->obtain(JJIIIIIIIILjava/lang/String;)Landroid/view/KeyEvent;
+Landroid/view/KeyEvent;->recycle()V
 Landroid/view/LayoutInflater;->createViewFromTag(Landroid/view/View;Ljava/lang/String;Landroid/content/Context;Landroid/util/AttributeSet;)Landroid/view/View;
 Landroid/view/LayoutInflater;->createViewFromTag(Landroid/view/View;Ljava/lang/String;Landroid/content/Context;Landroid/util/AttributeSet;Z)Landroid/view/View;
 Landroid/view/LayoutInflater;->mConstructorArgs:[Ljava/lang/Object;
+Landroid/view/LayoutInflater;->mContext:Landroid/content/Context;
 Landroid/view/LayoutInflater;->mFactory2:Landroid/view/LayoutInflater$Factory2;
 Landroid/view/LayoutInflater;->mFactory:Landroid/view/LayoutInflater$Factory;
 Landroid/view/LayoutInflater;->mFactorySet:Z
+Landroid/view/LayoutInflater;->mPrivateFactory:Landroid/view/LayoutInflater$Factory2;
 Landroid/view/LayoutInflater;->sConstructorMap:Ljava/util/HashMap;
+Landroid/view/LayoutInflater;->setPrivateFactory(Landroid/view/LayoutInflater$Factory2;)V
 Landroid/view/MotionEvent;->HISTORY_CURRENT:I
 Landroid/view/MotionEvent;->mNativePtr:J
 Landroid/view/MotionEvent;->nativeGetRawAxisValue(JIII)F
+Landroid/view/MotionEvent;->obtain()Landroid/view/MotionEvent;
+Landroid/view/MotionEvent$PointerCoords;->mPackedAxisBits:J
+Landroid/view/MotionEvent$PointerCoords;->mPackedAxisValues:[F
 Landroid/view/MotionEvent;->scale(F)V
+Landroid/view/PointerIcon;->load(Landroid/content/Context;)Landroid/view/PointerIcon;
+Landroid/view/PointerIcon;->mBitmapFrames:[Landroid/graphics/Bitmap;
+Landroid/view/PointerIcon;->mBitmap:Landroid/graphics/Bitmap;
+Landroid/view/PointerIcon;->mDurationPerFrame:I
+Landroid/view/PointerIcon;->mHotSpotX:F
+Landroid/view/PointerIcon;->mHotSpotY:F
+Landroid/view/PointerIcon;->mType:I
+Landroid/view/RenderNodeAnimator;->callOnFinished(Landroid/view/RenderNodeAnimator;)V
 Landroid/view/ScaleGestureDetector;->mListener:Landroid/view/ScaleGestureDetector$OnScaleGestureListener;
+Landroid/view/SurfaceControl$PhysicalDisplayInfo;->appVsyncOffsetNanos:J
+Landroid/view/SurfaceControl$PhysicalDisplayInfo;->density:F
+Landroid/view/SurfaceControl$PhysicalDisplayInfo;->height:I
+Landroid/view/SurfaceControl$PhysicalDisplayInfo;-><init>()V
+Landroid/view/SurfaceControl$PhysicalDisplayInfo;->presentationDeadlineNanos:J
+Landroid/view/SurfaceControl$PhysicalDisplayInfo;->refreshRate:F
+Landroid/view/SurfaceControl$PhysicalDisplayInfo;->secure:Z
+Landroid/view/SurfaceControl$PhysicalDisplayInfo;->width:I
+Landroid/view/SurfaceControl$PhysicalDisplayInfo;->xDpi:F
+Landroid/view/SurfaceControl$PhysicalDisplayInfo;->yDpi:F
+Landroid/view/Surface;-><init>(J)V
+Landroid/view/Surface;->mLock:Ljava/lang/Object;
+Landroid/view/Surface;->mNativeObject:J
+Landroid/view/SurfaceSession;->mNativeClient:J
 Landroid/view/SurfaceView;->mCallbacks:Ljava/util/ArrayList;
 Landroid/view/SurfaceView;->mFormat:I
 Landroid/view/SurfaceView;->mRequestedFormat:I
 Landroid/view/SurfaceView;->mSurfaceHolder:Landroid/view/SurfaceHolder;
+Landroid/view/SurfaceView;->surfacePositionLost_uiRtSync(J)V
+Landroid/view/SurfaceView;->updateSurfacePosition_renderWorker(JIIII)V
 Landroid/view/textclassifier/logging/SmartSelectionEventTracker;-><init>(Landroid/content/Context;I)V
 Landroid/view/textclassifier/logging/SmartSelectionEventTracker;->logEvent(Landroid/view/textclassifier/logging/SmartSelectionEventTracker$SelectionEvent;)V
 Landroid/view/textclassifier/logging/SmartSelectionEventTracker$SelectionEvent;->selectionAction(III)Landroid/view/textclassifier/logging/SmartSelectionEventTracker$SelectionEvent;
@@ -1020,10 +1771,18 @@
 Landroid/view/textclassifier/logging/SmartSelectionEventTracker$SelectionEvent;->selectionStarted(I)Landroid/view/textclassifier/logging/SmartSelectionEventTracker$SelectionEvent;
 Landroid/view/textservice/TextServicesManager;->isSpellCheckerEnabled()Z
 Landroid/view/TextureView;->mLayer:Landroid/view/HardwareLayer;
+Landroid/view/TextureView;->mNativeWindow:J
 Landroid/view/TextureView;->mSurface:Landroid/graphics/SurfaceTexture;
 Landroid/view/TextureView;->mUpdateListener:Landroid/graphics/SurfaceTexture$OnFrameAvailableListener;
 Landroid/view/TouchDelegate;->mDelegateTargeted:Z
+Landroid/view/VelocityTracker$Estimator;->confidence:F
+Landroid/view/VelocityTracker$Estimator;->degree:I
+Landroid/view/VelocityTracker$Estimator;->xCoeff:[F
+Landroid/view/VelocityTracker$Estimator;->yCoeff:[F
 Landroid/view/VelocityTracker;->obtain(Ljava/lang/String;)Landroid/view/VelocityTracker;
+Landroid/view/View;->applyDrawableToTransparentRegion(Landroid/graphics/drawable/Drawable;Landroid/graphics/Region;)V
+Landroid/view/View$AttachInfo;->mDrawingTime:J
+Landroid/view/View$AttachInfo;->mStableInsets:Landroid/graphics/Rect;
 Landroid/view/View;->clearAccessibilityFocus()V
 Landroid/view/View;->computeFitSystemWindows(Landroid/graphics/Rect;Landroid/graphics/Rect;)Z
 Landroid/view/View;->computeOpaqueFlags()V
@@ -1036,28 +1795,37 @@
 Landroid/view/View;->dispatchAttachedToWindow(Landroid/view/View$AttachInfo;I)V
 Landroid/view/View;->dispatchDetachedFromWindow()V
 Landroid/view/View;->fitsSystemWindows()Z
+Landroid/view/View;->getAccessibilityDelegate()Landroid/view/View$AccessibilityDelegate;
 Landroid/view/View;->getListenerInfo()Landroid/view/View$ListenerInfo;
+Landroid/view/View;->getTransitionAlpha()F
 Landroid/view/View;->getViewRootImpl()Landroid/view/ViewRootImpl;
+Landroid/view/ViewGroup;->dispatchViewAdded(Landroid/view/View;)V
+Landroid/view/ViewGroup;->dispatchViewRemoved(Landroid/view/View;)V
 Landroid/view/ViewGroup;->FLAG_SUPPORT_STATIC_TRANSFORMATIONS:I
 Landroid/view/ViewGroup;->FLAG_USE_CHILD_DRAWING_ORDER:I
 Landroid/view/ViewGroup;->makeOptionalFitsSystemWindows()V
 Landroid/view/ViewGroup$MarginLayoutParams;->endMargin:I
 Landroid/view/ViewGroup$MarginLayoutParams;->startMargin:I
+Landroid/view/ViewGroup;->mChildrenCount:I
 Landroid/view/ViewGroup;->mChildren:[Landroid/view/View;
 Landroid/view/ViewGroup;->mFirstTouchTarget:Landroid/view/ViewGroup$TouchTarget;
 Landroid/view/ViewGroup;->mGroupFlags:I
 Landroid/view/ViewGroup;->mOnHierarchyChangeListener:Landroid/view/ViewGroup$OnHierarchyChangeListener;
+Landroid/view/ViewGroup;->suppressLayout(Z)V
 Landroid/view/View;->initializeScrollbars(Landroid/content/res/TypedArray;)V
+Landroid/view/View;->internalSetPadding(IIII)V
 Landroid/view/View;->isPaddingResolved()Z
 Landroid/view/View;->isVisibleToUser(Landroid/graphics/Rect;)Z
 Landroid/view/View;->isVisibleToUser()Z
 Landroid/view/View$ListenerInfo;->mOnClickListener:Landroid/view/View$OnClickListener;
+Landroid/view/View$ListenerInfo;->mOnLongClickListener:Landroid/view/View$OnLongClickListener;
 Landroid/view/View$ListenerInfo;->mOnTouchListener:Landroid/view/View$OnTouchListener;
 Landroid/view/View;->mAccessibilityDelegate:Landroid/view/View$AccessibilityDelegate;
 Landroid/view/View;->mAttachInfo:Landroid/view/View$AttachInfo;
 Landroid/view/View;->mBottom:I
 Landroid/view/View;->mContext:Landroid/content/Context;
 Landroid/view/View;->mDrawingCache:Landroid/graphics/Bitmap;
+Landroid/view/View;->mLayoutParams:Landroid/view/ViewGroup$LayoutParams;
 Landroid/view/View;->mLeft:I
 Landroid/view/View;->mListenerInfo:Landroid/view/View$ListenerInfo;
 Landroid/view/View;->mMinHeight:I
@@ -1073,8 +1841,10 @@
 Landroid/view/View;->mScrollX:I
 Landroid/view/View;->mScrollY:I
 Landroid/view/View;->mStartActivityRequestWho:Ljava/lang/String;
+Landroid/view/View;->mTag:Ljava/lang/Object;
 Landroid/view/View;->mTop:I
 Landroid/view/View;->mUnscaledDrawingCache:Landroid/graphics/Bitmap;
+Landroid/view/View;->mViewFlags:I
 Landroid/view/View;->notifySubtreeAccessibilityStateChangedIfNeeded()V
 Landroid/view/View;->recomputePadding()V
 Landroid/view/View;->requestAccessibilityFocus()Z
@@ -1082,9 +1852,15 @@
 Landroid/view/ViewRootImpl;->detachFunctor(J)V
 Landroid/view/ViewRootImpl;->invokeFunctor(JZ)V
 Landroid/view/ViewRootImpl;->mStopped:Z
+Landroid/view/ViewRootImpl;->mView:Landroid/view/View;
+Landroid/view/View$ScrollabilityCache;->scrollBar:Landroid/widget/ScrollBarDrawable;
+Landroid/view/View;->setAlphaNoInvalidation(F)Z
+Landroid/view/View;->setAnimationMatrix(Landroid/graphics/Matrix;)V
 Landroid/view/View;->setAssistBlocked(Z)V
 Landroid/view/View;->setFrame(IIII)Z
 Landroid/view/View;->setIsRootNamespace(Z)V
+Landroid/view/View;->setLeftTopRightBottom(IIII)V
+Landroid/view/View;->setTransitionAlpha(F)V
 Landroid/view/View;->startActivityForResult(Landroid/content/Intent;I)V
 Landroid/view/View;->STATUS_BAR_DISABLE_BACK:I
 Landroid/view/View;->STATUS_BAR_DISABLE_EXPAND:I
@@ -1092,43 +1868,117 @@
 Landroid/view/View;->STATUS_BAR_DISABLE_RECENT:I
 Landroid/view/View;->toGlobalMotionEvent(Landroid/view/MotionEvent;)Z
 Landroid/view/View;->toLocalMotionEvent(Landroid/view/MotionEvent;)Z
+Landroid/view/View;->transformMatrixToGlobal(Landroid/graphics/Matrix;)V
+Landroid/view/View;->transformMatrixToLocal(Landroid/graphics/Matrix;)V
 Landroid/view/ViewTreeObserver;->addOnComputeInternalInsetsListener(Landroid/view/ViewTreeObserver$OnComputeInternalInsetsListener;)V
 Landroid/view/ViewTreeObserver$InternalInsetsInfo;->setTouchableInsets(I)V
 Landroid/view/ViewTreeObserver$InternalInsetsInfo;->TOUCHABLE_INSETS_REGION:I
 Landroid/view/ViewTreeObserver$InternalInsetsInfo;->touchableRegion:Landroid/graphics/Region;
 Landroid/view/ViewTreeObserver;->removeOnComputeInternalInsetsListener(Landroid/view/ViewTreeObserver$OnComputeInternalInsetsListener;)V
+Landroid/view/WindowAnimationFrameStats;->init(J[J)V
+Landroid/view/WindowContentFrameStats;->init(J[J[J[J)V
 Landroid/view/WindowManagerGlobal;->getInstance()Landroid/view/WindowManagerGlobal;
 Landroid/view/WindowManagerGlobal;->getRootView(Ljava/lang/String;)Landroid/view/View;
 Landroid/view/WindowManagerGlobal;->getViewRootNames()[Ljava/lang/String;
 Landroid/view/WindowManagerGlobal;->getWindowManagerService()Landroid/view/IWindowManager;
 Landroid/view/WindowManagerGlobal;->mLock:Ljava/lang/Object;
+Landroid/view/WindowManagerGlobal;->mParams:Ljava/util/ArrayList;
+Landroid/view/WindowManagerGlobal;->mRoots:Ljava/util/ArrayList;
 Landroid/view/WindowManagerGlobal;->mViews:Ljava/util/ArrayList;
+Landroid/view/WindowManagerGlobal;->sDefaultWindowManager:Landroid/view/WindowManagerGlobal;
+Landroid/view/WindowManagerGlobal;->sWindowManagerService:Landroid/view/IWindowManager;
+Landroid/view/WindowManagerGlobal;->sWindowSession:Landroid/view/IWindowSession;
 Landroid/view/WindowManagerGlobal;->trimMemory(I)V
+Landroid/view/WindowManagerImpl;->mGlobal:Landroid/view/WindowManagerGlobal;
+Landroid/view/WindowManager$LayoutParams;->hideTimeoutMilliseconds:J
 Landroid/view/WindowManager$LayoutParams;->needsMenuKey:I
 Landroid/view/WindowManager$LayoutParams;->NEEDS_MENU_SET_TRUE:I
+Landroid/view/WindowManager$LayoutParams;->PRIVATE_FLAG_NO_MOVE_ANIMATION:I
 Landroid/view/WindowManager$LayoutParams;->privateFlags:I
 Landroid/view/WindowManager$LayoutParams;->userActivityTimeout:J
 Landroid/view/Window;->mAppName:Ljava/lang/String;
 Landroid/view/Window;->mAppToken:Landroid/os/IBinder;
 Landroid/view/Window;->mHardwareAccelerated:Z
+Landroid/webkit/FindActionModeCallback;->findAll()V
+Landroid/webkit/FindActionModeCallback;-><init>(Landroid/content/Context;)V
+Landroid/webkit/FindActionModeCallback;->setText(Ljava/lang/String;)V
+Landroid/webkit/FindActionModeCallback;->setWebView(Landroid/webkit/WebView;)V
+Landroid/webkit/FindActionModeCallback;->showSoftInput()V
+Landroid/webkit/GeolocationPermissions;-><init>()V
+Landroid/webkit/HttpAuthHandler;-><init>()V
+Landroid/webkit/IWebViewUpdateService$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
+Landroid/webkit/JsDialogHelper;-><init>(Landroid/webkit/JsPromptResult;ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
+Landroid/webkit/JsDialogHelper;->showDialog(Landroid/content/Context;)V
+Landroid/webkit/JsPromptResult;->getStringResult()Ljava/lang/String;
+Landroid/webkit/JsPromptResult;-><init>(Landroid/webkit/JsResult$ResultReceiver;)V
+Landroid/webkit/SslErrorHandler;-><init>()V
+Landroid/webkit/TokenBindingService;-><init>()V
+Landroid/webkit/TokenBindingService$TokenBindingKey;-><init>()V
+Landroid/webkit/WebChromeClient;->openFileChooser(Landroid/webkit/ValueCallback;Ljava/lang/String;Ljava/lang/String;)V
+Landroid/webkit/WebMessagePort;-><init>()V
+Landroid/webkit/WebResourceError;-><init>()V
+Landroid/webkit/WebResourceResponse;-><init>(ZLjava/lang/String;Ljava/lang/String;ILjava/lang/String;Ljava/util/Map;Ljava/io/InputStream;)V
+Landroid/webkit/WebResourceResponse;->mImmutable:Z
+Landroid/webkit/WebSettings;->getAcceptThirdPartyCookies()Z
+Landroid/webkit/WebSettings;->setAcceptThirdPartyCookies(Z)V
 Landroid/webkit/WebSettings;->setNavDump(Z)V
 Landroid/webkit/WebSettings;->setPluginsEnabled(Z)V
+Landroid/webkit/WebStorage;-><init>()V
+Landroid/webkit/WebStorage$Origin;-><init>(Ljava/lang/String;JJ)V
+Landroid/webkit/WebSyncManager;->mHandler:Landroid/os/Handler;
 Landroid/webkit/WebView;->debugDump()V
+Landroid/webkit/WebViewDelegate;->addWebViewAssetPath(Landroid/content/Context;)V
+Landroid/webkit/WebViewDelegate;->callDrawGlFunction(Landroid/graphics/Canvas;JLjava/lang/Runnable;)V
+Landroid/webkit/WebViewDelegate;->callDrawGlFunction(Landroid/graphics/Canvas;J)V
+Landroid/webkit/WebViewDelegate;->canInvokeDrawGlFunctor(Landroid/view/View;)Z
+Landroid/webkit/WebViewDelegate;->detachDrawGlFunctor(Landroid/view/View;J)V
+Landroid/webkit/WebViewDelegate;->getApplication()Landroid/app/Application;
+Landroid/webkit/WebViewDelegate;->getDataDirectorySuffix()Ljava/lang/String;
+Landroid/webkit/WebViewDelegate;->getErrorString(Landroid/content/Context;I)Ljava/lang/String;
+Landroid/webkit/WebViewDelegate;->getPackageId(Landroid/content/res/Resources;Ljava/lang/String;)I
+Landroid/webkit/WebViewDelegate;->invokeDrawGlFunctor(Landroid/view/View;JZ)V
+Landroid/webkit/WebViewDelegate;->isMultiProcessEnabled()Z
+Landroid/webkit/WebViewDelegate;->isTraceTagEnabled()Z
+Landroid/webkit/WebViewDelegate;->setOnTraceEnabledChangeListener(Landroid/webkit/WebViewDelegate$OnTraceEnabledChangeListener;)V
 Landroid/webkit/WebView;->disablePlatformNotifications()V
 Landroid/webkit/WebView;->emulateShiftHeld()V
 Landroid/webkit/WebView;->enablePlatformNotifications()V
 Landroid/webkit/WebViewFactory;->getLoadedPackageInfo()Landroid/content/pm/PackageInfo;
 Landroid/webkit/WebViewFactory;->getProvider()Landroid/webkit/WebViewFactoryProvider;
+Landroid/webkit/WebViewFactory;->getWebViewContextAndSetProvider()Landroid/content/Context;
+Landroid/webkit/WebViewFactory;->loadWebViewNativeLibraryFromPackage(Ljava/lang/String;Ljava/lang/ClassLoader;)I
+Landroid/webkit/WebViewFactoryProvider;->getStatics()Landroid/webkit/WebViewFactoryProvider$Statics;
+Landroid/webkit/WebViewFactoryProvider$Statics;->getDefaultUserAgent(Landroid/content/Context;)Ljava/lang/String;
 Landroid/webkit/WebViewFactory;->sPackageInfo:Landroid/content/pm/PackageInfo;
+Landroid/webkit/WebViewFactory;->sProviderInstance:Landroid/webkit/WebViewFactoryProvider;
 Landroid/webkit/WebView;->getVisibleTitleHeight()I
 Landroid/webkit/WebView;->getWebViewProvider()Landroid/webkit/WebViewProvider;
+Landroid/webkit/WebView$HitTestResult;-><init>()V
+Landroid/webkit/WebView$HitTestResult;->setExtra(Ljava/lang/String;)V
+Landroid/webkit/WebView$HitTestResult;->setType(I)V
 Landroid/webkit/WebView;->isPaused()Z
 Landroid/webkit/WebView;->mProvider:Landroid/webkit/WebViewProvider;
 Landroid/webkit/WebView;->notifyFindDialogDismissed()V
+Landroid/webkit/WebView$PrivateAccess;->overScrollBy(IIIIIIIIZ)V
+Landroid/webkit/WebView$PrivateAccess;->setMeasuredDimension(II)V
+Landroid/webkit/WebView$PrivateAccess;->super_dispatchKeyEvent(Landroid/view/KeyEvent;)Z
+Landroid/webkit/WebView$PrivateAccess;->super_getScrollBarStyle()I
+Landroid/webkit/WebView$PrivateAccess;->super_onDrawVerticalScrollBar(Landroid/graphics/Canvas;Landroid/graphics/drawable/Drawable;IIII)V
+Landroid/webkit/WebView$PrivateAccess;->super_onGenericMotionEvent(Landroid/view/MotionEvent;)Z
+Landroid/webkit/WebView$PrivateAccess;->super_performAccessibilityAction(ILandroid/os/Bundle;)Z
+Landroid/webkit/WebView$PrivateAccess;->super_performLongClick()Z
+Landroid/webkit/WebView$PrivateAccess;->super_requestFocus(ILandroid/graphics/Rect;)Z
+Landroid/webkit/WebView$PrivateAccess;->super_scrollTo(II)V
+Landroid/webkit/WebView$PrivateAccess;->super_setFrame(IIII)Z
+Landroid/webkit/WebView$PrivateAccess;->super_setLayoutParams(Landroid/view/ViewGroup$LayoutParams;)V
+Landroid/webkit/WebView$PrivateAccess;->super_startActivityForResult(Landroid/content/Intent;I)V
 Landroid/webkit/WebView;->restorePicture(Landroid/os/Bundle;Ljava/io/File;)Z
 Landroid/webkit/WebView;->savePicture(Landroid/os/Bundle;Ljava/io/File;)Z
 Landroid/webkit/WebView;->sEnforceThreadChecking:Z
+Landroid/webkit/WebViewUpdateService;->getCurrentWebViewPackageName()Ljava/lang/String;
 Landroid/widget/AbsListView$FlingRunnable;->endFling()V
+Landroid/widget/AbsListView$FlingRunnable;->mScroller:Landroid/widget/OverScroller;
+Landroid/widget/AbsListView$FlingRunnable;->start(I)V
 Landroid/widget/AbsListView;->invokeOnItemScrollListener()V
 Landroid/widget/AbsListView;->isVerticalScrollBarHidden()Z
 Landroid/widget/AbsListView;->mAdapter:Landroid/widget/ListAdapter;
@@ -1149,6 +1999,9 @@
 Landroid/widget/AbsListView;->mVelocityTracker:Landroid/view/VelocityTracker;
 Landroid/widget/AbsListView;->performLongPress(Landroid/view/View;IJFF)Z
 Landroid/widget/AbsListView;->performLongPress(Landroid/view/View;IJ)Z
+Landroid/widget/AbsListView$RecycleBin;->clear()V
+Landroid/widget/AbsListView$RecycleBin;->mRecyclerListener:Landroid/widget/AbsListView$RecyclerListener;
+Landroid/widget/AbsListView;->reportScrollStateChange(I)V
 Landroid/widget/AbsListView;->smoothScrollBy(IIZZ)V
 Landroid/widget/AbsListView;->trackMotionScroll(II)Z
 Landroid/widget/AbsSeekBar;->mIsDragging:Z
@@ -1157,6 +2010,7 @@
 Landroid/widget/AbsSeekBar;->mTouchProgressOffset:F
 Landroid/widget/ActivityChooserView;->setExpandActivityOverflowButtonDrawable(Landroid/graphics/drawable/Drawable;)V
 Landroid/widget/AdapterView;->mDataChanged:Z
+Landroid/widget/AdapterView;->mFirstPosition:I
 Landroid/widget/AdapterView;->setNextSelectedPositionInt(I)V
 Landroid/widget/AdapterView;->setSelectedPositionInt(I)V
 Landroid/widget/AutoCompleteTextView;->doAfterTextChanged()V
@@ -1171,23 +2025,41 @@
 Landroid/widget/ExpandableListView;->mChildDivider:Landroid/graphics/drawable/Drawable;
 Landroid/widget/FastScroller;->mThumbDrawable:Landroid/graphics/drawable/Drawable;
 Landroid/widget/FastScroller;->mTrackDrawable:Landroid/graphics/drawable/Drawable;
+Landroid/widget/Gallery;->fillToGalleryLeft()V
+Landroid/widget/Gallery;->fillToGalleryRight()V
+Landroid/widget/Gallery$FlingRunnable;->startUsingVelocity(I)V
+Landroid/widget/Gallery;->makeAndAddView(IIIZ)Landroid/view/View;
+Landroid/widget/Gallery;->mDownTouchPosition:I
 Landroid/widget/Gallery;->mDownTouchView:Landroid/view/View;
+Landroid/widget/Gallery;->mFlingRunnable:Landroid/widget/Gallery$FlingRunnable;
+Landroid/widget/Gallery;->moveDirection(I)Z
+Landroid/widget/Gallery;->mSpacing:I
+Landroid/widget/GridView;->fillDown(II)Landroid/view/View;
+Landroid/widget/GridView;->fillUp(II)Landroid/view/View;
 Landroid/widget/GridView;->mColumnWidth:I
 Landroid/widget/GridView;->mHorizontalSpacing:I
 Landroid/widget/GridView;->mNumColumns:I
 Landroid/widget/GridView;->mRequestedNumColumns:I
 Landroid/widget/GridView;->mVerticalSpacing:I
+Landroid/widget/HorizontalScrollView;->mChildToScrollTo:Landroid/view/View;
 Landroid/widget/HorizontalScrollView;->mEdgeGlowLeft:Landroid/widget/EdgeEffect;
 Landroid/widget/HorizontalScrollView;->mEdgeGlowRight:Landroid/widget/EdgeEffect;
 Landroid/widget/HorizontalScrollView;->mScroller:Landroid/widget/OverScroller;
 Landroid/widget/ImageView;->mAdjustViewBounds:Z
 Landroid/widget/ImageView;->mAlpha:I
+Landroid/widget/ImageView;->mDrawMatrix:Landroid/graphics/Matrix;
 Landroid/widget/ImageView;->mMaxHeight:I
 Landroid/widget/ImageView;->mMaxWidth:I
+Landroid/widget/ImageView;->mResource:I
+Landroid/widget/ImageView;->mUri:Landroid/net/Uri;
+Landroid/widget/ImageView;->updateDrawable(Landroid/graphics/drawable/Drawable;)V
 Landroid/widget/LinearLayout;->mGravity:I
 Landroid/widget/LinearLayout;->mUseLargestChild:Z
 Landroid/widget/ListPopupWindow;->mPopup:Landroid/widget/PopupWindow;
 Landroid/widget/ListPopupWindow;->setForceIgnoreOutsideTouch(Z)V
+Landroid/widget/ListView;->fillDown(II)Landroid/view/View;
+Landroid/widget/ListView;->fillSpecific(II)Landroid/view/View;
+Landroid/widget/ListView;->fillUp(II)Landroid/view/View;
 Landroid/widget/ListView;->mAreAllItemsSelectable:Z
 Landroid/widget/ListView;->setSelectionInt(I)V
 Landroid/widget/MediaController;->mAnchor:Landroid/view/View;
@@ -1197,6 +2069,8 @@
 Landroid/widget/NumberPicker;->mInputText:Landroid/widget/EditText;
 Landroid/widget/NumberPicker;->mSelectionDivider:Landroid/graphics/drawable/Drawable;
 Landroid/widget/NumberPicker;->mSelectorWheelPaint:Landroid/graphics/Paint;
+Landroid/widget/OverScroller;->mScrollerY:Landroid/widget/OverScroller$SplineOverScroller;
+Landroid/widget/OverScroller$SplineOverScroller;->mCurrVelocity:F
 Landroid/widget/PopupMenu;->mPopup:Lcom/android/internal/view/menu/MenuPopupHelper;
 Landroid/widget/PopupWindow;->computeAnimationResource()I
 Landroid/widget/PopupWindow;->createPopupLayoutParams(Landroid/os/IBinder;)Landroid/view/WindowManager$LayoutParams;
@@ -1212,8 +2086,12 @@
 Landroid/widget/PopupWindow;->mLastHeight:I
 Landroid/widget/PopupWindow;->mLastWidth:I
 Landroid/widget/PopupWindow;->mOnScrollChangedListener:Landroid/view/ViewTreeObserver$OnScrollChangedListener;
+Landroid/widget/PopupWindow;->mOverlapAnchor:Z
 Landroid/widget/PopupWindow;->mWidthMode:I
+Landroid/widget/PopupWindow;->mWindowLayoutType:I
 Landroid/widget/PopupWindow;->preparePopup(Landroid/view/WindowManager$LayoutParams;)V
+Landroid/widget/PopupWindow;->setClipToScreenEnabled(Z)V
+Landroid/widget/PopupWindow;->setEpicenterBounds(Landroid/graphics/Rect;)V
 Landroid/widget/PopupWindow;->setLayoutInScreenEnabled(Z)V
 Landroid/widget/PopupWindow;->setLayoutInsetDecor(Z)V
 Landroid/widget/PopupWindow;->setTouchModal(Z)V
@@ -1230,9 +2108,16 @@
 Landroid/widget/RelativeLayout;->mGravity:I
 Landroid/widget/RemoteViews$Action;->mergeBehavior()I
 Landroid/widget/RemoteViews$Action;->viewId:I
+Landroid/widget/RemoteViews$BitmapCache;->mBitmaps:Ljava/util/ArrayList;
 Landroid/widget/RemoteViews;->mActions:Ljava/util/ArrayList;
 Landroid/widget/RemoteViews;->mApplication:Landroid/content/pm/ApplicationInfo;
+Landroid/widget/RemoteViews;->mBitmapCache:Landroid/widget/RemoteViews$BitmapCache;
+Landroid/widget/RemoteViews;->mergeRemoteViews(Landroid/widget/RemoteViews;)V
 Landroid/widget/RemoteViews$ReflectionAction;->methodName:Ljava/lang/String;
+Landroid/widget/ScrollBarDrawable;->mVerticalThumb:Landroid/graphics/drawable/Drawable;
+Landroid/widget/ScrollBarDrawable;->setHorizontalThumbDrawable(Landroid/graphics/drawable/Drawable;)V
+Landroid/widget/ScrollBarDrawable;->setVerticalThumbDrawable(Landroid/graphics/drawable/Drawable;)V
+Landroid/widget/ScrollView;->mChildToScrollTo:Landroid/view/View;
 Landroid/widget/ScrollView;->mEdgeGlowBottom:Landroid/widget/EdgeEffect;
 Landroid/widget/ScrollView;->mEdgeGlowTop:Landroid/widget/EdgeEffect;
 Landroid/widget/ScrollView;->mIsBeingDragged:Z
@@ -1248,6 +2133,7 @@
 Landroid/widget/Spinner;->mPopup:Landroid/widget/Spinner$SpinnerPopup;
 Landroid/widget/Switch;->mThumbDrawable:Landroid/graphics/drawable/Drawable;
 Landroid/widget/Switch;->mTrackDrawable:Landroid/graphics/drawable/Drawable;
+Landroid/widget/TabHost$TabSpec;->mContentStrategy:Landroid/widget/TabHost$ContentStrategy;
 Landroid/widget/TabWidget;->setTabSelectionListener(Landroid/widget/TabWidget$OnTabSelectionChanged;)V
 Landroid/widget/TextView;->assumeLayout()V
 Landroid/widget/TextView;->createEditorIfNeeded()V
@@ -1259,14 +2145,21 @@
 Landroid/widget/TextView;->mMaximum:I
 Landroid/widget/TextView;->mMaxMode:I
 Landroid/widget/TextView;->mSingleLine:Z
+Landroid/widget/TextView;->setText(Ljava/lang/CharSequence;Landroid/widget/TextView$BufferType;ZI)V
+Landroid/widget/Toast;->getService()Landroid/app/INotificationManager;
+Landroid/widget/Toast;->sService:Landroid/app/INotificationManager;
 Landroid/widget/VideoView;->mCurrentBufferPercentage:I
 Landroid/widget/VideoView;->mMediaController:Landroid/widget/MediaController;
 Landroid/widget/VideoView;->mSHCallback:Landroid/view/SurfaceHolder$Callback;
 Landroid/widget/VideoView;->mUri:Landroid/net/Uri;
 Landroid/widget/VideoView;->mVideoHeight:I
 Landroid/widget/VideoView;->mVideoWidth:I
+Lcom/android/internal/app/IAppOpsService$Stub$Proxy;->checkOperation(IILjava/lang/String;)I
+Lcom/android/internal/app/IAppOpsService$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Lcom/android/internal/app/IBatteryStats;->getStatistics()[B
 Lcom/android/internal/app/IBatteryStats$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/app/IBatteryStats;
+Lcom/android/internal/app/IVoiceInteractionManagerService$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/app/IVoiceInteractionManagerService;
+Lcom/android/internal/app/IVoiceInteractionManagerService$Stub$Proxy;->showSessionFromSession(Landroid/os/IBinder;Landroid/os/Bundle;I)Z
 Lcom/android/internal/os/BatterySipper;->add(Lcom/android/internal/os/BatterySipper;)V
 Lcom/android/internal/os/BatterySipper;->drainType:Lcom/android/internal/os/BatterySipper$DrainType;
 Lcom/android/internal/os/BatterySipper;->getUid()I
@@ -1311,15 +2204,32 @@
 Lcom/android/internal/os/PowerProfile;->getAveragePower(Ljava/lang/String;)D
 Lcom/android/internal/os/PowerProfile;->getAveragePower(Ljava/lang/String;I)D
 Lcom/android/internal/os/PowerProfile;->getBatteryCapacity()D
+Lcom/android/internal/os/PowerProfile;-><init>(Landroid/content/Context;)V
 Lcom/android/internal/R$array;->config_mobile_hotspot_provision_app:I
 Lcom/android/internal/R$array;->config_tether_wifi_regexs:I
+Lcom/android/internal/R$array;->maps_starting_lat_lng:I
+Lcom/android/internal/R$array;->maps_starting_zoom:I
+Lcom/android/internal/R$attr;->mapViewStyle:I
+Lcom/android/internal/R$attr;->state_focused:I
+Lcom/android/internal/R$attr;->state_pressed:I
+Lcom/android/internal/R$attr;->state_selected:I
 Lcom/android/internal/R$attr;->switchStyle:I
 Lcom/android/internal/R$bool;->config_mms_content_disposition_support:I
 Lcom/android/internal/R$bool;->config_showNavigationBar:I
+Lcom/android/internal/R$dimen;-><init>()V
 Lcom/android/internal/R$dimen;->navigation_bar_height:I
 Lcom/android/internal/R$dimen;->navigation_bar_height_landscape:I
 Lcom/android/internal/R$dimen;->status_bar_height:I
+Lcom/android/internal/R$dimen;->toast_y_offset:I
+Lcom/android/internal/R$drawable;->btn_check_off:I
+Lcom/android/internal/R$drawable;->compass_arrow:I
+Lcom/android/internal/R$drawable;->compass_base:I
+Lcom/android/internal/R$drawable;->ic_maps_indicator_current_position_anim:I
 Lcom/android/internal/R$drawable;->ic_menu_close_clear_cancel:I
+Lcom/android/internal/R$drawable;->loading_tile_android:I
+Lcom/android/internal/R$drawable;->maps_google_logo:I
+Lcom/android/internal/R$drawable;->no_tile_256:I
+Lcom/android/internal/R$drawable;->reticle:I
 Lcom/android/internal/R$id;->amPm:I
 Lcom/android/internal/R$id;->edittext_container:I
 Lcom/android/internal/R$id;->icon:I
@@ -1332,12 +2242,37 @@
 Lcom/android/internal/R$id;->title_container:I
 Lcom/android/internal/R$id;->title:I
 Lcom/android/internal/R$integer;->config_screenBrightnessDim:I
+Lcom/android/internal/R$integer;->config_toastDefaultGravity:I
 Lcom/android/internal/R$layout;->screen_title:I
+Lcom/android/internal/R$styleable;->AndroidManifestApplication_enabled:I
+Lcom/android/internal/R$styleable;->AndroidManifestApplication_hardwareAccelerated:I
+Lcom/android/internal/R$styleable;->AndroidManifestApplication:[I
+Lcom/android/internal/R$styleable;->AndroidManifestApplication_label:I
+Lcom/android/internal/R$styleable;->AndroidManifestApplication_largeHeap:I
+Lcom/android/internal/R$styleable;->AndroidManifestApplication_name:I
+Lcom/android/internal/R$styleable;->AndroidManifestApplication_permission:I
+Lcom/android/internal/R$styleable;->AndroidManifestApplication_process:I
+Lcom/android/internal/R$styleable;->AndroidManifestApplication_supportsRtl:I
+Lcom/android/internal/R$styleable;->AndroidManifestApplication_theme:I
+Lcom/android/internal/R$styleable;->AndroidManifestApplication_uiOptions:I
+Lcom/android/internal/R$styleable;->AndroidManifest:[I
+Lcom/android/internal/R$styleable;->AndroidManifest_installLocation:I
+Lcom/android/internal/R$styleable;->AndroidManifest_sharedUserId:I
+Lcom/android/internal/R$styleable;->AndroidManifestUsesPermission:[I
+Lcom/android/internal/R$styleable;->AndroidManifestUsesPermission_name:I
+Lcom/android/internal/R$styleable;->AndroidManifestUsesSdk:[I
+Lcom/android/internal/R$styleable;->AndroidManifestUsesSdk_minSdkVersion:I
+Lcom/android/internal/R$styleable;->AndroidManifestUsesSdk_targetSdkVersion:I
+Lcom/android/internal/R$styleable;->AndroidManifest_versionCode:I
+Lcom/android/internal/R$styleable;->AndroidManifest_versionName:I
 Lcom/android/internal/R$styleable;->CompoundButton_button:I
 Lcom/android/internal/R$styleable;->CompoundButton:[I
+Lcom/android/internal/R$styleable;->EdgeEffect_colorEdgeEffect:I
+Lcom/android/internal/R$styleable;->EdgeEffect:[I
 Lcom/android/internal/R$styleable;->IconMenuView:[I
 Lcom/android/internal/R$styleable;->ImageView:[I
 Lcom/android/internal/R$styleable;->ImageView_src:I
+Lcom/android/internal/R$styleable;->ScrollView_fillViewport:I
 Lcom/android/internal/R$styleable;->ScrollView:[I
 Lcom/android/internal/R$styleable;->TabWidget:[I
 Lcom/android/internal/R$styleable;->TextView_drawableBottom:I
@@ -1346,31 +2281,56 @@
 Lcom/android/internal/R$styleable;->TextView_drawableTop:I
 Lcom/android/internal/R$styleable;->TextView:[I
 Lcom/android/internal/R$styleable;->View_background:I
+Lcom/android/internal/R$styleable;->ViewGroup_Layout:[I
+Lcom/android/internal/R$styleable;->ViewGroup_Layout_layout_height:I
+Lcom/android/internal/R$styleable;->ViewGroup_Layout_layout_width:I
 Lcom/android/internal/R$styleable;->View:[I
 Lcom/android/internal/R$styleable;->View_id:I
 Lcom/android/internal/R$styleable;->ViewStub:[I
 Lcom/android/internal/R$styleable;->ViewStub_inflatedId:I
 Lcom/android/internal/R$styleable;->ViewStub_layout:I
 Lcom/android/internal/R$styleable;->Window_windowActionBarFullscreenDecorLayout:I
+Lcom/android/internal/R$style;->Theme:I
 Lcom/android/internal/R$xml;->power_profile:I
 Lcom/android/internal/telephony/IPhoneSubInfo$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/telephony/IPhoneSubInfo;
+Lcom/android/internal/telephony/IPhoneSubInfo$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Lcom/android/internal/telephony/ISms$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/telephony/ISms;
+Lcom/android/internal/telephony/ISub$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Lcom/android/internal/telephony/ITelephony;->call(Ljava/lang/String;Ljava/lang/String;)V
 Lcom/android/internal/telephony/ITelephony;->endCall()Z
 Lcom/android/internal/telephony/ITelephony;->isIdle(Ljava/lang/String;)Z
 Lcom/android/internal/telephony/ITelephony;->silenceRinger()V
 Lcom/android/internal/telephony/ITelephony$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/telephony/ITelephony;
+Lcom/android/internal/telephony/ITelephony$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
+Lcom/android/internal/telephony/ITelephony$Stub;->TRANSACTION_getDeviceId:I
 Lcom/android/internal/util/XmlUtils;->readMapXml(Ljava/io/InputStream;)Ljava/util/HashMap;
+Lcom/android/internal/view/IInputMethodManager$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/view/IInputMethodManager;
+Lcom/android/internal/view/IInputMethodManager$Stub$Proxy;->getEnabledInputMethodList()Ljava/util/List;
+Lcom/android/internal/view/IInputMethodManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Lcom/android/internal/view/InputBindResult;->CREATOR:Landroid/os/Parcelable$Creator;
 Lcom/android/internal/view/menu/MenuBuilder;->mContext:Landroid/content/Context;
 Lcom/android/internal/view/menu/MenuBuilder;->setCurrentMenuInfo(Landroid/view/ContextMenu$ContextMenuInfo;)V
 Lcom/android/internal/view/menu/MenuBuilder;->setOptionalIconsVisible(Z)V
 Lcom/android/internal/view/menu/MenuItemImpl;->mIconResId:I
 Lcom/android/internal/view/menu/MenuItemImpl;->setMenuInfo(Landroid/view/ContextMenu$ContextMenuInfo;)V
+Lcom/android/internal/view/menu/MenuView$ItemView;->getItemData()Lcom/android/internal/view/menu/MenuItemImpl;
+Lcom/android/okhttp/ConnectionPool;->keepAliveDurationNs:J
 Lcom/android/okhttp/ConnectionPool;->maxIdleConnections:I
 Lcom/android/okhttp/ConnectionPool;->systemDefault:Lcom/android/okhttp/ConnectionPool;
+Lcom/android/okhttp/internal/http/HttpEngine;->httpStream:Lcom/android/okhttp/internal/http/HttpStream;
+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;
+Lcom/android/okhttp/OkHttpClient;->setProtocols(Ljava/util/List;)Lcom/android/okhttp/OkHttpClient;
+Lcom/android/okhttp/okio/ByteString;->readObject(Ljava/io/ObjectInputStream;)V
+Lcom/android/okhttp/okio/ByteString;->writeObject(Ljava/io/ObjectOutputStream;)V
 Lcom/android/org/conscrypt/OpenSSLSocketImpl;->getAlpnSelectedProtocol()[B
+Lcom/android/org/conscrypt/OpenSSLSocketImpl;->getNpnSelectedProtocol()[B
 Lcom/android/org/conscrypt/OpenSSLSocketImpl;->setAlpnProtocols([B)V
+Lcom/android/org/conscrypt/OpenSSLSocketImpl;->setHostname(Ljava/lang/String;)V
+Lcom/android/org/conscrypt/OpenSSLSocketImpl;->setNpnProtocols([B)V
+Lcom/android/org/conscrypt/OpenSSLSocketImpl;->setUseSessionTickets(Z)V
+Lcom/android/org/conscrypt/TrustManagerImpl;-><init>(Ljava/security/KeyStore;)V
 Ldalvik/system/BaseDexClassLoader;->getLdLibraryPath()Ljava/lang/String;
 Ldalvik/system/BaseDexClassLoader;->pathList:Ldalvik/system/DexPathList;
 Ldalvik/system/BlockGuard;->getThreadPolicy()Ldalvik/system/BlockGuard$Policy;
@@ -1379,18 +2339,26 @@
 Ldalvik/system/CloseGuard;->get()Ldalvik/system/CloseGuard;
 Ldalvik/system/CloseGuard;->open(Ljava/lang/String;)V
 Ldalvik/system/CloseGuard;->warnIfOpen()V
+Ldalvik/system/DexFile;->loadClassBinaryName(Ljava/lang/String;Ljava/lang/ClassLoader;Ljava/util/List;)Ljava/lang/Class;
 Ldalvik/system/DexFile;->mCookie:Ljava/lang/Object;
 Ldalvik/system/DexFile;->mFileName:Ljava/lang/String;
 Ldalvik/system/DexFile;->openDexFile(Ljava/lang/String;Ljava/lang/String;ILjava/lang/ClassLoader;[Ldalvik/system/DexPathList$Element;)Ljava/lang/Object;
+Ldalvik/system/DexPathList;->addDexPath(Ljava/lang/String;Ljava/io/File;)V
 Ldalvik/system/DexPathList;->dexElements:[Ldalvik/system/DexPathList$Element;
 Ldalvik/system/DexPathList$Element;->dexFile:Ldalvik/system/DexFile;
+Ldalvik/system/DexPathList$Element;-><init>(Ldalvik/system/DexFile;Ljava/io/File;)V
+Ldalvik/system/DexPathList$Element;-><init>(Ljava/io/File;ZLjava/io/File;Ldalvik/system/DexFile;)V
+Ldalvik/system/DexPathList;-><init>(Ljava/lang/ClassLoader;Ljava/lang/String;Ljava/lang/String;Ljava/io/File;)V
 Ldalvik/system/DexPathList;->makeDexElements(Ljava/util/List;Ljava/io/File;Ljava/util/List;Ljava/lang/ClassLoader;)[Ldalvik/system/DexPathList$Element;
 Ldalvik/system/DexPathList;->makePathElements(Ljava/util/List;)[Ldalvik/system/DexPathList$NativeLibraryElement;
 Ldalvik/system/DexPathList;->makePathElements(Ljava/util/List;Ljava/io/File;Ljava/util/List;)[Ldalvik/system/DexPathList$Element;
 Ldalvik/system/DexPathList;->nativeLibraryDirectories:Ljava/util/List;
+Ldalvik/system/DexPathList$NativeLibraryElement;-><init>(Ljava/io/File;)V
 Ldalvik/system/DexPathList;->nativeLibraryPathElements:[Ldalvik/system/DexPathList$NativeLibraryElement;
+Ldalvik/system/DexPathList;->splitPaths(Ljava/lang/String;Z)Ljava/util/List;
 Ldalvik/system/DexPathList;->systemNativeLibraryDirectories:Ljava/util/List;
 Ldalvik/system/VMDebug;->dumpReferenceTables()V
+Ldalvik/system/VMRuntime;->addressOf(Ljava/lang/Object;)J
 Ldalvik/system/VMRuntime;->clearGrowthLimit()V
 Ldalvik/system/VMRuntime;->getCurrentInstructionSet()Ljava/lang/String;
 Ldalvik/system/VMRuntime;->getRuntime()Ldalvik/system/VMRuntime;
@@ -1398,52 +2366,333 @@
 Ldalvik/system/VMRuntime;->newNonMovableArray(Ljava/lang/Class;I)Ljava/lang/Object;
 Ldalvik/system/VMRuntime;->registerNativeAllocation(I)V
 Ldalvik/system/VMRuntime;->registerNativeFree(I)V
+Ldalvik/system/VMRuntime;->runFinalization(J)V
 Ldalvik/system/VMRuntime;->setMinimumHeapSize(J)J
 Ldalvik/system/VMRuntime;->setTargetHeapUtilization(F)F
 Ldalvik/system/VMRuntime;->trackExternalAllocation(J)Z
 Ldalvik/system/VMRuntime;->trackExternalFree(J)V
+Ldalvik/system/VMRuntime;->vmInstructionSet()Ljava/lang/String;
+Ldalvik/system/VMRuntime;->vmLibrary()Ljava/lang/String;
 Ldalvik/system/VMStack;->getCallingClassLoader()Ljava/lang/ClassLoader;
 Ldalvik/system/VMStack;->getStackClass2()Ljava/lang/Class;
+Ljava/awt/font/NumericShaper;->writeObject(Ljava/io/ObjectOutputStream;)V
+Ljava/beans/PropertyChangeSupport;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/beans/PropertyChangeSupport;->writeObject(Ljava/io/ObjectOutputStream;)V
 Ljava/io/FileDescriptor;->descriptor:I
 Ljava/io/FileDescriptor;->getInt$()I
 Ljava/io/FileDescriptor;->setInt$(I)V
+Ljava/io/FileInputStream;->fd:Ljava/io/FileDescriptor;
+Ljava/io/FileOutputStream;->fd:Ljava/io/FileDescriptor;
+Ljava/io/File;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/io/File;->writeObject(Ljava/io/ObjectOutputStream;)V
 Ljava/io/ObjectStreamClass;->getConstructorId(Ljava/lang/Class;)J
 Ljava/io/ObjectStreamClass;->newInstance(Ljava/lang/Class;J)Ljava/lang/Object;
 Ljava/io/ObjectStreamClass;->newInstance()Ljava/lang/Object;
+Ljava/io/UncheckedIOException;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/lang/AbstractStringBuilder;->value:[C
+Ljava/lang/Boolean;->value:Z
+Ljava/lang/Byte;->value:B
+Ljava/lang/Character;->value:C
 Ljava/lang/Class;->dexCache:Ljava/lang/Object;
 Ljava/lang/Class;->dexClassDefIndex:I
 Ljava/lang/ClassLoader;->parent:Ljava/lang/ClassLoader;
+Ljava/lang/Daemons$Daemon;->isRunning()Z
+Ljava/lang/Daemons$Daemon;->start()V
 Ljava/lang/Daemons$Daemon;->stop()V
 Ljava/lang/Daemons$Daemon;->thread:Ljava/lang/Thread;
 Ljava/lang/Daemons$FinalizerDaemon;->finalizingObject:Ljava/lang/Object;
 Ljava/lang/Daemons$FinalizerDaemon;->INSTANCE:Ljava/lang/Daemons$FinalizerDaemon;
 Ljava/lang/Daemons$FinalizerWatchdogDaemon;->INSTANCE:Ljava/lang/Daemons$FinalizerWatchdogDaemon;
+Ljava/lang/Daemons;->MAX_FINALIZE_NANOS:J
+Ljava/lang/Daemons$ReferenceQueueDaemon;->INSTANCE:Ljava/lang/Daemons$ReferenceQueueDaemon;
+Ljava/lang/Daemons;->requestHeapTrim()V
+Ljava/lang/Daemons;->start()V
+Ljava/lang/Daemons;->stop()V
+Ljava/lang/Double;->value:D
+Ljava/lang/Enum;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/lang/Float;->value:F
+Ljava/lang/Integer;->value:I
+Ljava/lang/invoke/MethodType;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/lang/invoke/MethodType;->writeObject(Ljava/io/ObjectOutputStream;)V
+Ljava/lang/Long;->value:J
+Ljava/lang/ref/FinalizerReference;->add(Ljava/lang/Object;)V
+Ljava/lang/ref/FinalizerReference;->head:Ljava/lang/ref/FinalizerReference;
+Ljava/lang/ref/FinalizerReference;->next:Ljava/lang/ref/FinalizerReference;
+Ljava/lang/ref/FinalizerReference;->queue:Ljava/lang/ref/ReferenceQueue;
+Ljava/lang/ref/FinalizerReference;->remove(Ljava/lang/ref/FinalizerReference;)V
+Ljava/lang/reflect/Executable;->artMethod:J
+Ljava/lang/reflect/Parameter;-><init>(Ljava/lang/String;ILjava/lang/reflect/Executable;I)V
+Ljava/lang/reflect/Proxy;->invoke(Ljava/lang/reflect/Proxy;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/lang/ref/ReferenceQueue;->add(Ljava/lang/ref/Reference;)V
+Ljava/lang/ref/Reference;->referent:Ljava/lang/Object;
 Ljava/lang/Runtime;->loadLibrary(Ljava/lang/String;Ljava/lang/ClassLoader;)V
 Ljava/lang/Runtime;->load(Ljava/lang/String;Ljava/lang/ClassLoader;)V
 Ljava/lang/Runtime;->nativeLoad(Ljava/lang/String;Ljava/lang/ClassLoader;)Ljava/lang/String;
+Ljava/lang/Short;->value:S
+Ljava/lang/StringBuffer;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/lang/StringBuffer;->writeObject(Ljava/io/ObjectOutputStream;)V
+Ljava/lang/StringBuilder;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/lang/StringBuilder;->writeObject(Ljava/io/ObjectOutputStream;)V
+Ljava/lang/String;-><init>(II[C)V
+Ljava/lang/Thread;->daemon:Z
+Ljava/lang/Thread;->dispatchUncaughtException(Ljava/lang/Throwable;)V
+Ljava/lang/ThreadGroup;->add(Ljava/lang/Thread;)V
+Ljava/lang/ThreadGroup;->groups:[Ljava/lang/ThreadGroup;
+Ljava/lang/Thread;->group:Ljava/lang/ThreadGroup;
+Ljava/lang/ThreadGroup;->mainThreadGroup:Ljava/lang/ThreadGroup;
+Ljava/lang/ThreadGroup;->name:Ljava/lang/String;
+Ljava/lang/ThreadGroup;->ngroups:I
 Ljava/lang/ThreadGroup;->parent:Ljava/lang/ThreadGroup;
 Ljava/lang/ThreadGroup;->systemThreadGroup:Ljava/lang/ThreadGroup;
+Ljava/lang/ThreadGroup;->threadTerminated(Ljava/lang/Thread;)V
 Ljava/lang/Thread;->inheritableThreadLocals:Ljava/lang/ThreadLocal$ThreadLocalMap;
+Ljava/lang/Thread;-><init>(Ljava/lang/ThreadGroup;Ljava/lang/String;IZ)V
+Ljava/lang/Thread;->lock:Ljava/lang/Object;
+Ljava/lang/Thread;->name:Ljava/lang/String;
+Ljava/lang/Thread;->nativePeer:J
+Ljava/lang/Thread;->priority:I
+Ljava/lang/Throwable;->backtrace:Ljava/lang/Object;
+Ljava/lang/Throwable;->cause:Ljava/lang/Throwable;
 Ljava/lang/Throwable;->detailMessage:Ljava/lang/String;
+Ljava/lang/Throwable;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/lang/Throwable;->stackTrace:[Ljava/lang/StackTraceElement;
+Ljava/lang/Throwable;->suppressedExceptions:Ljava/util/List;
+Ljava/lang/Throwable;->writeObject(Ljava/io/ObjectOutputStream;)V
+Ljava/lang/Void;-><init>()V
+Ljava/math/BigDecimal;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/math/BigDecimal;->writeObject(Ljava/io/ObjectOutputStream;)V
+Ljava/math/BigInteger;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/math/BigInteger;->writeObject(Ljava/io/ObjectOutputStream;)V
+Ljava/math/MathContext;->readObject(Ljava/io/ObjectInputStream;)V
 Ljava/net/Authenticator;->theAuthenticator:Ljava/net/Authenticator;
 Ljava/net/DatagramSocket;->impl:Ljava/net/DatagramSocketImpl;
+Ljava/net/HttpCookie;->httpOnly:Z
+Ljava/net/HttpCookie;->whenCreated:J
+Ljava/net/Inet4Address;-><init>()V
+Ljava/net/Inet6Address;->holder6:Ljava/net/Inet6Address$Inet6AddressHolder;
+Ljava/net/Inet6Address$Inet6AddressHolder;->ipaddress:[B
+Ljava/net/Inet6Address$Inet6AddressHolder;->scope_id:I
+Ljava/net/Inet6Address$Inet6AddressHolder;->scope_id_set:Z
+Ljava/net/Inet6Address$Inet6AddressHolder;->scope_ifname:Ljava/net/NetworkInterface;
+Ljava/net/Inet6Address;-><init>()V
+Ljava/net/Inet6Address;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/net/Inet6Address;->writeObject(Ljava/io/ObjectOutputStream;)V
 Ljava/net/InetAddress;->clearDnsCache()V
+Ljava/net/InetAddress;->holder:Ljava/net/InetAddress$InetAddressHolder;
+Ljava/net/InetAddress$InetAddressHolder;->address:I
+Ljava/net/InetAddress$InetAddressHolder;->family:I
+Ljava/net/InetAddress$InetAddressHolder;->hostName:Ljava/lang/String;
+Ljava/net/InetAddress$InetAddressHolder;->originalHostName:Ljava/lang/String;
 Ljava/net/InetAddress;->isNumeric(Ljava/lang/String;)Z
 Ljava/net/InetAddress;->parseNumericAddress(Ljava/lang/String;)Ljava/net/InetAddress;
+Ljava/net/InetAddress;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/net/InetAddress;->writeObject(Ljava/io/ObjectOutputStream;)V
+Ljava/net/InetSocketAddress;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/net/InetSocketAddress;->writeObject(Ljava/io/ObjectOutputStream;)V
+Ljava/net/Socket;->getFileDescriptor$()Ljava/io/FileDescriptor;
 Ljava/net/Socket;->impl:Ljava/net/SocketImpl;
 Ljava/net/URI;->host:Ljava/lang/String;
+Ljava/net/URI;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/net/URI;->writeObject(Ljava/io/ObjectOutputStream;)V
+Ljava/net/URL;->handlers:Ljava/util/Hashtable;
+Ljava/net/URL;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/net/URL;->writeObject(Ljava/io/ObjectOutputStream;)V
+Ljava/nio/Buffer;->address:J
+Ljava/nio/Buffer;->capacity:I
+Ljava/nio/Buffer;->_elementSizeShift:I
+Ljava/nio/Buffer;->limit:I
+Ljava/nio/Buffer;->position:I
+Ljava/nio/ByteBuffer;->hb:[B
+Ljava/nio/ByteBuffer;->isReadOnly:Z
+Ljava/nio/ByteBuffer;->offset:I
 Ljava/nio/charset/CharsetEncoder;->canEncode(Ljava/nio/CharBuffer;)Z
+Ljava/nio/DirectByteBuffer;-><init>(JI)V
+Ljava/nio/file/DirectoryIteratorException;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/nio/NIOAccess;->getBaseArray(Ljava/nio/Buffer;)Ljava/lang/Object;
+Ljava/nio/NIOAccess;->getBaseArrayOffset(Ljava/nio/Buffer;)I
+Ljava/nio/NIOAccess;->getBasePointer(Ljava/nio/Buffer;)J
+Ljava/security/cert/CertificateRevokedException;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/security/cert/CertificateRevokedException;->writeObject(Ljava/io/ObjectOutputStream;)V
+Ljava/security/cert/CertPathValidatorException;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/security/CodeSigner;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/security/GuardedObject;->writeObject(Ljava/io/ObjectOutputStream;)V
+Ljava/security/Provider;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/security/SignedObject;->readObject(Ljava/io/ObjectInputStream;)V
 Ljava/security/spec/ECParameterSpec;->getCurveName()Ljava/lang/String;
 Ljava/security/spec/ECParameterSpec;->setCurveName(Ljava/lang/String;)V
+Ljava/security/Timestamp;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/text/ChoiceFormat;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/text/DateFormatSymbols;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/text/DateFormatSymbols;->writeObject(Ljava/io/ObjectOutputStream;)V
+Ljava/text/DecimalFormat;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/text/DecimalFormatSymbols;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/text/DecimalFormatSymbols;->writeObject(Ljava/io/ObjectOutputStream;)V
+Ljava/text/DecimalFormat;->writeObject(Ljava/io/ObjectOutputStream;)V
+Ljava/text/MessageFormat;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/text/NumberFormat;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/text/NumberFormat;->writeObject(Ljava/io/ObjectOutputStream;)V
+Ljava/text/SimpleDateFormat;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/time/chrono/AbstractChronology;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/time/chrono/HijrahChronology;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/time/chrono/HijrahDate;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/time/chrono/IsoChronology;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/time/chrono/JapaneseChronology;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/time/chrono/JapaneseDate;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/time/chrono/JapaneseEra;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/time/chrono/MinguoChronology;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/time/chrono/MinguoDate;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/time/chrono/ThaiBuddhistChronology;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/time/chrono/ThaiBuddhistDate;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/time/Duration;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/time/Instant;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/time/LocalDate;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/time/LocalDateTime;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/time/LocalTime;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/time/MonthDay;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/time/OffsetDateTime;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/time/OffsetTime;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/time/Period;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/time/temporal/ValueRange;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/time/temporal/WeekFields;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/time/YearMonth;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/time/Year;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/time/ZonedDateTime;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/time/ZoneId;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/time/ZoneOffset;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/time/zone/ZoneOffsetTransition;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/time/zone/ZoneOffsetTransitionRule;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/time/zone/ZoneRules;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/util/ArrayDeque;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/util/ArrayDeque;->writeObject(Ljava/io/ObjectOutputStream;)V
+Ljava/util/ArrayList;->elementData:[Ljava/lang/Object;
+Ljava/util/ArrayList;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/util/ArrayList;->size:I
 Ljava/util/ArrayList$SubList;->parent:Ljava/util/AbstractList;
 Ljava/util/ArrayList$SubList;->parentOffset:I
 Ljava/util/ArrayList$SubList;->size:I
+Ljava/util/ArrayList;->writeObject(Ljava/io/ObjectOutputStream;)V
 Ljava/util/Arrays$ArrayList;->a:[Ljava/lang/Object;
+Ljava/util/BitSet;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/util/BitSet;->writeObject(Ljava/io/ObjectOutputStream;)V
+Ljava/util/Calendar;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/util/Calendar;->writeObject(Ljava/io/ObjectOutputStream;)V
 Ljava/util/Calendar;->zone:Ljava/util/TimeZone;
+Ljava/util/Collections$EmptyList;-><init>()V
+Ljava/util/Collections$SetFromMap;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/util/Collections$SynchronizedCollection;->c:Ljava/util/Collection;
+Ljava/util/Collections$SynchronizedCollection;->writeObject(Ljava/io/ObjectOutputStream;)V
+Ljava/util/Collections$SynchronizedMap;->m:Ljava/util/Map;
+Ljava/util/Collections$SynchronizedMap;->writeObject(Ljava/io/ObjectOutputStream;)V
+Ljava/util/Collections$UnmodifiableCollection;->c:Ljava/util/Collection;
+Ljava/util/Collections$UnmodifiableMap;->m:Ljava/util/Map;
+Ljava/util/concurrent/atomic/AtomicReferenceArray;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/util/concurrent/atomic/DoubleAccumulator;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/util/concurrent/atomic/DoubleAdder;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/util/concurrent/atomic/LongAccumulator;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/util/concurrent/atomic/LongAdder;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/util/concurrent/ConcurrentHashMap;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/util/concurrent/ConcurrentHashMap;->writeObject(Ljava/io/ObjectOutputStream;)V
+Ljava/util/concurrent/ConcurrentLinkedDeque;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/util/concurrent/ConcurrentLinkedDeque;->writeObject(Ljava/io/ObjectOutputStream;)V
+Ljava/util/concurrent/ConcurrentLinkedQueue;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/util/concurrent/ConcurrentLinkedQueue;->writeObject(Ljava/io/ObjectOutputStream;)V
+Ljava/util/concurrent/ConcurrentSkipListMap;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/util/concurrent/ConcurrentSkipListMap;->writeObject(Ljava/io/ObjectOutputStream;)V
+Ljava/util/concurrent/CopyOnWriteArrayList;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/util/concurrent/CopyOnWriteArrayList;->writeObject(Ljava/io/ObjectOutputStream;)V
+Ljava/util/concurrent/ForkJoinTask;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/util/concurrent/ForkJoinTask;->writeObject(Ljava/io/ObjectOutputStream;)V
 Ljava/util/concurrent/FutureTask;->callable:Ljava/util/concurrent/Callable;
+Ljava/util/concurrent/LinkedBlockingDeque;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/util/concurrent/LinkedBlockingDeque;->writeObject(Ljava/io/ObjectOutputStream;)V
+Ljava/util/concurrent/LinkedBlockingQueue;->capacity:I
+Ljava/util/concurrent/LinkedBlockingQueue;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/util/concurrent/LinkedBlockingQueue;->writeObject(Ljava/io/ObjectOutputStream;)V
+Ljava/util/concurrent/LinkedTransferQueue;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/util/concurrent/LinkedTransferQueue;->writeObject(Ljava/io/ObjectOutputStream;)V
+Ljava/util/concurrent/locks/ReentrantLock$Sync;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/util/concurrent/locks/ReentrantReadWriteLock$Sync;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/util/concurrent/locks/StampedLock;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/util/concurrent/PriorityBlockingQueue;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/util/concurrent/PriorityBlockingQueue;->writeObject(Ljava/io/ObjectOutputStream;)V
+Ljava/util/concurrent/SynchronousQueue;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/util/concurrent/SynchronousQueue;->writeObject(Ljava/io/ObjectOutputStream;)V
+Ljava/util/concurrent/ThreadLocalRandom;->writeObject(Ljava/io/ObjectOutputStream;)V
+Ljava/util/Date;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/util/Date;->writeObject(Ljava/io/ObjectOutputStream;)V
+Ljava/util/EnumMap;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/util/EnumMap;->writeObject(Ljava/io/ObjectOutputStream;)V
+Ljava/util/EnumSet;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/util/GregorianCalendar;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/util/HashMap$HashIterator;->hasNext()Z
+Ljava/util/HashMap;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/util/HashMap;->writeObject(Ljava/io/ObjectOutputStream;)V
+Ljava/util/HashSet;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/util/HashSet;->writeObject(Ljava/io/ObjectOutputStream;)V
+Ljava/util/Hashtable;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/util/Hashtable;->writeObject(Ljava/io/ObjectOutputStream;)V
+Ljava/util/IdentityHashMap;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/util/IdentityHashMap;->writeObject(Ljava/io/ObjectOutputStream;)V
+Ljava/util/InvalidPropertiesFormatException;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/util/InvalidPropertiesFormatException;->writeObject(Ljava/io/ObjectOutputStream;)V
+Ljava/util/LinkedHashMap;->eldest()Ljava/util/Map$Entry;
+Ljava/util/LinkedList;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/util/LinkedList;->writeObject(Ljava/io/ObjectOutputStream;)V
 Ljava/util/Locale;->createConstant(Ljava/lang/String;Ljava/lang/String;)Ljava/util/Locale;
+Ljava/util/Locale;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/util/Locale;->readResolve()Ljava/lang/Object;
+Ljava/util/Locale;->writeObject(Ljava/io/ObjectOutputStream;)V
+Ljava/util/logging/LogRecord;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/util/logging/LogRecord;->writeObject(Ljava/io/ObjectOutputStream;)V
+Ljava/util/prefs/NodeChangeEvent;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/util/prefs/NodeChangeEvent;->writeObject(Ljava/io/ObjectOutputStream;)V
+Ljava/util/prefs/PreferenceChangeEvent;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/util/prefs/PreferenceChangeEvent;->writeObject(Ljava/io/ObjectOutputStream;)V
+Ljava/util/PriorityQueue;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/util/PriorityQueue;->writeObject(Ljava/io/ObjectOutputStream;)V
+Ljava/util/Random;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/util/Random;->writeObject(Ljava/io/ObjectOutputStream;)V
+Ljava/util/regex/Matcher;->appendPos:I
+Ljava/util/regex/Pattern;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/util/SimpleTimeZone;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/util/SimpleTimeZone;->writeObject(Ljava/io/ObjectOutputStream;)V
+Ljava/util/TreeMap;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/util/TreeMap;->writeObject(Ljava/io/ObjectOutputStream;)V
+Ljava/util/TreeSet;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/util/TreeSet;->writeObject(Ljava/io/ObjectOutputStream;)V
+Ljava/util/Vector;->writeObject(Ljava/io/ObjectOutputStream;)V
+Ljava/util/zip/Deflater;->buf:[B
+Ljava/util/zip/Deflater;->finished:Z
+Ljava/util/zip/Deflater;->finish:Z
+Ljava/util/zip/Deflater;->len:I
+Ljava/util/zip/Deflater;->level:I
+Ljava/util/zip/Deflater;->off:I
+Ljava/util/zip/Deflater;->setParams:Z
+Ljava/util/zip/Deflater;->strategy:I
+Ljava/util/zip/Inflater;->buf:[B
+Ljava/util/zip/Inflater;->finished:Z
+Ljava/util/zip/Inflater;->len:I
+Ljava/util/zip/Inflater;->needDict:Z
+Ljava/util/zip/Inflater;->off:I
+Ljava/util/zip/ZipEntry;-><init>(Ljava/lang/String;Ljava/lang/String;JJJII[BJ)V
+Ljava/util/zip/ZipFile;->jzfile:J
+Ljavax/crypto/SealedObject;->readObject(Ljava/io/ObjectInputStream;)V
 Ljavax/net/ssl/SSLServerSocketFactory;->defaultServerSocketFactory:Ljavax/net/ssl/SSLServerSocketFactory;
 Ljavax/net/ssl/SSLSocketFactory;->defaultSocketFactory:Ljavax/net/ssl/SSLSocketFactory;
+Ljavax/security/auth/Subject;->readObject(Ljava/io/ObjectInputStream;)V
+Ljavax/security/auth/Subject$SecureSet;->readObject(Ljava/io/ObjectInputStream;)V
+Ljavax/security/auth/Subject$SecureSet;->writeObject(Ljava/io/ObjectOutputStream;)V
+Ljavax/security/auth/Subject;->writeObject(Ljava/io/ObjectOutputStream;)V
+Ljavax/security/auth/x500/X500Principal;->readObject(Ljava/io/ObjectInputStream;)V
+Ljavax/security/auth/x500/X500Principal;->writeObject(Ljava/io/ObjectOutputStream;)V
+Ljavax/xml/datatype/DatatypeConfigurationException;->readObject(Ljava/io/ObjectInputStream;)V
+Ljavax/xml/namespace/QName;->readObject(Ljava/io/ObjectInputStream;)V
+Llibcore/util/ZoneInfo;->mTransitions:[J
+Llibcore/util/ZoneInfo;->readObject(Ljava/io/ObjectInputStream;)V
 Lorg/apache/http/conn/ssl/SSLSocketFactory;-><init>(Ljavax/net/ssl/SSLSocketFactory;)V
+Lorg/apache/http/conn/ssl/SSLSocketFactory;-><init>()V
 Lorg/json/JSONArray;->values:Ljava/util/List;
+Lorg/json/JSONObject;->writeTo(Lorg/json/JSONStringer;)V
 Lsun/misc/Unsafe;->theUnsafe:Lsun/misc/Unsafe;
+Lsun/security/util/ObjectIdentifier;->readObject(Ljava/io/ObjectInputStream;)V
+Lsun/security/util/ObjectIdentifier;->writeObject(Ljava/io/ObjectOutputStream;)V
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index aca8d48..0bc510a 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -6362,8 +6362,6 @@
         } else {
             writer.print(prefix); writer.println("No AutofillManager");
         }
-
-        ResourcesManager.getInstance().dump(prefix, writer);
     }
 
     /**
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index 4626cb2..b365d52 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -219,6 +219,9 @@
     /**
      * Start activity {@code intents} as if {@code packageName} on user {@code userId} did it.
      *
+     * - DO NOT call it with the calling UID cleared.
+     * - All the necessary caller permission checks must be done at callsites.
+     *
      * @return error codes used by {@link IActivityManager#startActivity} and its siblings.
      */
     public abstract int startActivitiesAsPackage(String packageName,
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index c805658..e80610b 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -8862,6 +8862,7 @@
         private static final String EXTRA_CONTENT_INTENT = "content_intent";
         private static final String EXTRA_DELETE_INTENT = "delete_intent";
         private static final String EXTRA_CHANNEL_ID = "channel_id";
+        private static final String EXTRA_SUPPRESS_SHOW_OVER_APPS = "suppressShowOverApps";
 
         // Flags bitwise-ored to mFlags
         private static final int FLAG_AVAILABLE_ON_TV = 0x1;
@@ -8870,6 +8871,7 @@
         private String mChannelId;
         private PendingIntent mContentIntent;
         private PendingIntent mDeleteIntent;
+        private boolean mSuppressShowOverApps;
 
         /**
          * Create a {@link TvExtender} with default options.
@@ -8889,6 +8891,7 @@
             if (bundle != null) {
                 mFlags = bundle.getInt(EXTRA_FLAGS);
                 mChannelId = bundle.getString(EXTRA_CHANNEL_ID);
+                mSuppressShowOverApps = bundle.getBoolean(EXTRA_SUPPRESS_SHOW_OVER_APPS);
                 mContentIntent = bundle.getParcelable(EXTRA_CONTENT_INTENT);
                 mDeleteIntent = bundle.getParcelable(EXTRA_DELETE_INTENT);
             }
@@ -8905,6 +8908,7 @@
 
             bundle.putInt(EXTRA_FLAGS, mFlags);
             bundle.putString(EXTRA_CHANNEL_ID, mChannelId);
+            bundle.putBoolean(EXTRA_SUPPRESS_SHOW_OVER_APPS, mSuppressShowOverApps);
             if (mContentIntent != null) {
                 bundle.putParcelable(EXTRA_CONTENT_INTENT, mContentIntent);
             }
@@ -8997,6 +9001,23 @@
         public PendingIntent getDeleteIntent() {
             return mDeleteIntent;
         }
+
+        /**
+         * Specifies whether this notification should suppress showing a message over top of apps
+         * outside of the launcher.
+         */
+        public TvExtender setSuppressShowOverApps(boolean suppress) {
+            mSuppressShowOverApps = suppress;
+            return this;
+        }
+
+        /**
+         * Returns true if this notification should not show messages over top of apps
+         * outside of the launcher.
+         */
+        public boolean getSuppressShowOverApps() {
+            return mSuppressShowOverApps;
+        }
     }
 
     /**
diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java
index b96e028..fb11272 100644
--- a/core/java/android/app/ResourcesManager.java
+++ b/core/java/android/app/ResourcesManager.java
@@ -21,7 +21,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.pm.ActivityInfo;
-import android.content.res.ApkAssets;
 import android.content.res.AssetManager;
 import android.content.res.CompatResources;
 import android.content.res.CompatibilityInfo;
@@ -35,7 +34,6 @@
 import android.util.ArrayMap;
 import android.util.DisplayMetrics;
 import android.util.Log;
-import android.util.LruCache;
 import android.util.Pair;
 import android.util.Slog;
 import android.view.Display;
@@ -43,13 +41,9 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.ArrayUtils;
-import com.android.internal.util.IndentingPrintWriter;
 
-import java.io.IOException;
-import java.io.PrintWriter;
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
-import java.util.Collection;
 import java.util.Objects;
 import java.util.WeakHashMap;
 import java.util.function.Predicate;
@@ -65,7 +59,12 @@
      * Predicate that returns true if a WeakReference is gc'ed.
      */
     private static final Predicate<WeakReference<Resources>> sEmptyReferencePredicate =
-            weakRef -> weakRef == null || weakRef.get() == null;
+            new Predicate<WeakReference<Resources>>() {
+                @Override
+                public boolean test(WeakReference<Resources> weakRef) {
+                    return weakRef == null || weakRef.get() == null;
+                }
+            };
 
     /**
      * The global compatibility settings.
@@ -90,48 +89,6 @@
      */
     private final ArrayList<WeakReference<Resources>> mResourceReferences = new ArrayList<>();
 
-    private static class ApkKey {
-        public final String path;
-        public final boolean sharedLib;
-        public final boolean overlay;
-
-        ApkKey(String path, boolean sharedLib, boolean overlay) {
-            this.path = path;
-            this.sharedLib = sharedLib;
-            this.overlay = overlay;
-        }
-
-        @Override
-        public int hashCode() {
-            int result = 1;
-            result = 31 * result + this.path.hashCode();
-            result = 31 * result + Boolean.hashCode(this.sharedLib);
-            result = 31 * result + Boolean.hashCode(this.overlay);
-            return result;
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            if (!(obj instanceof ApkKey)) {
-                return false;
-            }
-            ApkKey other = (ApkKey) obj;
-            return this.path.equals(other.path) && this.sharedLib == other.sharedLib
-                    && this.overlay == other.overlay;
-        }
-    }
-
-    /**
-     * The ApkAssets we are caching and intend to hold strong references to.
-     */
-    private final LruCache<ApkKey, ApkAssets> mLoadedApkAssets = new LruCache<>(15);
-
-    /**
-     * The ApkAssets that are being referenced in the wild that we can reuse, even if they aren't
-     * in our LRU cache. Bonus resources :)
-     */
-    private final ArrayMap<ApkKey, WeakReference<ApkAssets>> mCachedApkAssets = new ArrayMap<>();
-
     /**
      * Resources and base configuration override associated with an Activity.
      */
@@ -303,41 +260,6 @@
         }
     }
 
-    private @NonNull ApkAssets loadApkAssets(String path, boolean sharedLib, boolean overlay)
-            throws IOException {
-        final ApkKey newKey = new ApkKey(path, sharedLib, overlay);
-        ApkAssets apkAssets = mLoadedApkAssets.get(newKey);
-        if (apkAssets != null) {
-            return apkAssets;
-        }
-
-        // Optimistically check if this ApkAssets exists somewhere else.
-        final WeakReference<ApkAssets> apkAssetsRef = mCachedApkAssets.get(newKey);
-        if (apkAssetsRef != null) {
-            apkAssets = apkAssetsRef.get();
-            if (apkAssets != null) {
-                mLoadedApkAssets.put(newKey, apkAssets);
-                return apkAssets;
-            } else {
-                // Clean up the reference.
-                mCachedApkAssets.remove(newKey);
-            }
-        }
-
-        // We must load this from disk.
-        if (overlay) {
-            final String idmapPath = "/data/resource-cache/"
-                    + path.substring(1).replace('/', '@')
-                    + "@idmap";
-            apkAssets = ApkAssets.loadOverlayFromPath(idmapPath, false /*system*/);
-        } else {
-            apkAssets = ApkAssets.loadFromPath(path, false /*system*/, sharedLib);
-        }
-        mLoadedApkAssets.put(newKey, apkAssets);
-        mCachedApkAssets.put(newKey, new WeakReference<>(apkAssets));
-        return apkAssets;
-    }
-
     /**
      * Creates an AssetManager from the paths within the ResourcesKey.
      *
@@ -348,15 +270,13 @@
     */
     @VisibleForTesting
     protected @Nullable AssetManager createAssetManager(@NonNull final ResourcesKey key) {
-        final ArrayList<ApkAssets> apkAssets = new ArrayList<>();
+        AssetManager assets = new AssetManager();
 
         // resDir can be null if the 'android' package is creating a new Resources object.
         // This is fine, since each AssetManager automatically loads the 'android' package
         // already.
         if (key.mResDir != null) {
-            try {
-                apkAssets.add(loadApkAssets(key.mResDir, false /*sharedLib*/, false /*overlay*/));
-            } catch (IOException e) {
+            if (assets.addAssetPath(key.mResDir) == 0) {
                 Log.e(TAG, "failed to add asset path " + key.mResDir);
                 return null;
             }
@@ -364,10 +284,7 @@
 
         if (key.mSplitResDirs != null) {
             for (final String splitResDir : key.mSplitResDirs) {
-                try {
-                    apkAssets.add(loadApkAssets(splitResDir, false /*sharedLib*/,
-                            false /*overlay*/));
-                } catch (IOException e) {
+                if (assets.addAssetPath(splitResDir) == 0) {
                     Log.e(TAG, "failed to add split asset path " + splitResDir);
                     return null;
                 }
@@ -376,13 +293,7 @@
 
         if (key.mOverlayDirs != null) {
             for (final String idmapPath : key.mOverlayDirs) {
-                try {
-                    apkAssets.add(loadApkAssets(idmapPath, false /*sharedLib*/, true /*overlay*/));
-                } catch (IOException e) {
-                    Log.w(TAG, "failed to add overlay path " + idmapPath);
-
-                    // continue.
-                }
+                assets.addOverlayPath(idmapPath);
             }
         }
 
@@ -391,77 +302,16 @@
                 if (libDir.endsWith(".apk")) {
                     // Avoid opening files we know do not have resources,
                     // like code-only .jar files.
-                    try {
-                        apkAssets.add(loadApkAssets(libDir, true /*sharedLib*/, false /*overlay*/));
-                    } catch (IOException e) {
+                    if (assets.addAssetPathAsSharedLibrary(libDir) == 0) {
                         Log.w(TAG, "Asset path '" + libDir +
                                 "' does not exist or contains no resources.");
-
-                        // continue.
                     }
                 }
             }
         }
-
-        AssetManager assets = new AssetManager();
-        assets.setApkAssets(apkAssets.toArray(new ApkAssets[apkAssets.size()]),
-                false /*invalidateCaches*/);
         return assets;
     }
 
-    private static <T> int countLiveReferences(Collection<WeakReference<T>> collection) {
-        int count = 0;
-        for (WeakReference<T> ref : collection) {
-            final T value = ref != null ? ref.get() : null;
-            if (value != null) {
-                count++;
-            }
-        }
-        return count;
-    }
-
-    /**
-     * @hide
-     */
-    public void dump(String prefix, PrintWriter printWriter) {
-        synchronized (this) {
-            IndentingPrintWriter pw = new IndentingPrintWriter(printWriter, "  ");
-            for (int i = 0; i < prefix.length() / 2; i++) {
-                pw.increaseIndent();
-            }
-
-            pw.println("ResourcesManager:");
-            pw.increaseIndent();
-            pw.print("cached apks: total=");
-            pw.print(mLoadedApkAssets.size());
-            pw.print(" created=");
-            pw.print(mLoadedApkAssets.createCount());
-            pw.print(" evicted=");
-            pw.print(mLoadedApkAssets.evictionCount());
-            pw.print(" hit=");
-            pw.print(mLoadedApkAssets.hitCount());
-            pw.print(" miss=");
-            pw.print(mLoadedApkAssets.missCount());
-            pw.print(" max=");
-            pw.print(mLoadedApkAssets.maxSize());
-            pw.println();
-
-            pw.print("total apks: ");
-            pw.println(countLiveReferences(mCachedApkAssets.values()));
-
-            pw.print("resources: ");
-
-            int references = countLiveReferences(mResourceReferences);
-            for (ActivityResources activityResources : mActivityResourceReferences.values()) {
-                references += countLiveReferences(activityResources.activityResources);
-            }
-            pw.println(references);
-
-            pw.print("resource impls: ");
-            pw.println(countLiveReferences(mResourceImpls.values()));
-        }
-    }
-
     private Configuration generateConfig(@NonNull ResourcesKey key, @NonNull DisplayMetrics dm) {
         Configuration config;
         final boolean isDefaultDisplay = (key.mDisplayId == Display.DEFAULT_DISPLAY);
@@ -780,16 +630,28 @@
 
                 // We will create the ResourcesImpl object outside of holding this lock.
             }
+        }
 
-            // If we're here, we didn't find a suitable ResourcesImpl to use, so create one now.
-            ResourcesImpl resourcesImpl = createResourcesImpl(key);
-            if (resourcesImpl == null) {
-                return null;
+        // If we're here, we didn't find a suitable ResourcesImpl to use, so create one now.
+        ResourcesImpl resourcesImpl = createResourcesImpl(key);
+        if (resourcesImpl == null) {
+            return null;
+        }
+
+        synchronized (this) {
+            ResourcesImpl existingResourcesImpl = findResourcesImplForKeyLocked(key);
+            if (existingResourcesImpl != null) {
+                if (DEBUG) {
+                    Slog.d(TAG, "- got beat! existing impl=" + existingResourcesImpl
+                            + " new impl=" + resourcesImpl);
+                }
+                resourcesImpl.getAssets().close();
+                resourcesImpl = existingResourcesImpl;
+            } else {
+                // Add this ResourcesImpl to the cache.
+                mResourceImpls.put(key, new WeakReference<>(resourcesImpl));
             }
 
-            // Add this ResourcesImpl to the cache.
-            mResourceImpls.put(key, new WeakReference<>(resourcesImpl));
-
             final Resources resources;
             if (activityToken != null) {
                 resources = getOrCreateResourcesForActivityLocked(activityToken, classLoader,
diff --git a/core/java/android/app/Service.java b/core/java/android/app/Service.java
index ea0fd75..256c479 100644
--- a/core/java/android/app/Service.java
+++ b/core/java/android/app/Service.java
@@ -471,6 +471,14 @@
      * {@link #onStart} and returns either {@link #START_STICKY}
      * or {@link #START_STICKY_COMPATIBILITY}.
      * 
+     * <p>If you need your application to run on platform versions prior to API
+     * level 5, you can use the following model to handle the older {@link #onStart}
+     * callback in that case.  The <code>handleCommand</code> method is implemented by
+     * you as appropriate:
+     * 
+     * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/ForegroundService.java
+     *   start_compatibility}
+     *
      * <p class="caution">Note that the system calls this on your
      * service's main thread.  A service's main thread is the same
      * thread where UI operations take place for Activities running in the
@@ -679,10 +687,6 @@
      * {@link #startService(Intent)} first to tell the system it should keep the service running,
      * and then use this method to tell it to keep it running harder.</p>
      *
-     * <p>Apps targeting API {@link android.os.Build.VERSION_CODES#P} or later must request
-     * the permission {@link android.Manifest.permission#FOREGROUND_SERVICE} in order to use
-     * this API.</p>
-     *
      * @param id The identifier for this notification as per
      * {@link NotificationManager#notify(int, Notification)
      * NotificationManager.notify(int, Notification)}; must not be 0.
diff --git a/core/java/android/app/admin/DeviceAdminReceiver.java b/core/java/android/app/admin/DeviceAdminReceiver.java
index 28e845a..8c30fc4 100644
--- a/core/java/android/app/admin/DeviceAdminReceiver.java
+++ b/core/java/android/app/admin/DeviceAdminReceiver.java
@@ -19,6 +19,8 @@
 import android.accounts.AccountManager;
 import android.annotation.BroadcastBehavior;
 import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.annotation.SystemApi;
@@ -34,9 +36,6 @@
 import android.os.UserHandle;
 import android.security.KeyChain;
 
-import libcore.util.NonNull;
-import libcore.util.Nullable;
-
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 
@@ -928,29 +927,29 @@
             int networkLogsCount) {
     }
 
-     /**
-      * Called when a user or profile is created.
-      *
-      * <p>This callback is only applicable to device owners.
-      *
-      * @param context The running context as per {@link #onReceive}.
-      * @param intent The received intent as per {@link #onReceive}.
-      * @param newUser The {@link UserHandle} of the user that has just been added.
-      */
-     public void onUserAdded(Context context, Intent intent, UserHandle newUser) {
-     }
+    /**
+     * Called when a user or profile is created.
+     *
+     * <p>This callback is only applicable to device owners.
+     *
+     * @param context The running context as per {@link #onReceive}.
+     * @param intent The received intent as per {@link #onReceive}.
+     * @param newUser The {@link UserHandle} of the user that has just been added.
+     */
+    public void onUserAdded(Context context, Intent intent, @NonNull UserHandle newUser) {
+    }
 
-     /**
-      * Called when a user or profile is removed.
-      *
-      * <p>This callback is only applicable to device owners.
-      *
-      * @param context The running context as per {@link #onReceive}.
-      * @param intent The received intent as per {@link #onReceive}.
-      * @param removedUser The {@link UserHandle} of the user that has just been removed.
-      */
-     public void onUserRemoved(Context context, Intent intent, UserHandle removedUser) {
-     }
+    /**
+     * Called when a user or profile is removed.
+     *
+     * <p>This callback is only applicable to device owners.
+     *
+     * @param context The running context as per {@link #onReceive}.
+     * @param intent The received intent as per {@link #onReceive}.
+     * @param removedUser The {@link UserHandle} of the user that has just been removed.
+     */
+    public void onUserRemoved(Context context, Intent intent, @NonNull UserHandle removedUser) {
+    }
 
     /**
      * Called when a user or profile is started.
@@ -961,7 +960,7 @@
      * @param intent The received intent as per {@link #onReceive}.
      * @param startedUser The {@link UserHandle} of the user that has just been started.
      */
-    public void onUserStarted(Context context, Intent intent, UserHandle startedUser) {
+    public void onUserStarted(Context context, Intent intent, @NonNull UserHandle startedUser) {
     }
 
     /**
@@ -973,7 +972,7 @@
      * @param intent The received intent as per {@link #onReceive}.
      * @param stoppedUser The {@link UserHandle} of the user that has just been stopped.
      */
-    public void onUserStopped(Context context, Intent intent, UserHandle stoppedUser) {
+    public void onUserStopped(Context context, Intent intent, @NonNull UserHandle stoppedUser) {
     }
 
     /**
@@ -985,7 +984,7 @@
      * @param intent The received intent as per {@link #onReceive}.
      * @param switchedUser The {@link UserHandle} of the user that has just been switched to.
      */
-    public void onUserSwitched(Context context, Intent intent, UserHandle switchedUser) {
+    public void onUserSwitched(Context context, Intent intent, @NonNull UserHandle switchedUser) {
     }
 
     /**
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 77e118c..b29644b 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -3444,9 +3444,6 @@
 
     /**
      * Flag for {@link #wipeData(int)}: also erase the device's eUICC data.
-     *
-     * TODO(b/35851809): make this public.
-     * @hide
      */
     public static final int WIPE_EUICC = 0x0004;
 
diff --git a/core/java/android/app/assist/AssistStructure.java b/core/java/android/app/assist/AssistStructure.java
index 8f49bc1..0f1c249 100644
--- a/core/java/android/app/assist/AssistStructure.java
+++ b/core/java/android/app/assist/AssistStructure.java
@@ -24,6 +24,7 @@
 import android.util.Log;
 import android.util.Pair;
 import android.view.View;
+import android.view.View.AutofillImportance;
 import android.view.ViewRootImpl;
 import android.view.ViewStructure;
 import android.view.ViewStructure.HtmlInfo;
@@ -632,6 +633,7 @@
         int mMaxEms = -1;
         int mMaxLength = -1;
         @Nullable String mTextIdEntry;
+        @AutofillImportance int mImportantForAutofill;
 
         // POJO used to override some autofill-related values when the node is parcelized.
         // Not written to parcel.
@@ -733,6 +735,7 @@
                 mMaxEms = in.readInt();
                 mMaxLength = in.readInt();
                 mTextIdEntry = preader.readString();
+                mImportantForAutofill = in.readInt();
             }
             if ((flags&FLAGS_HAS_LARGE_COORDS) != 0) {
                 mX = in.readInt();
@@ -900,6 +903,7 @@
                 out.writeInt(mMaxEms);
                 out.writeInt(mMaxLength);
                 pwriter.writeString(mTextIdEntry);
+                out.writeInt(mImportantForAutofill);
             }
             if ((flags&FLAGS_HAS_LARGE_COORDS) != 0) {
                 out.writeInt(mX);
@@ -1512,6 +1516,16 @@
         public int getMaxTextLength() {
             return mMaxLength;
         }
+
+        /**
+         * Gets the {@link View#setImportantForAutofill(int) importantForAutofill mode} of
+         * the view associated with this node.
+         *
+         * <p>It's only relevant when the {@link AssistStructure} is used for autofill purposes.
+         */
+        public @AutofillImportance int getImportantForAutofill() {
+            return mImportantForAutofill;
+        }
     }
 
     /**
@@ -1844,6 +1858,11 @@
         }
 
         @Override
+        public void setImportantForAutofill(@AutofillImportance int mode) {
+            mNode.mImportantForAutofill = mode;
+        }
+
+        @Override
         public void setInputType(int inputType) {
             mNode.mInputType = inputType;
         }
@@ -2144,7 +2163,8 @@
                     + ", options=" + Arrays.toString(node.getAutofillOptions())
                     + ", hints=" + Arrays.toString(node.getAutofillHints())
                     + ", value=" + node.getAutofillValue()
-                    + ", sanitized=" + node.isSanitized());
+                    + ", sanitized=" + node.isSanitized()
+                    + ", importantFor=" + node.getImportantForAutofill());
         }
 
         final int NCHILDREN = node.getChildCount();
diff --git a/core/java/android/app/job/JobInfo.java b/core/java/android/app/job/JobInfo.java
index a1ad825c..ee13880 100644
--- a/core/java/android/app/job/JobInfo.java
+++ b/core/java/android/app/job/JobInfo.java
@@ -365,9 +365,7 @@
 
     /** @hide */
     public boolean isExemptedFromAppStandby() {
-        return ((flags & FLAG_EXEMPT_FROM_APP_STANDBY) != 0)
-                && !hasEarlyConstraint()
-                && !hasLateConstraint();
+        return ((flags & FLAG_EXEMPT_FROM_APP_STANDBY) != 0) && !isPeriodic();
     }
 
     /**
diff --git a/core/java/android/app/timezone/RulesManager.java b/core/java/android/app/timezone/RulesManager.java
index 0a38eb9..dc79256 100644
--- a/core/java/android/app/timezone/RulesManager.java
+++ b/core/java/android/app/timezone/RulesManager.java
@@ -68,6 +68,23 @@
     private static final String TAG = "timezone.RulesManager";
     private static final boolean DEBUG = false;
 
+    /**
+     * The action of the intent that the Android system will broadcast when a time zone rules update
+     * operation has been successfully staged  (i.e. to be applied next reboot) or unstaged.
+     *
+     * <p>See {@link #EXTRA_OPERATION_STAGED}
+     *
+     * <p>This is a protected intent that can only be sent by the system.
+     */
+    public static final String ACTION_RULES_UPDATE_OPERATION =
+            "com.android.intent.action.timezone.RULES_UPDATE_OPERATION";
+
+    /**
+     * The key for a boolean extra for the {@link #ACTION_RULES_UPDATE_OPERATION} intent used to
+     * indicate whether the operation was a "stage" or an "unstage".
+     */
+    public static final String EXTRA_OPERATION_STAGED = "staged";
+
     @Retention(RetentionPolicy.SOURCE)
     @IntDef(prefix = { "SUCCESS", "ERROR_" }, value = {
             SUCCESS,
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 15f3777..a738312 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -3671,10 +3671,8 @@
      *
      * @see #getSystemService(String)
      * @see android.telephony.euicc.EuiccManager
-     * TODO(b/35851809): Unhide this API.
-     * @hide
      */
-    public static final String EUICC_SERVICE = "euicc_service";
+    public static final String EUICC_SERVICE = "euicc";
 
     /**
      * Use with {@link #getSystemService(String)} to retrieve a
@@ -3682,10 +3680,10 @@
      *
      * @see #getSystemService(String)
      * @see android.telephony.euicc.EuiccCardManager
-     * TODO(b/35851809): Make this a SystemApi.
      * @hide
      */
-    public static final String EUICC_CARD_SERVICE = "euicc_card_service";
+    @SystemApi
+    public static final String EUICC_CARD_SERVICE = "euicc_card";
 
     /**
      * Use with {@link #getSystemService(String)} to retrieve a
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 12d4079..e7aead1 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -2498,6 +2498,9 @@
      * off, not sleeping).  Once the broadcast is complete, the final shutdown
      * will proceed and all unsaved data lost.  Apps will not normally need
      * to handle this, since the foreground activity will be paused as well.
+     * <p>As of {@link Build.VERSION_CODES#P} this broadcast is only sent to receivers registered
+     * through {@link Context#registerReceiver(BroadcastReceiver, IntentFilter)
+     * Context.registerReceiver}.
      *
      * <p class="note">This is a protected intent that can only be sent
      * by the system.
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 486c86c..aa8faf8 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -2108,8 +2108,6 @@
     /**
      * Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}: The device
      * supports embedded subscriptions on eUICCs.
-     * TODO(b/35851809): Make this public.
-     * @hide
      */
     @SdkConstant(SdkConstantType.FEATURE)
     public static final String FEATURE_TELEPHONY_EUICC = "android.hardware.telephony.euicc";
@@ -5067,6 +5065,7 @@
      * which market the package came from.
      *
      * @param packageName The name of the package to query
+     * @throws IllegalArgumentException if the given package name is not installed
      */
     public abstract String getInstallerPackageName(String packageName);
 
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 377942a..dda4167 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -54,7 +54,6 @@
 import android.content.pm.split.DefaultSplitAssetLoader;
 import android.content.pm.split.SplitAssetDependencyLoader;
 import android.content.pm.split.SplitAssetLoader;
-import android.content.res.ApkAssets;
 import android.content.res.AssetManager;
 import android.content.res.Configuration;
 import android.content.res.Resources;
@@ -1287,6 +1286,7 @@
      */
     @Deprecated
     public Package parseMonolithicPackage(File apkFile, int flags) throws PackageParserException {
+        final AssetManager assets = newConfiguredAssetManager();
         final PackageLite lite = parseMonolithicPackageLite(apkFile, flags);
         if (mOnlyCoreApps) {
             if (!lite.coreApp) {
@@ -1295,9 +1295,8 @@
             }
         }
 
-        final SplitAssetLoader assetLoader = new DefaultSplitAssetLoader(lite, flags);
         try {
-            final Package pkg = parseBaseApk(apkFile, assetLoader.getBaseAssetManager(), flags);
+            final Package pkg = parseBaseApk(apkFile, assets, flags);
             pkg.setCodePath(apkFile.getCanonicalPath());
             pkg.setUse32bitAbi(lite.use32bitAbi);
             return pkg;
@@ -1305,10 +1304,28 @@
             throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
                     "Failed to get path: " + apkFile, e);
         } finally {
-            IoUtils.closeQuietly(assetLoader);
+            IoUtils.closeQuietly(assets);
         }
     }
 
+    private static int loadApkIntoAssetManager(AssetManager assets, String apkPath, int flags)
+            throws PackageParserException {
+        if ((flags & PARSE_MUST_BE_APK) != 0 && !isApkPath(apkPath)) {
+            throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
+                    "Invalid package file: " + apkPath);
+        }
+
+        // The AssetManager guarantees uniqueness for asset paths, so if this asset path
+        // already exists in the AssetManager, addAssetPath will only return the cookie
+        // assigned to it.
+        int cookie = assets.addAssetPath(apkPath);
+        if (cookie == 0) {
+            throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
+                    "Failed adding asset path: " + apkPath);
+        }
+        return cookie;
+    }
+
     private Package parseBaseApk(File apkFile, AssetManager assets, int flags)
             throws PackageParserException {
         final String apkPath = apkFile.getAbsolutePath();
@@ -1324,15 +1341,13 @@
 
         if (DEBUG_JAR) Slog.d(TAG, "Scanning base APK: " + apkPath);
 
+        final int cookie = loadApkIntoAssetManager(assets, apkPath, flags);
+
+        Resources res = null;
         XmlResourceParser parser = null;
         try {
-            final int cookie = assets.findCookieForPath(apkPath);
-            if (cookie == 0) {
-                throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
-                        "Failed adding asset path: " + apkPath);
-            }
+            res = new Resources(assets, mMetrics, null);
             parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
-            final Resources res = new Resources(assets, mMetrics, null);
 
             final String[] outError = new String[1];
             final Package pkg = parseBaseApk(apkPath, res, parser, flags, outError);
@@ -1367,18 +1382,15 @@
 
         if (DEBUG_JAR) Slog.d(TAG, "Scanning split APK: " + apkPath);
 
+        final int cookie = loadApkIntoAssetManager(assets, apkPath, flags);
+
         final Resources res;
         XmlResourceParser parser = null;
         try {
-            // This must always succeed, as the path has been added to the AssetManager before.
-            final int cookie = assets.findCookieForPath(apkPath);
-            if (cookie == 0) {
-                throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
-                        "Failed adding asset path: " + apkPath);
-            }
-
-            parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
             res = new Resources(assets, mMetrics, null);
+            assets.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                    Build.VERSION.RESOURCES_SDK_INT);
+            parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
 
             final String[] outError = new String[1];
             pkg = parseSplitApk(pkg, res, parser, flags, splitIndex, outError);
@@ -1580,19 +1592,21 @@
             int flags) throws PackageParserException {
         final String apkPath = fd != null ? debugPathName : apkFile.getAbsolutePath();
 
+        AssetManager assets = null;
         XmlResourceParser parser = null;
         try {
-            final ApkAssets apkAssets;
-            try {
-                apkAssets = fd != null
-                        ? ApkAssets.loadFromFd(fd, debugPathName, false, false)
-                        : ApkAssets.loadFromPath(apkPath);
-            } catch (IOException e) {
+            assets = newConfiguredAssetManager();
+            int cookie = fd != null
+                    ? assets.addAssetFd(fd, debugPathName) : assets.addAssetPath(apkPath);
+            if (cookie == 0) {
                 throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
                         "Failed to parse " + apkPath);
             }
 
-            parser = apkAssets.openXml(ANDROID_MANIFEST_FILENAME);
+            final DisplayMetrics metrics = new DisplayMetrics();
+            metrics.setToDefaults();
+
+            parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
 
             final SigningDetails signingDetails;
             if ((flags & PARSE_COLLECT_CERTIFICATES) != 0) {
@@ -1619,7 +1633,7 @@
                     "Failed to parse " + apkPath, e);
         } finally {
             IoUtils.closeQuietly(parser);
-            // TODO(b/72056911): Implement and call close() on ApkAssets.
+            IoUtils.closeQuietly(assets);
         }
     }
 
diff --git a/core/java/android/content/pm/split/DefaultSplitAssetLoader.java b/core/java/android/content/pm/split/DefaultSplitAssetLoader.java
index 9e3a8f4..99eb470 100644
--- a/core/java/android/content/pm/split/DefaultSplitAssetLoader.java
+++ b/core/java/android/content/pm/split/DefaultSplitAssetLoader.java
@@ -15,13 +15,10 @@
  */
 package android.content.pm.split;
 
-import static android.content.pm.PackageManager.INSTALL_FAILED_INVALID_APK;
+import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_BAD_MANIFEST;
 import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_NOT_APK;
 
 import android.content.pm.PackageParser;
-import android.content.pm.PackageParser.PackageParserException;
-import android.content.pm.PackageParser.ParseFlags;
-import android.content.res.ApkAssets;
 import android.content.res.AssetManager;
 import android.os.Build;
 
@@ -29,8 +26,6 @@
 
 import libcore.io.IoUtils;
 
-import java.io.IOException;
-
 /**
  * Loads the base and split APKs into a single AssetManager.
  * @hide
@@ -38,66 +33,68 @@
 public class DefaultSplitAssetLoader implements SplitAssetLoader {
     private final String mBaseCodePath;
     private final String[] mSplitCodePaths;
-    private final @ParseFlags int mFlags;
+    private final int mFlags;
+
     private AssetManager mCachedAssetManager;
 
-    public DefaultSplitAssetLoader(PackageParser.PackageLite pkg, @ParseFlags int flags) {
+    public DefaultSplitAssetLoader(PackageParser.PackageLite pkg, int flags) {
         mBaseCodePath = pkg.baseCodePath;
         mSplitCodePaths = pkg.splitCodePaths;
         mFlags = flags;
     }
 
-    private static ApkAssets loadApkAssets(String path, @ParseFlags int flags)
-            throws PackageParserException {
-        if ((flags & PackageParser.PARSE_MUST_BE_APK) != 0 && !PackageParser.isApkPath(path)) {
-            throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
-                    "Invalid package file: " + path);
+    private static void loadApkIntoAssetManager(AssetManager assets, String apkPath, int flags)
+            throws PackageParser.PackageParserException {
+        if ((flags & PackageParser.PARSE_MUST_BE_APK) != 0 && !PackageParser.isApkPath(apkPath)) {
+            throw new PackageParser.PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
+                    "Invalid package file: " + apkPath);
         }
 
-        try {
-            return ApkAssets.loadFromPath(path);
-        } catch (IOException e) {
-            throw new PackageParserException(INSTALL_FAILED_INVALID_APK,
-                    "Failed to load APK at path " + path, e);
+        if (assets.addAssetPath(apkPath) == 0) {
+            throw new PackageParser.PackageParserException(
+                    INSTALL_PARSE_FAILED_BAD_MANIFEST,
+                    "Failed adding asset path: " + apkPath);
         }
     }
 
     @Override
-    public AssetManager getBaseAssetManager() throws PackageParserException {
+    public AssetManager getBaseAssetManager() throws PackageParser.PackageParserException {
         if (mCachedAssetManager != null) {
             return mCachedAssetManager;
         }
 
-        ApkAssets[] apkAssets = new ApkAssets[(mSplitCodePaths != null
-                ? mSplitCodePaths.length : 0) + 1];
+        AssetManager assets = new AssetManager();
+        try {
+            assets.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                    Build.VERSION.RESOURCES_SDK_INT);
+            loadApkIntoAssetManager(assets, mBaseCodePath, mFlags);
 
-        // Load the base.
-        int splitIdx = 0;
-        apkAssets[splitIdx++] = loadApkAssets(mBaseCodePath, mFlags);
+            if (!ArrayUtils.isEmpty(mSplitCodePaths)) {
+                for (String apkPath : mSplitCodePaths) {
+                    loadApkIntoAssetManager(assets, apkPath, mFlags);
+                }
+            }
 
-        // Load any splits.
-        if (!ArrayUtils.isEmpty(mSplitCodePaths)) {
-            for (String apkPath : mSplitCodePaths) {
-                apkAssets[splitIdx++] = loadApkAssets(apkPath, mFlags);
+            mCachedAssetManager = assets;
+            assets = null;
+            return mCachedAssetManager;
+        } finally {
+            if (assets != null) {
+                IoUtils.closeQuietly(assets);
             }
         }
-
-        AssetManager assets = new AssetManager();
-        assets.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                Build.VERSION.RESOURCES_SDK_INT);
-        assets.setApkAssets(apkAssets, false /*invalidateCaches*/);
-
-        mCachedAssetManager = assets;
-        return mCachedAssetManager;
     }
 
     @Override
-    public AssetManager getSplitAssetManager(int splitIdx) throws PackageParserException {
+    public AssetManager getSplitAssetManager(int splitIdx)
+            throws PackageParser.PackageParserException {
         return getBaseAssetManager();
     }
 
     @Override
     public void close() throws Exception {
-        IoUtils.closeQuietly(mCachedAssetManager);
+        if (mCachedAssetManager != null) {
+            IoUtils.closeQuietly(mCachedAssetManager);
+        }
     }
 }
diff --git a/core/java/android/content/pm/split/SplitAssetDependencyLoader.java b/core/java/android/content/pm/split/SplitAssetDependencyLoader.java
index 58eaabf..16023f0 100644
--- a/core/java/android/content/pm/split/SplitAssetDependencyLoader.java
+++ b/core/java/android/content/pm/split/SplitAssetDependencyLoader.java
@@ -15,21 +15,17 @@
  */
 package android.content.pm.split;
 
+import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_BAD_MANIFEST;
 import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_NOT_APK;
 
 import android.annotation.NonNull;
-import android.content.pm.PackageManager;
 import android.content.pm.PackageParser;
-import android.content.pm.PackageParser.PackageParserException;
-import android.content.pm.PackageParser.ParseFlags;
-import android.content.res.ApkAssets;
 import android.content.res.AssetManager;
 import android.os.Build;
 import android.util.SparseArray;
 
 import libcore.io.IoUtils;
 
-import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Collections;
 
@@ -38,15 +34,17 @@
  * is to be used when an application opts-in to isolated split loading.
  * @hide
  */
-public class SplitAssetDependencyLoader extends SplitDependencyLoader<PackageParserException>
+public class SplitAssetDependencyLoader
+        extends SplitDependencyLoader<PackageParser.PackageParserException>
         implements SplitAssetLoader {
     private final String[] mSplitPaths;
-    private final @ParseFlags int mFlags;
-    private final ApkAssets[][] mCachedSplitApks;
-    private final AssetManager[] mCachedAssetManagers;
+    private final int mFlags;
+
+    private String[][] mCachedPaths;
+    private AssetManager[] mCachedAssetManagers;
 
     public SplitAssetDependencyLoader(PackageParser.PackageLite pkg,
-            SparseArray<int[]> dependencies, @ParseFlags int flags) {
+            SparseArray<int[]> dependencies, int flags) {
         super(dependencies);
 
         // The base is inserted into index 0, so we need to shift all the splits by 1.
@@ -55,7 +53,7 @@
         System.arraycopy(pkg.splitCodePaths, 0, mSplitPaths, 1, pkg.splitCodePaths.length);
 
         mFlags = flags;
-        mCachedSplitApks = new ApkAssets[mSplitPaths.length][];
+        mCachedPaths = new String[mSplitPaths.length][];
         mCachedAssetManagers = new AssetManager[mSplitPaths.length];
     }
 
@@ -64,60 +62,58 @@
         return mCachedAssetManagers[splitIdx] != null;
     }
 
-    private static ApkAssets loadApkAssets(String path, @ParseFlags int flags)
-            throws PackageParserException {
-        if ((flags & PackageParser.PARSE_MUST_BE_APK) != 0 && !PackageParser.isApkPath(path)) {
-            throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
-                    "Invalid package file: " + path);
-        }
-
-        try {
-            return ApkAssets.loadFromPath(path);
-        } catch (IOException e) {
-            throw new PackageParserException(PackageManager.INSTALL_FAILED_INVALID_APK,
-                    "Failed to load APK at path " + path, e);
-        }
-    }
-
-    private static AssetManager createAssetManagerWithAssets(ApkAssets[] apkAssets) {
+    private static AssetManager createAssetManagerWithPaths(String[] assetPaths, int flags)
+            throws PackageParser.PackageParserException {
         final AssetManager assets = new AssetManager();
-        assets.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                Build.VERSION.RESOURCES_SDK_INT);
-        assets.setApkAssets(apkAssets, false /*invalidateCaches*/);
-        return assets;
+        try {
+            assets.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                    Build.VERSION.RESOURCES_SDK_INT);
+
+            for (String assetPath : assetPaths) {
+                if ((flags & PackageParser.PARSE_MUST_BE_APK) != 0 &&
+                        !PackageParser.isApkPath(assetPath)) {
+                    throw new PackageParser.PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
+                            "Invalid package file: " + assetPath);
+                }
+
+                if (assets.addAssetPath(assetPath) == 0) {
+                    throw new PackageParser.PackageParserException(
+                            INSTALL_PARSE_FAILED_BAD_MANIFEST,
+                            "Failed adding asset path: " + assetPath);
+                }
+            }
+            return assets;
+        } catch (Throwable e) {
+            IoUtils.closeQuietly(assets);
+            throw e;
+        }
     }
 
     @Override
     protected void constructSplit(int splitIdx, @NonNull int[] configSplitIndices,
-            int parentSplitIdx) throws PackageParserException {
-        final ArrayList<ApkAssets> assets = new ArrayList<>();
-
-        // Include parent ApkAssets.
+            int parentSplitIdx) throws PackageParser.PackageParserException {
+        final ArrayList<String> assetPaths = new ArrayList<>();
         if (parentSplitIdx >= 0) {
-            Collections.addAll(assets, mCachedSplitApks[parentSplitIdx]);
+            Collections.addAll(assetPaths, mCachedPaths[parentSplitIdx]);
         }
 
-        // Include this ApkAssets.
-        assets.add(loadApkAssets(mSplitPaths[splitIdx], mFlags));
-
-        // Load and include all config splits for this feature.
+        assetPaths.add(mSplitPaths[splitIdx]);
         for (int configSplitIdx : configSplitIndices) {
-            assets.add(loadApkAssets(mSplitPaths[configSplitIdx], mFlags));
+            assetPaths.add(mSplitPaths[configSplitIdx]);
         }
-
-        // Cache the results.
-        mCachedSplitApks[splitIdx] = assets.toArray(new ApkAssets[assets.size()]);
-        mCachedAssetManagers[splitIdx] = createAssetManagerWithAssets(mCachedSplitApks[splitIdx]);
+        mCachedPaths[splitIdx] = assetPaths.toArray(new String[assetPaths.size()]);
+        mCachedAssetManagers[splitIdx] = createAssetManagerWithPaths(mCachedPaths[splitIdx],
+                mFlags);
     }
 
     @Override
-    public AssetManager getBaseAssetManager() throws PackageParserException {
+    public AssetManager getBaseAssetManager() throws PackageParser.PackageParserException {
         loadDependenciesForSplit(0);
         return mCachedAssetManagers[0];
     }
 
     @Override
-    public AssetManager getSplitAssetManager(int idx) throws PackageParserException {
+    public AssetManager getSplitAssetManager(int idx) throws PackageParser.PackageParserException {
         // Since we insert the base at position 0, and PackageParser keeps splits separate from
         // the base, we need to adjust the index.
         loadDependenciesForSplit(idx + 1);
diff --git a/core/java/android/content/res/ApkAssets.java b/core/java/android/content/res/ApkAssets.java
deleted file mode 100644
index fd664bc..0000000
--- a/core/java/android/content/res/ApkAssets.java
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.content.res;
-
-import android.annotation.NonNull;
-
-import com.android.internal.annotations.GuardedBy;
-import com.android.internal.util.Preconditions;
-
-import java.io.FileDescriptor;
-import java.io.IOException;
-
-/**
- * The loaded, immutable, in-memory representation of an APK.
- *
- * The main implementation is native C++ and there is very little API surface exposed here. The APK
- * is mainly accessed via {@link AssetManager}.
- *
- * Since the ApkAssets instance is immutable, it can be reused and shared across AssetManagers,
- * making the creation of AssetManagers very cheap.
- * @hide
- */
-public final class ApkAssets {
-    @GuardedBy("this") private final long mNativePtr;
-    @GuardedBy("this") private StringBlock mStringBlock;
-
-    /**
-     * Creates a new ApkAssets instance from the given path on disk.
-     *
-     * @param path The path to an APK on disk.
-     * @return a new instance of ApkAssets.
-     * @throws IOException if a disk I/O error or parsing error occurred.
-     */
-    public static @NonNull ApkAssets loadFromPath(@NonNull String path) throws IOException {
-        return new ApkAssets(path, false /*system*/, false /*forceSharedLib*/, false /*overlay*/);
-    }
-
-    /**
-     * Creates a new ApkAssets instance from the given path on disk.
-     *
-     * @param path The path to an APK on disk.
-     * @param system When true, the APK is loaded as a system APK (framework).
-     * @return a new instance of ApkAssets.
-     * @throws IOException if a disk I/O error or parsing error occurred.
-     */
-    public static @NonNull ApkAssets loadFromPath(@NonNull String path, boolean system)
-            throws IOException {
-        return new ApkAssets(path, system, false /*forceSharedLib*/, false /*overlay*/);
-    }
-
-    /**
-     * Creates a new ApkAssets instance from the given path on disk.
-     *
-     * @param path The path to an APK on disk.
-     * @param system When true, the APK is loaded as a system APK (framework).
-     * @param forceSharedLibrary When true, any packages within the APK with package ID 0x7f are
-     *                           loaded as a shared library.
-     * @return a new instance of ApkAssets.
-     * @throws IOException if a disk I/O error or parsing error occurred.
-     */
-    public static @NonNull ApkAssets loadFromPath(@NonNull String path, boolean system,
-            boolean forceSharedLibrary) throws IOException {
-        return new ApkAssets(path, system, forceSharedLibrary, false /*overlay*/);
-    }
-
-    /**
-     * Creates a new ApkAssets instance from the given file descriptor. Not for use by applications.
-     *
-     * Performs a dup of the underlying fd, so you must take care of still closing
-     * the FileDescriptor yourself (and can do that whenever you want).
-     *
-     * @param fd The FileDescriptor of an open, readable APK.
-     * @param friendlyName The friendly name used to identify this ApkAssets when logging.
-     * @param system When true, the APK is loaded as a system APK (framework).
-     * @param forceSharedLibrary When true, any packages within the APK with package ID 0x7f are
-     *                           loaded as a shared library.
-     * @return a new instance of ApkAssets.
-     * @throws IOException if a disk I/O error or parsing error occurred.
-     */
-    public static @NonNull ApkAssets loadFromFd(@NonNull FileDescriptor fd,
-            @NonNull String friendlyName, boolean system, boolean forceSharedLibrary)
-            throws IOException {
-        return new ApkAssets(fd, friendlyName, system, forceSharedLibrary);
-    }
-
-    /**
-     * Creates a new ApkAssets instance from the IDMAP at idmapPath. The overlay APK path
-     * is encoded within the IDMAP.
-     *
-     * @param idmapPath Path to the IDMAP of an overlay APK.
-     * @param system When true, the APK is loaded as a system APK (framework).
-     * @return a new instance of ApkAssets.
-     * @throws IOException if a disk I/O error or parsing error occurred.
-     */
-    public static @NonNull ApkAssets loadOverlayFromPath(@NonNull String idmapPath, boolean system)
-            throws IOException {
-        return new ApkAssets(idmapPath, system, false /*forceSharedLibrary*/, true /*overlay*/);
-    }
-
-    private ApkAssets(@NonNull String path, boolean system, boolean forceSharedLib, boolean overlay)
-            throws IOException {
-        Preconditions.checkNotNull(path, "path");
-        mNativePtr = nativeLoad(path, system, forceSharedLib, overlay);
-        mStringBlock = new StringBlock(nativeGetStringBlock(mNativePtr), true /*useSparse*/);
-    }
-
-    private ApkAssets(@NonNull FileDescriptor fd, @NonNull String friendlyName, boolean system,
-            boolean forceSharedLib) throws IOException {
-        Preconditions.checkNotNull(fd, "fd");
-        Preconditions.checkNotNull(friendlyName, "friendlyName");
-        mNativePtr = nativeLoadFromFd(fd, friendlyName, system, forceSharedLib);
-        mStringBlock = new StringBlock(nativeGetStringBlock(mNativePtr), true /*useSparse*/);
-    }
-
-    @NonNull String getAssetPath() {
-        synchronized (this) {
-            return nativeGetAssetPath(mNativePtr);
-        }
-    }
-
-    CharSequence getStringFromPool(int idx) {
-        synchronized (this) {
-            return mStringBlock.get(idx);
-        }
-    }
-
-    /**
-     * Retrieve a parser for a compiled XML file. This is associated with a single APK and
-     * <em>NOT</em> a full AssetManager. This means that shared-library references will not be
-     * dynamically assigned runtime package IDs.
-     *
-     * @param fileName The path to the file within the APK.
-     * @return An XmlResourceParser.
-     * @throws IOException if the file was not found or an error occurred retrieving it.
-     */
-    public @NonNull XmlResourceParser openXml(@NonNull String fileName) throws IOException {
-        Preconditions.checkNotNull(fileName, "fileName");
-        synchronized (this) {
-            long nativeXmlPtr = nativeOpenXml(mNativePtr, fileName);
-            try (XmlBlock block = new XmlBlock(null, nativeXmlPtr)) {
-                XmlResourceParser parser = block.newParser();
-                // If nativeOpenXml doesn't throw, it will always return a valid native pointer,
-                // which makes newParser always return non-null. But let's be paranoid.
-                if (parser == null) {
-                    throw new AssertionError("block.newParser() returned a null parser");
-                }
-                return parser;
-            }
-        }
-    }
-
-    /**
-     * Returns false if the underlying APK was changed since this ApkAssets was loaded.
-     */
-    public boolean isUpToDate() {
-        synchronized (this) {
-            return nativeIsUpToDate(mNativePtr);
-        }
-    }
-
-    @Override
-    protected void finalize() throws Throwable {
-        nativeDestroy(mNativePtr);
-    }
-
-    private static native long nativeLoad(
-            @NonNull String path, boolean system, boolean forceSharedLib, boolean overlay)
-            throws IOException;
-    private static native long nativeLoadFromFd(@NonNull FileDescriptor fd,
-            @NonNull String friendlyName, boolean system, boolean forceSharedLib)
-            throws IOException;
-    private static native void nativeDestroy(long ptr);
-    private static native @NonNull String nativeGetAssetPath(long ptr);
-    private static native long nativeGetStringBlock(long ptr);
-    private static native boolean nativeIsUpToDate(long ptr);
-    private static native long nativeOpenXml(long ptr, @NonNull String fileName) throws IOException;
-}
diff --git a/core/java/android/content/res/AssetManager.java b/core/java/android/content/res/AssetManager.java
index bb90700..5f8a34d 100644
--- a/core/java/android/content/res/AssetManager.java
+++ b/core/java/android/content/res/AssetManager.java
@@ -18,11 +18,9 @@
 
 import android.annotation.AnyRes;
 import android.annotation.ArrayRes;
-import android.annotation.AttrRes;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.StringRes;
-import android.annotation.StyleRes;
 import android.content.pm.ActivityInfo;
 import android.content.res.Configuration.NativeConfig;
 import android.os.ParcelFileDescriptor;
@@ -31,19 +29,11 @@
 import android.util.TypedValue;
 
 import com.android.internal.annotations.GuardedBy;
-import com.android.internal.util.Preconditions;
 
-import libcore.io.IoUtils;
-
-import java.io.BufferedReader;
-import java.io.FileInputStream;
+import java.io.FileDescriptor;
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.nio.channels.FileLock;
-import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.HashMap;
 
 /**
@@ -54,19 +44,7 @@
  * bytes.
  */
 public final class AssetManager implements AutoCloseable {
-    private static final String TAG = "AssetManager";
-    private static final boolean DEBUG_REFS = false;
-
-    private static final String FRAMEWORK_APK_PATH = "/system/framework/framework-res.apk";
-
-    private static final Object sSync = new Object();
-
-    private static final ApkAssets[] sEmptyApkAssets = new ApkAssets[0];
-
-    // Not private for LayoutLib's BridgeAssetManager.
-    @GuardedBy("sSync") static AssetManager sSystem = null;
-
-    @GuardedBy("sSync") private static ApkAssets[] sSystemApkAssets = new ApkAssets[0];
+    /* modes used when opening an asset */
 
     /**
      * Mode for {@link #open(String, int)}: no specific information about how
@@ -89,335 +67,88 @@
      */
     public static final int ACCESS_BUFFER = 3;
 
-    @GuardedBy("this") private final TypedValue mValue = new TypedValue();
-    @GuardedBy("this") private final long[] mOffsets = new long[2];
+    private static final String TAG = "AssetManager";
+    private static final boolean localLOGV = false || false;
+    
+    private static final boolean DEBUG_REFS = false;
+    
+    private static final Object sSync = new Object();
+    /*package*/ static AssetManager sSystem = null;
 
-    // Pointer to native implementation, stuffed inside a long.
-    @GuardedBy("this") private long mObject;
+    private final TypedValue mValue = new TypedValue();
+    private final long[] mOffsets = new long[2];
+    
+    // For communication with native code.
+    private long mObject;
 
-    // The loaded asset paths.
-    @GuardedBy("this") private ApkAssets[] mApkAssets;
-
-    // Debug/reference counting implementation.
-    @GuardedBy("this") private boolean mOpen = true;
-    @GuardedBy("this") private int mNumRefs = 1;
-    @GuardedBy("this") private HashMap<Long, RuntimeException> mRefStacks;
-
+    private StringBlock mStringBlocks[] = null;
+    
+    private int mNumRefs = 1;
+    private boolean mOpen = true;
+    private HashMap<Long, RuntimeException> mRefStacks;
+ 
     /**
      * Create a new AssetManager containing only the basic system assets.
      * Applications will not generally use this method, instead retrieving the
      * appropriate asset manager with {@link Resources#getAssets}.    Not for
      * use by applications.
-     * @hide
+     * {@hide}
      */
     public AssetManager() {
-        final ApkAssets[] assets;
-        synchronized (sSync) {
-            createSystemAssetsInZygoteLocked();
-            assets = sSystemApkAssets;
-        }
-
-        mObject = nativeCreate();
-        if (DEBUG_REFS) {
-            mNumRefs = 0;
-            incRefsLocked(hashCode());
-        }
-
-        // Always set the framework resources.
-        setApkAssets(assets, false /*invalidateCaches*/);
-    }
-
-    /**
-     * Private constructor that doesn't call ensureSystemAssets.
-     * Used for the creation of system assets.
-     */
-    @SuppressWarnings("unused")
-    private AssetManager(boolean sentinel) {
-        mObject = nativeCreate();
-        if (DEBUG_REFS) {
-            mNumRefs = 0;
-            incRefsLocked(hashCode());
-        }
-    }
-
-    /**
-     * This must be called from Zygote so that system assets are shared by all applications.
-     */
-    @GuardedBy("sSync")
-    private static void createSystemAssetsInZygoteLocked() {
-        if (sSystem != null) {
-            return;
-        }
-
-        // Make sure that all IDMAPs are up to date.
-        nativeVerifySystemIdmaps();
-
-        try {
-            ArrayList<ApkAssets> apkAssets = new ArrayList<>();
-            apkAssets.add(ApkAssets.loadFromPath(FRAMEWORK_APK_PATH, true /*system*/));
-            loadStaticRuntimeOverlays(apkAssets);
-
-            sSystemApkAssets = apkAssets.toArray(new ApkAssets[apkAssets.size()]);
-            sSystem = new AssetManager(true /*sentinel*/);
-            sSystem.setApkAssets(sSystemApkAssets, false /*invalidateCaches*/);
-        } catch (IOException e) {
-            throw new IllegalStateException("Failed to create system AssetManager", e);
-        }
-    }
-
-    /**
-     * Loads the static runtime overlays declared in /data/resource-cache/overlays.list.
-     * Throws an exception if the file is corrupt or if loading the APKs referenced by the file
-     * fails. Returns quietly if the overlays.list file doesn't exist.
-     * @param outApkAssets The list to fill with the loaded ApkAssets.
-     */
-    private static void loadStaticRuntimeOverlays(ArrayList<ApkAssets> outApkAssets)
-            throws IOException {
-        final FileInputStream fis;
-        try {
-            fis = new FileInputStream("/data/resource-cache/overlays.list");
-        } catch (FileNotFoundException e) {
-            // We might not have any overlays, this is fine. We catch here since ApkAssets
-            // loading can also fail with the same exception, which we would want to propagate.
-            Log.i(TAG, "no overlays.list file found");
-            return;
-        }
-
-        try {
-            // Acquire a lock so that any idmap scanning doesn't impact the current set.
-            // The order of this try-with-resources block matters. We must release the lock, and
-            // then close the file streams when exiting the block.
-            try (final BufferedReader br = new BufferedReader(new InputStreamReader(fis));
-                 final FileLock flock = fis.getChannel().lock(0, Long.MAX_VALUE, true /*shared*/)) {
-                for (String line; (line = br.readLine()) != null; ) {
-                    final String idmapPath = line.split(" ")[1];
-                    outApkAssets.add(ApkAssets.loadOverlayFromPath(idmapPath, true /*system*/));
-                }
+        synchronized (this) {
+            if (DEBUG_REFS) {
+                mNumRefs = 0;
+                incRefsLocked(this.hashCode());
             }
-        } finally {
-            // When BufferedReader is closed above, FileInputStream is closed as well. But let's be
-            // paranoid.
-            IoUtils.closeQuietly(fis);
+            init(false);
+            if (localLOGV) Log.v(TAG, "New asset manager: " + this);
+            ensureSystemAssets();
         }
     }
 
+    private static void ensureSystemAssets() {
+        synchronized (sSync) {
+            if (sSystem == null) {
+                AssetManager system = new AssetManager(true);
+                system.makeStringBlocks(null);
+                sSystem = system;
+            }
+        }
+    }
+    
+    private AssetManager(boolean isSystem) {
+        if (DEBUG_REFS) {
+            synchronized (this) {
+                mNumRefs = 0;
+                incRefsLocked(this.hashCode());
+            }
+        }
+        init(true);
+        if (localLOGV) Log.v(TAG, "New asset manager: " + this);
+    }
+
     /**
      * Return a global shared asset manager that provides access to only
      * system assets (no application assets).
-     * @hide
+     * {@hide}
      */
     public static AssetManager getSystem() {
-        synchronized (sSync) {
-            createSystemAssetsInZygoteLocked();
-            return sSystem;
-        }
+        ensureSystemAssets();
+        return sSystem;
     }
 
     /**
      * Close this asset manager.
      */
-    @Override
     public void close() {
-        synchronized (this) {
-            if (!mOpen) {
-                return;
-            }
-
-            mOpen = false;
-            decRefsLocked(hashCode());
-        }
-    }
-
-    /**
-     * Changes the asset paths in this AssetManager. This replaces the {@link #addAssetPath(String)}
-     * family of methods.
-     *
-     * @param apkAssets The new set of paths.
-     * @param invalidateCaches Whether to invalidate any caches. This should almost always be true.
-     *                         Set this to false if you are appending new resources
-     *                         (not new configurations).
-     * @hide
-     */
-    public void setApkAssets(@NonNull ApkAssets[] apkAssets, boolean invalidateCaches) {
-        Preconditions.checkNotNull(apkAssets, "apkAssets");
-
-        // Copy the apkAssets, but prepend the system assets (framework + overlays).
-        final ApkAssets[] newApkAssets = new ApkAssets[apkAssets.length + sSystemApkAssets.length];
-        System.arraycopy(sSystemApkAssets, 0, newApkAssets, 0, sSystemApkAssets.length);
-        System.arraycopy(apkAssets, 0, newApkAssets, sSystemApkAssets.length, apkAssets.length);
-
-        synchronized (this) {
-            ensureOpenLocked();
-            mApkAssets = newApkAssets;
-            nativeSetApkAssets(mObject, mApkAssets, invalidateCaches);
-            if (invalidateCaches) {
-                // Invalidate all caches.
-                invalidateCachesLocked(-1);
-            }
-        }
-    }
-
-    /**
-     * Invalidates the caches in this AssetManager according to the bitmask `diff`.
-     *
-     * @param diff The bitmask of changes generated by {@link Configuration#diff(Configuration)}.
-     * @see ActivityInfo.Config
-     */
-    private void invalidateCachesLocked(int diff) {
-        // TODO(adamlesinski): Currently there are no caches to invalidate in Java code.
-    }
-
-    /**
-     * Returns the set of ApkAssets loaded by this AssetManager. If the AssetManager is closed, this
-     * returns a 0-length array.
-     * @hide
-     */
-    public @NonNull ApkAssets[] getApkAssets() {
-        synchronized (this) {
+        synchronized(this) {
+            //System.out.println("Release: num=" + mNumRefs
+            //                   + ", released=" + mReleased);
             if (mOpen) {
-                return mApkAssets;
+                mOpen = false;
+                decRefsLocked(this.hashCode());
             }
         }
-        return sEmptyApkAssets;
-    }
-
-    /**
-     * Returns a cookie for use with the other APIs of AssetManager.
-     * @return 0 if the path was not found, otherwise a positive integer cookie representing
-     * this path in the AssetManager.
-     * @hide
-     */
-    public int findCookieForPath(@NonNull String path) {
-        Preconditions.checkNotNull(path, "path");
-        synchronized (this) {
-            ensureValidLocked();
-            final int count = mApkAssets.length;
-            for (int i = 0; i < count; i++) {
-                if (path.equals(mApkAssets[i].getAssetPath())) {
-                    return i + 1;
-                }
-            }
-        }
-        return 0;
-    }
-
-    /**
-     * @deprecated Use {@link #setApkAssets(ApkAssets[], boolean)}
-     * @hide
-     */
-    @Deprecated
-    public int addAssetPath(String path) {
-        return addAssetPathInternal(path, false /*overlay*/, false /*appAsLib*/);
-    }
-
-    /**
-     * @deprecated Use {@link #setApkAssets(ApkAssets[], boolean)}
-     * @hide
-     */
-    @Deprecated
-    public int addAssetPathAsSharedLibrary(String path) {
-        return addAssetPathInternal(path, false /*overlay*/, true /*appAsLib*/);
-    }
-
-    /**
-     * @deprecated Use {@link #setApkAssets(ApkAssets[], boolean)}
-     * @hide
-     */
-    @Deprecated
-    public int addOverlayPath(String path) {
-        return addAssetPathInternal(path, true /*overlay*/, false /*appAsLib*/);
-    }
-
-    private int addAssetPathInternal(String path, boolean overlay, boolean appAsLib) {
-        Preconditions.checkNotNull(path, "path");
-        synchronized (this) {
-            ensureOpenLocked();
-            final int count = mApkAssets.length;
-            for (int i = 0; i < count; i++) {
-                if (mApkAssets[i].getAssetPath().equals(path)) {
-                    return i + 1;
-                }
-            }
-
-            final ApkAssets assets;
-            try {
-                if (overlay) {
-                    // TODO(b/70343104): This hardcoded path will be removed once
-                    // addAssetPathInternal is deleted.
-                    final String idmapPath = "/data/resource-cache/"
-                            + path.substring(1).replace('/', '@')
-                            + "@idmap";
-                    assets = ApkAssets.loadOverlayFromPath(idmapPath, false /*system*/);
-                } else {
-                    assets = ApkAssets.loadFromPath(path, false /*system*/, appAsLib);
-                }
-            } catch (IOException e) {
-                return 0;
-            }
-
-            final ApkAssets[] newApkAssets = Arrays.copyOf(mApkAssets, count + 1);
-            newApkAssets[count] = assets;
-            setApkAssets(newApkAssets, true);
-            return count + 1;
-        }
-    }
-
-    /**
-     * Ensures that the native implementation has not been destroyed.
-     * The AssetManager may have been closed, but references to it still exist
-     * and therefore the native implementation is not destroyed.
-     */
-    @GuardedBy("this")
-    private void ensureValidLocked() {
-        if (mObject == 0) {
-            throw new RuntimeException("AssetManager has been destroyed");
-        }
-    }
-
-    /**
-     * Ensures that the AssetManager has not been explicitly closed. If this method passes,
-     * then this implies that ensureValidLocked() also passes.
-     */
-    @GuardedBy("this")
-    private void ensureOpenLocked() {
-        // If mOpen is true, this implies that mObject != 0.
-        if (!mOpen) {
-            throw new RuntimeException("AssetManager has been closed");
-        }
-    }
-
-    /**
-     * Populates {@code outValue} with the data associated a particular
-     * resource identifier for the current configuration.
-     *
-     * @param resId the resource identifier to load
-     * @param densityDpi the density bucket for which to load the resource
-     * @param outValue the typed value in which to put the data
-     * @param resolveRefs {@code true} to resolve references, {@code false}
-     *                    to leave them unresolved
-     * @return {@code true} if the data was loaded into {@code outValue},
-     *         {@code false} otherwise
-     */
-    boolean getResourceValue(@AnyRes int resId, int densityDpi, @NonNull TypedValue outValue,
-            boolean resolveRefs) {
-        Preconditions.checkNotNull(outValue, "outValue");
-        synchronized (this) {
-            ensureValidLocked();
-            final int cookie = nativeGetResourceValue(
-                    mObject, resId, (short) densityDpi, outValue, resolveRefs);
-            if (cookie <= 0) {
-                return false;
-            }
-
-            // Convert the changing configurations flags populated by native code.
-            outValue.changingConfigurations = ActivityInfo.activityInfoConfigNativeToJava(
-                    outValue.changingConfigurations);
-
-            if (outValue.type == TypedValue.TYPE_STRING) {
-                outValue.string = mApkAssets[cookie - 1].getStringFromPool(outValue.data);
-            }
-            return true;
-        }
     }
 
     /**
@@ -427,7 +158,8 @@
      * @param resId the resource identifier to load
      * @return the string value, or {@code null}
      */
-    @Nullable CharSequence getResourceText(@StringRes int resId) {
+    @Nullable
+    final CharSequence getResourceText(@StringRes int resId) {
         synchronized (this) {
             final TypedValue outValue = mValue;
             if (getResourceValue(resId, 0, outValue, true)) {
@@ -442,15 +174,15 @@
      * identifier for the current configuration.
      *
      * @param resId the resource identifier to load
-     * @param bagEntryId the index into the bag to load
+     * @param bagEntryId
      * @return the string value, or {@code null}
      */
-    @Nullable CharSequence getResourceBagText(@StringRes int resId, int bagEntryId) {
+    @Nullable
+    final CharSequence getResourceBagText(@StringRes int resId, int bagEntryId) {
         synchronized (this) {
-            ensureValidLocked();
             final TypedValue outValue = mValue;
-            final int cookie = nativeGetResourceBagValue(mObject, resId, bagEntryId, outValue);
-            if (cookie <= 0) {
+            final int block = loadResourceBagValue(resId, bagEntryId, outValue, true);
+            if (block < 0) {
                 return null;
             }
 
@@ -459,49 +191,12 @@
                     outValue.changingConfigurations);
 
             if (outValue.type == TypedValue.TYPE_STRING) {
-                return mApkAssets[cookie - 1].getStringFromPool(outValue.data);
+                return mStringBlocks[block].get(outValue.data);
             }
             return outValue.coerceToString();
         }
     }
 
-    int getResourceArraySize(@ArrayRes int resId) {
-        synchronized (this) {
-            ensureValidLocked();
-            return nativeGetResourceArraySize(mObject, resId);
-        }
-    }
-
-    /**
-     * Populates `outData` with array elements of `resId`. `outData` is normally
-     * used with
-     * {@link TypedArray}.
-     *
-     * Each logical element in `outData` is {@link TypedArray#STYLE_NUM_ENTRIES}
-     * long,
-     * with the indices of the data representing the type, value, asset cookie,
-     * resource ID,
-     * configuration change mask, and density of the element.
-     *
-     * @param resId The resource ID of an array resource.
-     * @param outData The array to populate with data.
-     * @return The length of the array.
-     *
-     * @see TypedArray#STYLE_TYPE
-     * @see TypedArray#STYLE_DATA
-     * @see TypedArray#STYLE_ASSET_COOKIE
-     * @see TypedArray#STYLE_RESOURCE_ID
-     * @see TypedArray#STYLE_CHANGING_CONFIGURATIONS
-     * @see TypedArray#STYLE_DENSITY
-     */
-    int getResourceArray(@ArrayRes int resId, @NonNull int[] outData) {
-        Preconditions.checkNotNull(outData, "outData");
-        synchronized (this) {
-            ensureValidLocked();
-            return nativeGetResourceArray(mObject, resId, outData);
-        }
-    }
-
     /**
      * Retrieves the string array associated with a particular resource
      * identifier for the current configuration.
@@ -509,10 +204,39 @@
      * @param resId the resource identifier of the string array
      * @return the string array, or {@code null}
      */
-    @Nullable String[] getResourceStringArray(@ArrayRes int resId) {
+    @Nullable
+    final String[] getResourceStringArray(@ArrayRes int resId) {
+        return getArrayStringResource(resId);
+    }
+
+    /**
+     * Populates {@code outValue} with the data associated a particular
+     * resource identifier for the current configuration.
+     *
+     * @param resId the resource identifier to load
+     * @param densityDpi the density bucket for which to load the resource
+     * @param outValue the typed value in which to put the data
+     * @param resolveRefs {@code true} to resolve references, {@code false}
+     *                    to leave them unresolved
+     * @return {@code true} if the data was loaded into {@code outValue},
+     *         {@code false} otherwise
+     */
+    final boolean getResourceValue(@AnyRes int resId, int densityDpi, @NonNull TypedValue outValue,
+            boolean resolveRefs) {
         synchronized (this) {
-            ensureValidLocked();
-            return nativeGetResourceStringArray(mObject, resId);
+            final int block = loadResourceValue(resId, (short) densityDpi, outValue, resolveRefs);
+            if (block < 0) {
+                return false;
+            }
+
+            // Convert the changing configurations flags populated by native code.
+            outValue.changingConfigurations = ActivityInfo.activityInfoConfigNativeToJava(
+                    outValue.changingConfigurations);
+
+            if (outValue.type == TypedValue.TYPE_STRING) {
+                outValue.string = mStringBlocks[block].get(outValue.data);
+            }
+            return true;
         }
     }
 
@@ -522,48 +246,26 @@
      *
      * @param resId the resource id of the string array
      */
-    @Nullable CharSequence[] getResourceTextArray(@ArrayRes int resId) {
+    final @Nullable CharSequence[] getResourceTextArray(@ArrayRes int resId) {
         synchronized (this) {
-            ensureValidLocked();
-            final int[] rawInfoArray = nativeGetResourceStringArrayInfo(mObject, resId);
+            final int[] rawInfoArray = getArrayStringInfo(resId);
             if (rawInfoArray == null) {
                 return null;
             }
-
             final int rawInfoArrayLen = rawInfoArray.length;
             final int infoArrayLen = rawInfoArrayLen / 2;
+            int block;
+            int index;
             final CharSequence[] retArray = new CharSequence[infoArrayLen];
             for (int i = 0, j = 0; i < rawInfoArrayLen; i = i + 2, j++) {
-                int cookie = rawInfoArray[i];
-                int index = rawInfoArray[i + 1];
-                retArray[j] = (index >= 0 && cookie > 0)
-                        ? mApkAssets[cookie - 1].getStringFromPool(index) : null;
+                block = rawInfoArray[i];
+                index = rawInfoArray[i + 1];
+                retArray[j] = index >= 0 ? mStringBlocks[block].get(index) : null;
             }
             return retArray;
         }
     }
 
-    @Nullable int[] getResourceIntArray(@ArrayRes int resId) {
-        synchronized (this) {
-            ensureValidLocked();
-            return nativeGetResourceIntArray(mObject, resId);
-        }
-    }
-
-    /**
-     * Get the attributes for a style resource. These are the &lt;item&gt;
-     * elements in
-     * a &lt;style&gt; resource.
-     * @param resId The resource ID of the style
-     * @return An array of attribute IDs.
-     */
-    @AttrRes int[] getStyleAttributes(@StyleRes int resId) {
-        synchronized (this) {
-            ensureValidLocked();
-            return nativeGetStyleAttributes(mObject, resId);
-        }
-    }
-
     /**
      * Populates {@code outValue} with the data associated with a particular
      * resource identifier for the current configuration. Resolves theme
@@ -577,88 +279,73 @@
      * @return {@code true} if the data was loaded into {@code outValue},
      *         {@code false} otherwise
      */
-    boolean getThemeValue(long theme, @AnyRes int resId, @NonNull TypedValue outValue,
+    final boolean getThemeValue(long theme, @AnyRes int resId, @NonNull TypedValue outValue,
             boolean resolveRefs) {
-        Preconditions.checkNotNull(outValue, "outValue");
+        final int block = loadThemeAttributeValue(theme, resId, outValue, resolveRefs);
+        if (block < 0) {
+            return false;
+        }
+
+        // Convert the changing configurations flags populated by native code.
+        outValue.changingConfigurations = ActivityInfo.activityInfoConfigNativeToJava(
+                outValue.changingConfigurations);
+
+        if (outValue.type == TypedValue.TYPE_STRING) {
+            final StringBlock[] blocks = ensureStringBlocks();
+            outValue.string = blocks[block].get(outValue.data);
+        }
+        return true;
+    }
+
+    /**
+     * Ensures the string blocks are loaded.
+     *
+     * @return the string blocks
+     */
+    @NonNull
+    final StringBlock[] ensureStringBlocks() {
         synchronized (this) {
-            ensureValidLocked();
-            final int cookie = nativeThemeGetAttributeValue(mObject, theme, resId, outValue,
-                    resolveRefs);
-            if (cookie <= 0) {
-                return false;
+            if (mStringBlocks == null) {
+                makeStringBlocks(sSystem.mStringBlocks);
             }
+            return mStringBlocks;
+        }
+    }
 
-            // Convert the changing configurations flags populated by native code.
-            outValue.changingConfigurations = ActivityInfo.activityInfoConfigNativeToJava(
-                    outValue.changingConfigurations);
-
-            if (outValue.type == TypedValue.TYPE_STRING) {
-                outValue.string = mApkAssets[cookie - 1].getStringFromPool(outValue.data);
+    /*package*/ final void makeStringBlocks(StringBlock[] seed) {
+        final int seedNum = (seed != null) ? seed.length : 0;
+        final int num = getStringBlockCount();
+        mStringBlocks = new StringBlock[num];
+        if (localLOGV) Log.v(TAG, "Making string blocks for " + this
+                + ": " + num);
+        for (int i=0; i<num; i++) {
+            if (i < seedNum) {
+                mStringBlocks[i] = seed[i];
+            } else {
+                mStringBlocks[i] = new StringBlock(getNativeStringBlock(i), true);
             }
-            return true;
         }
     }
 
-    void dumpTheme(long theme, int priority, String tag, String prefix) {
+    /*package*/ final CharSequence getPooledStringForCookie(int cookie, int id) {
         synchronized (this) {
-            ensureValidLocked();
-            nativeThemeDump(mObject, theme, priority, tag, prefix);
+            // Cookies map to string blocks starting at 1.
+            return mStringBlocks[cookie - 1].get(id);
         }
     }
 
-    @Nullable String getResourceName(@AnyRes int resId) {
-        synchronized (this) {
-            ensureValidLocked();
-            return nativeGetResourceName(mObject, resId);
-        }
-    }
-
-    @Nullable String getResourcePackageName(@AnyRes int resId) {
-        synchronized (this) {
-            ensureValidLocked();
-            return nativeGetResourcePackageName(mObject, resId);
-        }
-    }
-
-    @Nullable String getResourceTypeName(@AnyRes int resId) {
-        synchronized (this) {
-            ensureValidLocked();
-            return nativeGetResourceTypeName(mObject, resId);
-        }
-    }
-
-    @Nullable String getResourceEntryName(@AnyRes int resId) {
-        synchronized (this) {
-            ensureValidLocked();
-            return nativeGetResourceEntryName(mObject, resId);
-        }
-    }
-
-    @AnyRes int getResourceIdentifier(@NonNull String name, @Nullable String defType,
-            @Nullable String defPackage) {
-        synchronized (this) {
-            ensureValidLocked();
-            // name is checked in JNI.
-            return nativeGetResourceIdentifier(mObject, name, defType, defPackage);
-        }
-    }
-
-    CharSequence getPooledStringForCookie(int cookie, int id) {
-        // Cookies map to ApkAssets starting at 1.
-        return getApkAssets()[cookie - 1].getStringFromPool(id);
-    }
-
     /**
      * Open an asset using ACCESS_STREAMING mode.  This provides access to
      * files that have been bundled with an application as assets -- that is,
      * files placed in to the "assets" directory.
      * 
-     * @param fileName The name of the asset to open.  This name can be hierarchical.
+     * @param fileName The name of the asset to open.  This name can be
+     *                 hierarchical.
      * 
      * @see #open(String, int)
      * @see #list
      */
-    public @NonNull InputStream open(@NonNull String fileName) throws IOException {
+    public final InputStream open(String fileName) throws IOException {
         return open(fileName, ACCESS_STREAMING);
     }
 
@@ -668,7 +355,8 @@
      * with an application as assets -- that is, files placed in to the
      * "assets" directory.
      * 
-     * @param fileName The name of the asset to open.  This name can be hierarchical.
+     * @param fileName The name of the asset to open.  This name can be
+     *                 hierarchical.
      * @param accessMode Desired access mode for retrieving the data.
      * 
      * @see #ACCESS_UNKNOWN
@@ -678,40 +366,34 @@
      * @see #open(String)
      * @see #list
      */
-    public @NonNull InputStream open(@NonNull String fileName, int accessMode) throws IOException {
-        Preconditions.checkNotNull(fileName, "fileName");
+    public final InputStream open(String fileName, int accessMode)
+        throws IOException {
         synchronized (this) {
-            ensureOpenLocked();
-            final long asset = nativeOpenAsset(mObject, fileName, accessMode);
-            if (asset == 0) {
-                throw new FileNotFoundException("Asset file: " + fileName);
+            if (!mOpen) {
+                throw new RuntimeException("Assetmanager has been closed");
             }
-            final AssetInputStream assetInputStream = new AssetInputStream(asset);
-            incRefsLocked(assetInputStream.hashCode());
-            return assetInputStream;
+            long asset = openAsset(fileName, accessMode);
+            if (asset != 0) {
+                AssetInputStream res = new AssetInputStream(asset);
+                incRefsLocked(res.hashCode());
+                return res;
+            }
         }
+        throw new FileNotFoundException("Asset file: " + fileName);
     }
 
-    /**
-     * Open an uncompressed asset by mmapping it and returning an {@link AssetFileDescriptor}.
-     * This provides access to files that have been bundled with an application as assets -- that
-     * is, files placed in to the "assets" directory.
-     *
-     * The asset must be uncompressed, or an exception will be thrown.
-     *
-     * @param fileName The name of the asset to open.  This name can be hierarchical.
-     * @return An open AssetFileDescriptor.
-     */
-    public @NonNull AssetFileDescriptor openFd(@NonNull String fileName) throws IOException {
-        Preconditions.checkNotNull(fileName, "fileName");
+    public final AssetFileDescriptor openFd(String fileName)
+            throws IOException {
         synchronized (this) {
-            ensureOpenLocked();
-            final ParcelFileDescriptor pfd = nativeOpenAssetFd(mObject, fileName, mOffsets);
-            if (pfd == null) {
-                throw new FileNotFoundException("Asset file: " + fileName);
+            if (!mOpen) {
+                throw new RuntimeException("Assetmanager has been closed");
             }
-            return new AssetFileDescriptor(pfd, mOffsets[0], mOffsets[1]);
+            ParcelFileDescriptor pfd = openAssetFd(fileName, mOffsets);
+            if (pfd != null) {
+                return new AssetFileDescriptor(pfd, mOffsets[0], mOffsets[1]);
+            }
         }
+        throw new FileNotFoundException("Asset file: " + fileName);
     }
 
     /**
@@ -726,121 +408,90 @@
      * 
      * @see #open
      */
-    public @Nullable String[] list(@NonNull String path) throws IOException {
-        Preconditions.checkNotNull(path, "path");
-        synchronized (this) {
-            ensureValidLocked();
-            return nativeList(mObject, path);
-        }
-    }
+    public native final String[] list(String path)
+        throws IOException;
 
     /**
+     * {@hide}
      * Open a non-asset file as an asset using ACCESS_STREAMING mode.  This
      * provides direct access to all of the files included in an application
      * package (not only its assets).  Applications should not normally use
      * this.
-     *
-     * @param fileName Name of the asset to retrieve.
-     *
+     * 
      * @see #open(String)
-     * @hide
      */
-    public @NonNull InputStream openNonAsset(@NonNull String fileName) throws IOException {
+    public final InputStream openNonAsset(String fileName) throws IOException {
         return openNonAsset(0, fileName, ACCESS_STREAMING);
     }
 
     /**
+     * {@hide}
      * Open a non-asset file as an asset using a specific access mode.  This
      * provides direct access to all of the files included in an application
      * package (not only its assets).  Applications should not normally use
      * this.
-     *
-     * @param fileName Name of the asset to retrieve.
-     * @param accessMode Desired access mode for retrieving the data.
-     *
-     * @see #ACCESS_UNKNOWN
-     * @see #ACCESS_STREAMING
-     * @see #ACCESS_RANDOM
-     * @see #ACCESS_BUFFER
+     * 
      * @see #open(String, int)
-     * @hide
      */
-    public @NonNull InputStream openNonAsset(@NonNull String fileName, int accessMode)
-            throws IOException {
+    public final InputStream openNonAsset(String fileName, int accessMode)
+        throws IOException {
         return openNonAsset(0, fileName, accessMode);
     }
 
     /**
+     * {@hide}
      * Open a non-asset in a specified package.  Not for use by applications.
-     *
+     * 
      * @param cookie Identifier of the package to be opened.
      * @param fileName Name of the asset to retrieve.
-     * @hide
      */
-    public @NonNull InputStream openNonAsset(int cookie, @NonNull String fileName)
-            throws IOException {
+    public final InputStream openNonAsset(int cookie, String fileName)
+        throws IOException {
         return openNonAsset(cookie, fileName, ACCESS_STREAMING);
     }
 
     /**
+     * {@hide}
      * Open a non-asset in a specified package.  Not for use by applications.
-     *
+     * 
      * @param cookie Identifier of the package to be opened.
      * @param fileName Name of the asset to retrieve.
      * @param accessMode Desired access mode for retrieving the data.
-     * @hide
      */
-    public @NonNull InputStream openNonAsset(int cookie, @NonNull String fileName, int accessMode)
-            throws IOException {
-        Preconditions.checkNotNull(fileName, "fileName");
+    public final InputStream openNonAsset(int cookie, String fileName, int accessMode)
+        throws IOException {
         synchronized (this) {
-            ensureOpenLocked();
-            final long asset = nativeOpenNonAsset(mObject, cookie, fileName, accessMode);
-            if (asset == 0) {
-                throw new FileNotFoundException("Asset absolute file: " + fileName);
+            if (!mOpen) {
+                throw new RuntimeException("Assetmanager has been closed");
             }
-            final AssetInputStream assetInputStream = new AssetInputStream(asset);
-            incRefsLocked(assetInputStream.hashCode());
-            return assetInputStream;
+            long asset = openNonAssetNative(cookie, fileName, accessMode);
+            if (asset != 0) {
+                AssetInputStream res = new AssetInputStream(asset);
+                incRefsLocked(res.hashCode());
+                return res;
+            }
         }
+        throw new FileNotFoundException("Asset absolute file: " + fileName);
     }
 
-    /**
-     * Open a non-asset as an asset by mmapping it and returning an {@link AssetFileDescriptor}.
-     * This provides direct access to all of the files included in an application
-     * package (not only its assets).  Applications should not normally use this.
-     *
-     * The asset must not be compressed, or an exception will be thrown.
-     *
-     * @param fileName Name of the asset to retrieve.
-     */
-    public @NonNull AssetFileDescriptor openNonAssetFd(@NonNull String fileName)
+    public final AssetFileDescriptor openNonAssetFd(String fileName)
             throws IOException {
         return openNonAssetFd(0, fileName);
     }
-
-    /**
-     * Open a non-asset as an asset by mmapping it and returning an {@link AssetFileDescriptor}.
-     * This provides direct access to all of the files included in an application
-     * package (not only its assets).  Applications should not normally use this.
-     *
-     * The asset must not be compressed, or an exception will be thrown.
-     *
-     * @param cookie Identifier of the package to be opened.
-     * @param fileName Name of the asset to retrieve.
-     */
-    public @NonNull AssetFileDescriptor openNonAssetFd(int cookie, @NonNull String fileName)
-            throws IOException {
-        Preconditions.checkNotNull(fileName, "fileName");
+    
+    public final AssetFileDescriptor openNonAssetFd(int cookie,
+            String fileName) throws IOException {
         synchronized (this) {
-            ensureOpenLocked();
-            final ParcelFileDescriptor pfd =
-                    nativeOpenNonAssetFd(mObject, cookie, fileName, mOffsets);
-            if (pfd == null) {
-                throw new FileNotFoundException("Asset absolute file: " + fileName);
+            if (!mOpen) {
+                throw new RuntimeException("Assetmanager has been closed");
             }
-            return new AssetFileDescriptor(pfd, mOffsets[0], mOffsets[1]);
+            ParcelFileDescriptor pfd = openNonAssetFdNative(cookie,
+                    fileName, mOffsets);
+            if (pfd != null) {
+                return new AssetFileDescriptor(pfd, mOffsets[0], mOffsets[1]);
+            }
         }
+        throw new FileNotFoundException("Asset absolute file: " + fileName);
     }
     
     /**
@@ -848,7 +499,7 @@
      * 
      * @param fileName The name of the file to retrieve.
      */
-    public @NonNull XmlResourceParser openXmlResourceParser(@NonNull String fileName)
+    public final XmlResourceParser openXmlResourceParser(String fileName)
             throws IOException {
         return openXmlResourceParser(0, fileName);
     }
@@ -859,265 +510,270 @@
      * @param cookie Identifier of the package to be opened.
      * @param fileName The name of the file to retrieve.
      */
-    public @NonNull XmlResourceParser openXmlResourceParser(int cookie, @NonNull String fileName)
-            throws IOException {
-        try (XmlBlock block = openXmlBlockAsset(cookie, fileName)) {
-            XmlResourceParser parser = block.newParser();
-            // If openXmlBlockAsset doesn't throw, it will always return an XmlBlock object with
-            // a valid native pointer, which makes newParser always return non-null. But let's
-            // be paranoid.
-            if (parser == null) {
-                throw new AssertionError("block.newParser() returned a null parser");
-            }
-            return parser;
-        }
+    public final XmlResourceParser openXmlResourceParser(int cookie,
+            String fileName) throws IOException {
+        XmlBlock block = openXmlBlockAsset(cookie, fileName);
+        XmlResourceParser rp = block.newParser();
+        block.close();
+        return rp;
     }
 
     /**
-     * Retrieve a non-asset as a compiled XML file.  Not for use by applications.
+     * {@hide}
+     * Retrieve a non-asset as a compiled XML file.  Not for use by
+     * applications.
      * 
      * @param fileName The name of the file to retrieve.
-     * @hide
      */
-    @NonNull XmlBlock openXmlBlockAsset(@NonNull String fileName) throws IOException {
+    /*package*/ final XmlBlock openXmlBlockAsset(String fileName)
+            throws IOException {
         return openXmlBlockAsset(0, fileName);
     }
 
     /**
+     * {@hide}
      * Retrieve a non-asset as a compiled XML file.  Not for use by
      * applications.
      * 
      * @param cookie Identifier of the package to be opened.
      * @param fileName Name of the asset to retrieve.
-     * @hide
      */
-    @NonNull XmlBlock openXmlBlockAsset(int cookie, @NonNull String fileName) throws IOException {
-        Preconditions.checkNotNull(fileName, "fileName");
+    /*package*/ final XmlBlock openXmlBlockAsset(int cookie, String fileName)
+        throws IOException {
         synchronized (this) {
-            ensureOpenLocked();
-            final long xmlBlock = nativeOpenXmlAsset(mObject, cookie, fileName);
-            if (xmlBlock == 0) {
-                throw new FileNotFoundException("Asset XML file: " + fileName);
+            if (!mOpen) {
+                throw new RuntimeException("Assetmanager has been closed");
             }
-            final XmlBlock block = new XmlBlock(this, xmlBlock);
-            incRefsLocked(block.hashCode());
-            return block;
+            long xmlBlock = openXmlAssetNative(cookie, fileName);
+            if (xmlBlock != 0) {
+                XmlBlock res = new XmlBlock(this, xmlBlock);
+                incRefsLocked(res.hashCode());
+                return res;
+            }
         }
+        throw new FileNotFoundException("Asset XML file: " + fileName);
     }
 
-    void xmlBlockGone(int id) {
+    /*package*/ void xmlBlockGone(int id) {
         synchronized (this) {
             decRefsLocked(id);
         }
     }
 
-    void applyStyle(long themePtr, @AttrRes int defStyleAttr, @StyleRes int defStyleRes,
-            @Nullable XmlBlock.Parser parser, @NonNull int[] inAttrs, long outValuesAddress,
-            long outIndicesAddress) {
-        Preconditions.checkNotNull(inAttrs, "inAttrs");
+    /*package*/ final long createTheme() {
         synchronized (this) {
-            // Need to synchronize on AssetManager because we will be accessing
-            // the native implementation of AssetManager.
-            ensureValidLocked();
-            nativeApplyStyle(mObject, themePtr, defStyleAttr, defStyleRes,
-                    parser != null ? parser.mParseState : 0, inAttrs, outValuesAddress,
-                    outIndicesAddress);
+            if (!mOpen) {
+                throw new RuntimeException("Assetmanager has been closed");
+            }
+            long res = newTheme();
+            incRefsLocked(res);
+            return res;
         }
     }
 
-    boolean resolveAttrs(long themePtr, @AttrRes int defStyleAttr, @StyleRes int defStyleRes,
-            @Nullable int[] inValues, @NonNull int[] inAttrs, @NonNull int[] outValues,
-            @NonNull int[] outIndices) {
-        Preconditions.checkNotNull(inAttrs, "inAttrs");
-        Preconditions.checkNotNull(outValues, "outValues");
-        Preconditions.checkNotNull(outIndices, "outIndices");
+    /*package*/ final void releaseTheme(long theme) {
         synchronized (this) {
-            // Need to synchronize on AssetManager because we will be accessing
-            // the native implementation of AssetManager.
-            ensureValidLocked();
-            return nativeResolveAttrs(mObject,
-                    themePtr, defStyleAttr, defStyleRes, inValues, inAttrs, outValues, outIndices);
+            deleteTheme(theme);
+            decRefsLocked(theme);
         }
     }
 
-    boolean retrieveAttributes(@NonNull XmlBlock.Parser parser, @NonNull int[] inAttrs,
-            @NonNull int[] outValues, @NonNull int[] outIndices) {
-        Preconditions.checkNotNull(parser, "parser");
-        Preconditions.checkNotNull(inAttrs, "inAttrs");
-        Preconditions.checkNotNull(outValues, "outValues");
-        Preconditions.checkNotNull(outIndices, "outIndices");
-        synchronized (this) {
-            // Need to synchronize on AssetManager because we will be accessing
-            // the native implementation of AssetManager.
-            ensureValidLocked();
-            return nativeRetrieveAttributes(
-                    mObject, parser.mParseState, inAttrs, outValues, outIndices);
-        }
-    }
-
-    long createTheme() {
-        synchronized (this) {
-            ensureValidLocked();
-            long themePtr = nativeThemeCreate(mObject);
-            incRefsLocked(themePtr);
-            return themePtr;
-        }
-    }
-
-    void releaseTheme(long themePtr) {
-        synchronized (this) {
-            nativeThemeDestroy(themePtr);
-            decRefsLocked(themePtr);
-        }
-    }
-
-    void applyStyleToTheme(long themePtr, @StyleRes int resId, boolean force) {
-        synchronized (this) {
-            // Need to synchronize on AssetManager because we will be accessing
-            // the native implementation of AssetManager.
-            ensureValidLocked();
-            nativeThemeApplyStyle(mObject, themePtr, resId, force);
-        }
-    }
-
-    @Override
     protected void finalize() throws Throwable {
-        if (DEBUG_REFS && mNumRefs != 0) {
-            Log.w(TAG, "AssetManager " + this + " finalized with non-zero refs: " + mNumRefs);
-            if (mRefStacks != null) {
-                for (RuntimeException e : mRefStacks.values()) {
-                    Log.w(TAG, "Reference from here", e);
+        try {
+            if (DEBUG_REFS && mNumRefs != 0) {
+                Log.w(TAG, "AssetManager " + this
+                        + " finalized with non-zero refs: " + mNumRefs);
+                if (mRefStacks != null) {
+                    for (RuntimeException e : mRefStacks.values()) {
+                        Log.w(TAG, "Reference from here", e);
+                    }
                 }
             }
-        }
-
-        if (mObject != 0) {
-            nativeDestroy(mObject);
+            destroy();
+        } finally {
+            super.finalize();
         }
     }
-
-    /* No Locking is needed for AssetInputStream because an AssetInputStream is not-thread
-    safe and it does not rely on AssetManager once it has been created. It completely owns the
-    underlying Asset. */
+    
     public final class AssetInputStream extends InputStream {
-        private long mAssetNativePtr;
-        private long mLength;
-        private long mMarkPos;
-
         /**
          * @hide
          */
         public final int getAssetInt() {
             throw new UnsupportedOperationException();
         }
-
         /**
          * @hide
          */
         public final long getNativeAsset() {
-            return mAssetNativePtr;
+            return mAsset;
         }
-
-        private AssetInputStream(long assetNativePtr) {
-            mAssetNativePtr = assetNativePtr;
-            mLength = nativeAssetGetLength(assetNativePtr);
+        private AssetInputStream(long asset)
+        {
+            mAsset = asset;
+            mLength = getAssetLength(asset);
         }
-
-        @Override
         public final int read() throws IOException {
-            ensureOpen();
-            return nativeAssetReadChar(mAssetNativePtr);
+            return readAssetChar(mAsset);
         }
-
-        @Override
-        public final int read(@NonNull byte[] b) throws IOException {
-            ensureOpen();
-            Preconditions.checkNotNull(b, "b");
-            return nativeAssetRead(mAssetNativePtr, b, 0, b.length);
-        }
-
-        @Override
-        public final int read(@NonNull byte[] b, int off, int len) throws IOException {
-            ensureOpen();
-            Preconditions.checkNotNull(b, "b");
-            return nativeAssetRead(mAssetNativePtr, b, off, len);
-        }
-
-        @Override
-        public final long skip(long n) throws IOException {
-            ensureOpen();
-            long pos = nativeAssetSeek(mAssetNativePtr, 0, 0);
-            if ((pos + n) > mLength) {
-                n = mLength - pos;
-            }
-            if (n > 0) {
-                nativeAssetSeek(mAssetNativePtr, n, 0);
-            }
-            return n;
-        }
-
-        @Override
-        public final int available() throws IOException {
-            ensureOpen();
-            final long len = nativeAssetGetRemainingLength(mAssetNativePtr);
-            return len > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) len;
-        }
-
-        @Override
         public final boolean markSupported() {
             return true;
         }
-
-        @Override
-        public final void mark(int readlimit) {
-            ensureOpen();
-            mMarkPos = nativeAssetSeek(mAssetNativePtr, 0, 0);
+        public final int available() throws IOException {
+            long len = getAssetRemainingLength(mAsset);
+            return len > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int)len;
         }
-
-        @Override
-        public final void reset() throws IOException {
-            ensureOpen();
-            nativeAssetSeek(mAssetNativePtr, mMarkPos, -1);
-        }
-
-        @Override
         public final void close() throws IOException {
-            if (mAssetNativePtr != 0) {
-                nativeAssetDestroy(mAssetNativePtr);
-                mAssetNativePtr = 0;
-
-                synchronized (AssetManager.this) {
+            synchronized (AssetManager.this) {
+                if (mAsset != 0) {
+                    destroyAsset(mAsset);
+                    mAsset = 0;
                     decRefsLocked(hashCode());
                 }
             }
         }
+        public final void mark(int readlimit) {
+            mMarkPos = seekAsset(mAsset, 0, 0);
+        }
+        public final void reset() throws IOException {
+            seekAsset(mAsset, mMarkPos, -1);
+        }
+        public final int read(byte[] b) throws IOException {
+            return readAsset(mAsset, b, 0, b.length);
+        }
+        public final int read(byte[] b, int off, int len) throws IOException {
+            return readAsset(mAsset, b, off, len);
+        }
+        public final long skip(long n) throws IOException {
+            long pos = seekAsset(mAsset, 0, 0);
+            if ((pos+n) > mLength) {
+                n = mLength-pos;
+            }
+            if (n > 0) {
+                seekAsset(mAsset, n, 0);
+            }
+            return n;
+        }
 
-        @Override
-        protected void finalize() throws Throwable {
+        protected void finalize() throws Throwable
+        {
             close();
         }
 
-        private void ensureOpen() {
-            if (mAssetNativePtr == 0) {
-                throw new IllegalStateException("AssetInputStream is closed");
-            }
+        private long mAsset;
+        private long mLength;
+        private long mMarkPos;
+    }
+
+    /**
+     * Add an additional set of assets to the asset manager.  This can be
+     * either a directory or ZIP file.  Not for use by applications.  Returns
+     * the cookie of the added asset, or 0 on failure.
+     * {@hide}
+     */
+    public final int addAssetPath(String path) {
+        return  addAssetPathInternal(path, false);
+    }
+
+    /**
+     * Add an application assets to the asset manager and loading it as shared library.
+     * This can be either a directory or ZIP file.  Not for use by applications.  Returns
+     * the cookie of the added asset, or 0 on failure.
+     * {@hide}
+     */
+    public final int addAssetPathAsSharedLibrary(String path) {
+        return addAssetPathInternal(path, true);
+    }
+
+    private final int addAssetPathInternal(String path, boolean appAsLib) {
+        synchronized (this) {
+            int res = addAssetPathNative(path, appAsLib);
+            makeStringBlocks(mStringBlocks);
+            return res;
         }
     }
 
+    private native final int addAssetPathNative(String path, boolean appAsLib);
+
+    /**
+     * Add an additional set of assets to the asset manager from an already open
+     * FileDescriptor.  Not for use by applications.
+     * This does not give full AssetManager functionality for these assets,
+     * since the origin of the file is not known for purposes of sharing,
+     * overlay resolution, and other features.  However it does allow you
+     * to do simple access to the contents of the given fd as an apk file.
+     * Performs a dup of the underlying fd, so you must take care of still closing
+     * the FileDescriptor yourself (and can do that whenever you want).
+     * Returns the cookie of the added asset, or 0 on failure.
+     * {@hide}
+     */
+    public int addAssetFd(FileDescriptor fd, String debugPathName) {
+        return addAssetFdInternal(fd, debugPathName, false);
+    }
+
+    private int addAssetFdInternal(FileDescriptor fd, String debugPathName,
+            boolean appAsLib) {
+        synchronized (this) {
+            int res = addAssetFdNative(fd, debugPathName, appAsLib);
+            makeStringBlocks(mStringBlocks);
+            return res;
+        }
+    }
+
+    private native int addAssetFdNative(FileDescriptor fd, String debugPathName,
+            boolean appAsLib);
+
+    /**
+     * Add a set of assets to overlay an already added set of assets.
+     *
+     * This is only intended for application resources. System wide resources
+     * are handled before any Java code is executed.
+     *
+     * {@hide}
+     */
+
+    public final int addOverlayPath(String idmapPath) {
+        synchronized (this) {
+            int res = addOverlayPathNative(idmapPath);
+            makeStringBlocks(mStringBlocks);
+            return res;
+        }
+    }
+
+    /**
+     * See addOverlayPath.
+     *
+     * {@hide}
+     */
+    public native final int addOverlayPathNative(String idmapPath);
+
+    /**
+     * Add multiple sets of assets to the asset manager at once.  See
+     * {@link #addAssetPath(String)} for more information.  Returns array of
+     * cookies for each added asset with 0 indicating failure, or null if
+     * the input array of paths is null.
+     * {@hide}
+     */
+    public final int[] addAssetPaths(String[] paths) {
+        if (paths == null) {
+            return null;
+        }
+
+        int[] cookies = new int[paths.length];
+        for (int i = 0; i < paths.length; i++) {
+            cookies[i] = addAssetPath(paths[i]);
+        }
+
+        return cookies;
+    }
+
     /**
      * Determine whether the state in this asset manager is up-to-date with
      * the files on the filesystem.  If false is returned, you need to
      * instantiate a new AssetManager class to see the new data.
-     * @hide
+     * {@hide}
      */
-    public boolean isUpToDate() {
-        for (ApkAssets apkAssets : getApkAssets()) {
-            if (!apkAssets.isUpToDate()) {
-                return false;
-            }
-        }
-        return true;
-    }
+    public native final boolean isUpToDate();
 
     /**
      * Get the locales that this asset manager contains data for.
@@ -1130,12 +786,7 @@
      * are of the form {@code ll_CC} where {@code ll} is a two letter language code,
      * and {@code CC} is a two letter country code.
      */
-    public String[] getLocales() {
-        synchronized (this) {
-            ensureValidLocked();
-            return nativeGetLocales(mObject, false /*excludeSystem*/);
-        }
-    }
+    public native final String[] getLocales();
 
     /**
      * Same as getLocales(), except that locales that are only provided by the system (i.e. those
@@ -1145,58 +796,132 @@
      * assets support Cherokee and French, getLocales() would return
      * [Cherokee, English, French, German], while getNonSystemLocales() would return
      * [Cherokee, French].
-     * @hide
+     * {@hide}
      */
-    public String[] getNonSystemLocales() {
-        synchronized (this) {
-            ensureValidLocked();
-            return nativeGetLocales(mObject, true /*excludeSystem*/);
-        }
-    }
+    public native final String[] getNonSystemLocales();
+
+    /** {@hide} */
+    public native final Configuration[] getSizeConfigurations();
 
     /**
-     * @hide
-     */
-    Configuration[] getSizeConfigurations() {
-        synchronized (this) {
-            ensureValidLocked();
-            return nativeGetSizeConfigurations(mObject);
-        }
-    }
-
-    /**
-     * Change the configuration used when retrieving resources.  Not for use by
+     * Change the configuation used when retrieving resources.  Not for use by
      * applications.
-     * @hide
+     * {@hide}
      */
-    public void setConfiguration(int mcc, int mnc, @Nullable String locale, int orientation,
-            int touchscreen, int density, int keyboard, int keyboardHidden, int navigation,
-            int screenWidth, int screenHeight, int smallestScreenWidthDp, int screenWidthDp,
-            int screenHeightDp, int screenLayout, int uiMode, int colorMode, int majorVersion) {
-        synchronized (this) {
-            ensureValidLocked();
-            nativeSetConfiguration(mObject, mcc, mnc, locale, orientation, touchscreen, density,
-                    keyboard, keyboardHidden, navigation, screenWidth, screenHeight,
-                    smallestScreenWidthDp, screenWidthDp, screenHeightDp, screenLayout, uiMode,
-                    colorMode, majorVersion);
-        }
-    }
+    public native final void setConfiguration(int mcc, int mnc, String locale,
+            int orientation, int touchscreen, int density, int keyboard,
+            int keyboardHidden, int navigation, int screenWidth, int screenHeight,
+            int smallestScreenWidthDp, int screenWidthDp, int screenHeightDp,
+            int screenLayout, int uiMode, int colorMode, int majorVersion);
 
     /**
-     * @hide
+     * Retrieve the resource identifier for the given resource name.
      */
-    public SparseArray<String> getAssignedPackageIdentifiers() {
-        synchronized (this) {
-            ensureValidLocked();
-            return nativeGetAssignedPackageIdentifiers(mObject);
-        }
-    }
+    /*package*/ native final int getResourceIdentifier(String name,
+                                                       String defType,
+                                                       String defPackage);
+
+    /*package*/ native final String getResourceName(int resid);
+    /*package*/ native final String getResourcePackageName(int resid);
+    /*package*/ native final String getResourceTypeName(int resid);
+    /*package*/ native final String getResourceEntryName(int resid);
+    
+    private native final long openAsset(String fileName, int accessMode);
+    private final native ParcelFileDescriptor openAssetFd(String fileName,
+            long[] outOffsets) throws IOException;
+    private native final long openNonAssetNative(int cookie, String fileName,
+            int accessMode);
+    private native ParcelFileDescriptor openNonAssetFdNative(int cookie,
+            String fileName, long[] outOffsets) throws IOException;
+    private native final void destroyAsset(long asset);
+    private native final int readAssetChar(long asset);
+    private native final int readAsset(long asset, byte[] b, int off, int len);
+    private native final long seekAsset(long asset, long offset, int whence);
+    private native final long getAssetLength(long asset);
+    private native final long getAssetRemainingLength(long asset);
+
+    /** Returns true if the resource was found, filling in mRetStringBlock and
+     *  mRetData. */
+    private native final int loadResourceValue(int ident, short density, TypedValue outValue,
+            boolean resolve);
+    /** Returns true if the resource was found, filling in mRetStringBlock and
+     *  mRetData. */
+    private native final int loadResourceBagValue(int ident, int bagEntryId, TypedValue outValue,
+                                               boolean resolve);
+    /*package*/ static final int STYLE_NUM_ENTRIES = 6;
+    /*package*/ static final int STYLE_TYPE = 0;
+    /*package*/ static final int STYLE_DATA = 1;
+    /*package*/ static final int STYLE_ASSET_COOKIE = 2;
+    /*package*/ static final int STYLE_RESOURCE_ID = 3;
+
+    /* Offset within typed data array for native changingConfigurations. */
+    static final int STYLE_CHANGING_CONFIGURATIONS = 4;
+
+    /*package*/ static final int STYLE_DENSITY = 5;
+    /*package*/ native static final void applyStyle(long theme,
+            int defStyleAttr, int defStyleRes, long xmlParser,
+            int[] inAttrs, int length, long outValuesAddress, long outIndicesAddress);
+    /*package*/ native static final boolean resolveAttrs(long theme,
+            int defStyleAttr, int defStyleRes, int[] inValues,
+            int[] inAttrs, int[] outValues, int[] outIndices);
+    /*package*/ native final boolean retrieveAttributes(
+            long xmlParser, int[] inAttrs, int[] outValues, int[] outIndices);
+    /*package*/ native final int getArraySize(int resource);
+    /*package*/ native final int retrieveArray(int resource, int[] outValues);
+    private native final int getStringBlockCount();
+    private native final long getNativeStringBlock(int block);
+
+    /**
+     * {@hide}
+     */
+    public native final String getCookieName(int cookie);
+
+    /**
+     * {@hide}
+     */
+    public native final SparseArray<String> getAssignedPackageIdentifiers();
+
+    /**
+     * {@hide}
+     */
+    public native static final int getGlobalAssetCount();
+    
+    /**
+     * {@hide}
+     */
+    public native static final String getAssetAllocations();
+    
+    /**
+     * {@hide}
+     */
+    public native static final int getGlobalAssetManagerCount();
+    
+    private native final long newTheme();
+    private native final void deleteTheme(long theme);
+    /*package*/ native static final void applyThemeStyle(long theme, int styleRes, boolean force);
+    /*package*/ native static final void copyTheme(long dest, long source);
+    /*package*/ native static final void clearTheme(long theme);
+    /*package*/ native static final int loadThemeAttributeValue(long theme, int ident,
+                                                                TypedValue outValue,
+                                                                boolean resolve);
+    /*package*/ native static final void dumpTheme(long theme, int priority, String tag, String prefix);
+    /*package*/ native static final @NativeConfig int getThemeChangingConfigurations(long theme);
+
+    private native final long openXmlAssetNative(int cookie, String fileName);
+
+    private native final String[] getArrayStringResource(int arrayRes);
+    private native final int[] getArrayStringInfo(int arrayRes);
+    /*package*/ native final int[] getArrayIntResource(int arrayRes);
+    /*package*/ native final int[] getStyleAttributes(int themeRes);
+
+    private native final void init(boolean isSystem);
+    private native final void destroy();
 
     @GuardedBy("this")
-    private void incRefsLocked(long id) {
+    private final void incRefsLocked(long id) {
         if (DEBUG_REFS) {
             if (mRefStacks == null) {
-                mRefStacks = new HashMap<>();
+                mRefStacks = new HashMap<Long, RuntimeException>();
             }
             RuntimeException ex = new RuntimeException();
             ex.fillInStackTrace();
@@ -1206,117 +931,15 @@
     }
 
     @GuardedBy("this")
-    private void decRefsLocked(long id) {
+    private final void decRefsLocked(long id) {
         if (DEBUG_REFS && mRefStacks != null) {
             mRefStacks.remove(id);
         }
         mNumRefs--;
-        if (mNumRefs == 0 && mObject != 0) {
-            nativeDestroy(mObject);
-            mObject = 0;
-            mApkAssets = sEmptyApkAssets;
+        //System.out.println("Dec streams: mNumRefs=" + mNumRefs
+        //                   + " mReleased=" + mReleased);
+        if (mNumRefs == 0) {
+            destroy();
         }
     }
-
-    // AssetManager setup native methods.
-    private static native long nativeCreate();
-    private static native void nativeDestroy(long ptr);
-    private static native void nativeSetApkAssets(long ptr, @NonNull ApkAssets[] apkAssets,
-            boolean invalidateCaches);
-    private static native void nativeSetConfiguration(long ptr, int mcc, int mnc,
-            @Nullable String locale, int orientation, int touchscreen, int density, int keyboard,
-            int keyboardHidden, int navigation, int screenWidth, int screenHeight,
-            int smallestScreenWidthDp, int screenWidthDp, int screenHeightDp, int screenLayout,
-            int uiMode, int colorMode, int majorVersion);
-    private static native @NonNull SparseArray<String> nativeGetAssignedPackageIdentifiers(
-            long ptr);
-
-    // File native methods.
-    private static native @Nullable String[] nativeList(long ptr, @NonNull String path)
-            throws IOException;
-    private static native long nativeOpenAsset(long ptr, @NonNull String fileName, int accessMode);
-    private static native @Nullable ParcelFileDescriptor nativeOpenAssetFd(long ptr,
-            @NonNull String fileName, long[] outOffsets) throws IOException;
-    private static native long nativeOpenNonAsset(long ptr, int cookie, @NonNull String fileName,
-            int accessMode);
-    private static native @Nullable ParcelFileDescriptor nativeOpenNonAssetFd(long ptr, int cookie,
-            @NonNull String fileName, @NonNull long[] outOffsets) throws IOException;
-    private static native long nativeOpenXmlAsset(long ptr, int cookie, @NonNull String fileName);
-
-    // Primitive resource native methods.
-    private static native int nativeGetResourceValue(long ptr, @AnyRes int resId, short density,
-            @NonNull TypedValue outValue, boolean resolveReferences);
-    private static native int nativeGetResourceBagValue(long ptr, @AnyRes int resId, int bagEntryId,
-            @NonNull TypedValue outValue);
-
-    private static native @Nullable @AttrRes int[] nativeGetStyleAttributes(long ptr,
-            @StyleRes int resId);
-    private static native @Nullable String[] nativeGetResourceStringArray(long ptr,
-            @ArrayRes int resId);
-    private static native @Nullable int[] nativeGetResourceStringArrayInfo(long ptr,
-            @ArrayRes int resId);
-    private static native @Nullable int[] nativeGetResourceIntArray(long ptr, @ArrayRes int resId);
-    private static native int nativeGetResourceArraySize(long ptr, @ArrayRes int resId);
-    private static native int nativeGetResourceArray(long ptr, @ArrayRes int resId,
-            @NonNull int[] outValues);
-
-    // Resource name/ID native methods.
-    private static native @AnyRes int nativeGetResourceIdentifier(long ptr, @NonNull String name,
-            @Nullable String defType, @Nullable String defPackage);
-    private static native @Nullable String nativeGetResourceName(long ptr, @AnyRes int resid);
-    private static native @Nullable String nativeGetResourcePackageName(long ptr,
-            @AnyRes int resid);
-    private static native @Nullable String nativeGetResourceTypeName(long ptr, @AnyRes int resid);
-    private static native @Nullable String nativeGetResourceEntryName(long ptr, @AnyRes int resid);
-    private static native @Nullable String[] nativeGetLocales(long ptr, boolean excludeSystem);
-    private static native @Nullable Configuration[] nativeGetSizeConfigurations(long ptr);
-
-    // Style attribute retrieval native methods.
-    private static native void nativeApplyStyle(long ptr, long themePtr, @AttrRes int defStyleAttr,
-            @StyleRes int defStyleRes, long xmlParserPtr, @NonNull int[] inAttrs,
-            long outValuesAddress, long outIndicesAddress);
-    private static native boolean nativeResolveAttrs(long ptr, long themePtr,
-            @AttrRes int defStyleAttr, @StyleRes int defStyleRes, @Nullable int[] inValues,
-            @NonNull int[] inAttrs, @NonNull int[] outValues, @NonNull int[] outIndices);
-    private static native boolean nativeRetrieveAttributes(long ptr, long xmlParserPtr,
-            @NonNull int[] inAttrs, @NonNull int[] outValues, @NonNull int[] outIndices);
-
-    // Theme related native methods
-    private static native long nativeThemeCreate(long ptr);
-    private static native void nativeThemeDestroy(long themePtr);
-    private static native void nativeThemeApplyStyle(long ptr, long themePtr, @StyleRes int resId,
-            boolean force);
-    static native void nativeThemeCopy(long destThemePtr, long sourceThemePtr);
-    static native void nativeThemeClear(long themePtr);
-    private static native int nativeThemeGetAttributeValue(long ptr, long themePtr,
-            @AttrRes int resId, @NonNull TypedValue outValue, boolean resolve);
-    private static native void nativeThemeDump(long ptr, long themePtr, int priority, String tag,
-            String prefix);
-    static native @NativeConfig int nativeThemeGetChangingConfigurations(long themePtr);
-
-    // AssetInputStream related native methods.
-    private static native void nativeAssetDestroy(long assetPtr);
-    private static native int nativeAssetReadChar(long assetPtr);
-    private static native int nativeAssetRead(long assetPtr, byte[] b, int off, int len);
-    private static native long nativeAssetSeek(long assetPtr, long offset, int whence);
-    private static native long nativeAssetGetLength(long assetPtr);
-    private static native long nativeAssetGetRemainingLength(long assetPtr);
-
-    private static native void nativeVerifySystemIdmaps();
-
-    // Global debug native methods.
-    /**
-     * @hide
-     */
-    public static native int getGlobalAssetCount();
-
-    /**
-     * @hide
-     */
-    public static native String getAssetAllocations();
-
-    /**
-     * @hide
-     */
-    public static native int getGlobalAssetManagerCount();
 }
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index d813382..ad85e71 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -590,7 +590,7 @@
      */
     @NonNull
     public int[] getIntArray(@ArrayRes int id) throws NotFoundException {
-        int[] res = mResourcesImpl.getAssets().getResourceIntArray(id);
+        int[] res = mResourcesImpl.getAssets().getArrayIntResource(id);
         if (res != null) {
             return res;
         }
@@ -613,13 +613,13 @@
     @NonNull
     public TypedArray obtainTypedArray(@ArrayRes int id) throws NotFoundException {
         final ResourcesImpl impl = mResourcesImpl;
-        int len = impl.getAssets().getResourceArraySize(id);
+        int len = impl.getAssets().getArraySize(id);
         if (len < 0) {
             throw new NotFoundException("Array resource ID #0x" + Integer.toHexString(id));
         }
         
         TypedArray array = TypedArray.obtain(this, len);
-        array.mLength = impl.getAssets().getResourceArray(id, array.mData);
+        array.mLength = impl.getAssets().retrieveArray(id, array.mData);
         array.mIndices[0] = 0;
         
         return array;
@@ -1794,7 +1794,8 @@
         // out the attributes from the XML file (applying type information
         // contained in the resources and such).
         XmlBlock.Parser parser = (XmlBlock.Parser)set;
-        mResourcesImpl.getAssets().retrieveAttributes(parser, attrs, array.mData, array.mIndices);
+        mResourcesImpl.getAssets().retrieveAttributes(parser.mParseState, attrs,
+                array.mData, array.mIndices);
 
         array.mXml = parser;
 
diff --git a/core/java/android/content/res/ResourcesImpl.java b/core/java/android/content/res/ResourcesImpl.java
index 08a1613..cf01451 100644
--- a/core/java/android/content/res/ResourcesImpl.java
+++ b/core/java/android/content/res/ResourcesImpl.java
@@ -168,6 +168,7 @@
         mDisplayAdjustments = displayAdjustments;
         mConfiguration.setToDefaults();
         updateConfiguration(config, metrics, displayAdjustments.getCompatibilityInfo());
+        mAssets.ensureStringBlocks();
     }
 
     public DisplayAdjustments getDisplayAdjustments() {
@@ -911,7 +912,7 @@
      * first try to load CSL from the cache. If not found, try to get from the constant state.
      * Last, parse the XML and generate the CSL.
      */
-    @NonNull
+    @Nullable
     private ComplexColor loadComplexColorFromName(Resources wrapper, Resources.Theme theme,
             TypedValue value, int id) {
         final long key = (((long) value.assetCookie) << 32) | value.data;
@@ -931,15 +932,17 @@
             complexColor = loadComplexColorForCookie(wrapper, value, id, theme);
         }
 
-        complexColor.setBaseChangingConfigurations(value.changingConfigurations);
+        if (complexColor != null) {
+            complexColor.setBaseChangingConfigurations(value.changingConfigurations);
 
-        if (mPreloading) {
-            if (verifyPreloadConfig(complexColor.getChangingConfigurations(),
-                    0, value.resourceId, "color")) {
-                sPreloadedComplexColors.put(key, complexColor.getConstantState());
+            if (mPreloading) {
+                if (verifyPreloadConfig(complexColor.getChangingConfigurations(),
+                        0, value.resourceId, "color")) {
+                    sPreloadedComplexColors.put(key, complexColor.getConstantState());
+                }
+            } else {
+                cache.put(key, theme, complexColor.getConstantState());
             }
-        } else {
-            cache.put(key, theme, complexColor.getConstantState());
         }
         return complexColor;
     }
@@ -1043,7 +1046,8 @@
      * We deferred the parser creation to this function b/c we need to differentiate b/t gradient
      * and selector tag.
      *
-     * @return a ComplexColor (GradientColor or ColorStateList) based on the XML file content.
+     * @return a ComplexColor (GradientColor or ColorStateList) based on the XML file content, or
+     *     {@code null} if the XML file is neither.
      */
     @NonNull
     private ComplexColor loadComplexColorForCookie(Resources wrapper, TypedValue value, int id,
@@ -1274,7 +1278,8 @@
 
         void applyStyle(int resId, boolean force) {
             synchronized (mKey) {
-                mAssets.applyStyleToTheme(mTheme, resId, force);
+                AssetManager.applyThemeStyle(mTheme, resId, force);
+
                 mThemeResId = resId;
                 mKey.append(resId, force);
             }
@@ -1283,7 +1288,7 @@
         void setTo(ThemeImpl other) {
             synchronized (mKey) {
                 synchronized (other.mKey) {
-                    AssetManager.nativeThemeCopy(mTheme, other.mTheme);
+                    AssetManager.copyTheme(mTheme, other.mTheme);
 
                     mThemeResId = other.mThemeResId;
                     mKey.setTo(other.getKey());
@@ -1306,10 +1311,12 @@
                 // out the attributes from the XML file (applying type information
                 // contained in the resources and such).
                 final XmlBlock.Parser parser = (XmlBlock.Parser) set;
-                mAssets.applyStyle(mTheme, defStyleAttr, defStyleRes, parser, attrs,
-                        array.mDataAddress, array.mIndicesAddress);
+                AssetManager.applyStyle(mTheme, defStyleAttr, defStyleRes,
+                        parser != null ? parser.mParseState : 0,
+                        attrs, attrs.length, array.mDataAddress, array.mIndicesAddress);
                 array.mTheme = wrapper;
                 array.mXml = parser;
+
                 return array;
             }
         }
@@ -1326,7 +1333,7 @@
                 }
 
                 final TypedArray array = TypedArray.obtain(wrapper.getResources(), len);
-                mAssets.resolveAttrs(mTheme, 0, 0, values, attrs, array.mData, array.mIndices);
+                AssetManager.resolveAttrs(mTheme, 0, 0, values, attrs, array.mData, array.mIndices);
                 array.mTheme = wrapper;
                 array.mXml = null;
                 return array;
@@ -1346,14 +1353,14 @@
         @Config int getChangingConfigurations() {
             synchronized (mKey) {
                 final @NativeConfig int nativeChangingConfig =
-                        AssetManager.nativeThemeGetChangingConfigurations(mTheme);
+                        AssetManager.getThemeChangingConfigurations(mTheme);
                 return ActivityInfo.activityInfoConfigNativeToJava(nativeChangingConfig);
             }
         }
 
         public void dump(int priority, String tag, String prefix) {
             synchronized (mKey) {
-                mAssets.dumpTheme(mTheme, priority, tag, prefix);
+                AssetManager.dumpTheme(mTheme, priority, tag, prefix);
             }
         }
 
@@ -1382,13 +1389,13 @@
          */
         void rebase() {
             synchronized (mKey) {
-                AssetManager.nativeThemeClear(mTheme);
+                AssetManager.clearTheme(mTheme);
 
                 // Reapply the same styles in the same order.
                 for (int i = 0; i < mKey.mCount; i++) {
                     final int resId = mKey.mResId[i];
                     final boolean force = mKey.mForce[i];
-                    mAssets.applyStyleToTheme(mTheme, resId, force);
+                    AssetManager.applyThemeStyle(mTheme, resId, force);
                 }
             }
         }
diff --git a/core/java/android/content/res/TypedArray.java b/core/java/android/content/res/TypedArray.java
index cbb3c6d..f33c751 100644
--- a/core/java/android/content/res/TypedArray.java
+++ b/core/java/android/content/res/TypedArray.java
@@ -61,15 +61,6 @@
         return attrs;
     }
 
-    // STYLE_ prefixed constants are offsets within the typed data array.
-    static final int STYLE_NUM_ENTRIES = 6;
-    static final int STYLE_TYPE = 0;
-    static final int STYLE_DATA = 1;
-    static final int STYLE_ASSET_COOKIE = 2;
-    static final int STYLE_RESOURCE_ID = 3;
-    static final int STYLE_CHANGING_CONFIGURATIONS = 4;
-    static final int STYLE_DENSITY = 5;
-
     private final Resources mResources;
     private DisplayMetrics mMetrics;
     private AssetManager mAssets;
@@ -87,7 +78,7 @@
 
     private void resize(int len) {
         mLength = len;
-        final int dataLen = len * STYLE_NUM_ENTRIES;
+        final int dataLen = len * AssetManager.STYLE_NUM_ENTRIES;
         final int indicesLen = len + 1;
         final VMRuntime runtime = VMRuntime.getRuntime();
         if (mDataAddress == 0 || mData.length < dataLen) {
@@ -175,9 +166,9 @@
             throw new RuntimeException("Cannot make calls to a recycled instance!");
         }
 
-        index *= STYLE_NUM_ENTRIES;
+        index *= AssetManager.STYLE_NUM_ENTRIES;
         final int[] data = mData;
-        final int type = data[index + STYLE_TYPE];
+        final int type = data[index+AssetManager.STYLE_TYPE];
         if (type == TypedValue.TYPE_NULL) {
             return null;
         } else if (type == TypedValue.TYPE_STRING) {
@@ -212,9 +203,9 @@
             throw new RuntimeException("Cannot make calls to a recycled instance!");
         }
 
-        index *= STYLE_NUM_ENTRIES;
+        index *= AssetManager.STYLE_NUM_ENTRIES;
         final int[] data = mData;
-        final int type = data[index + STYLE_TYPE];
+        final int type = data[index+AssetManager.STYLE_TYPE];
         if (type == TypedValue.TYPE_NULL) {
             return null;
         } else if (type == TypedValue.TYPE_STRING) {
@@ -251,13 +242,14 @@
             throw new RuntimeException("Cannot make calls to a recycled instance!");
         }
 
-        index *= STYLE_NUM_ENTRIES;
+        index *= AssetManager.STYLE_NUM_ENTRIES;
         final int[] data = mData;
-        final int type = data[index + STYLE_TYPE];
+        final int type = data[index+AssetManager.STYLE_TYPE];
         if (type == TypedValue.TYPE_STRING) {
-            final int cookie = data[index + STYLE_ASSET_COOKIE];
+            final int cookie = data[index+AssetManager.STYLE_ASSET_COOKIE];
             if (cookie < 0) {
-                return mXml.getPooledString(data[index + STYLE_DATA]).toString();
+                return mXml.getPooledString(
+                    data[index+AssetManager.STYLE_DATA]).toString();
             }
         }
         return null;
@@ -282,11 +274,11 @@
             throw new RuntimeException("Cannot make calls to a recycled instance!");
         }
 
-        index *= STYLE_NUM_ENTRIES;
+        index *= AssetManager.STYLE_NUM_ENTRIES;
         final int[] data = mData;
-        final int type = data[index + STYLE_TYPE];
+        final int type = data[index+AssetManager.STYLE_TYPE];
         final @Config int changingConfigs = ActivityInfo.activityInfoConfigNativeToJava(
-                data[index + STYLE_CHANGING_CONFIGURATIONS]);
+                data[index + AssetManager.STYLE_CHANGING_CONFIGURATIONS]);
         if ((changingConfigs & ~allowedChangingConfigs) != 0) {
             return null;
         }
@@ -328,14 +320,14 @@
             throw new RuntimeException("Cannot make calls to a recycled instance!");
         }
 
-        index *= STYLE_NUM_ENTRIES;
+        index *= AssetManager.STYLE_NUM_ENTRIES;
         final int[] data = mData;
-        final int type = data[index + STYLE_TYPE];
+        final int type = data[index+AssetManager.STYLE_TYPE];
         if (type == TypedValue.TYPE_NULL) {
             return defValue;
         } else if (type >= TypedValue.TYPE_FIRST_INT
                 && type <= TypedValue.TYPE_LAST_INT) {
-            return data[index + STYLE_DATA] != 0;
+            return data[index+AssetManager.STYLE_DATA] != 0;
         }
 
         final TypedValue v = mValue;
@@ -367,14 +359,14 @@
             throw new RuntimeException("Cannot make calls to a recycled instance!");
         }
 
-        index *= STYLE_NUM_ENTRIES;
+        index *= AssetManager.STYLE_NUM_ENTRIES;
         final int[] data = mData;
-        final int type = data[index + STYLE_TYPE];
+        final int type = data[index+AssetManager.STYLE_TYPE];
         if (type == TypedValue.TYPE_NULL) {
             return defValue;
         } else if (type >= TypedValue.TYPE_FIRST_INT
                 && type <= TypedValue.TYPE_LAST_INT) {
-            return data[index + STYLE_DATA];
+            return data[index+AssetManager.STYLE_DATA];
         }
 
         final TypedValue v = mValue;
@@ -404,16 +396,16 @@
             throw new RuntimeException("Cannot make calls to a recycled instance!");
         }
 
-        index *= STYLE_NUM_ENTRIES;
+        index *= AssetManager.STYLE_NUM_ENTRIES;
         final int[] data = mData;
-        final int type = data[index + STYLE_TYPE];
+        final int type = data[index+AssetManager.STYLE_TYPE];
         if (type == TypedValue.TYPE_NULL) {
             return defValue;
         } else if (type == TypedValue.TYPE_FLOAT) {
-            return Float.intBitsToFloat(data[index + STYLE_DATA]);
+            return Float.intBitsToFloat(data[index+AssetManager.STYLE_DATA]);
         } else if (type >= TypedValue.TYPE_FIRST_INT
                 && type <= TypedValue.TYPE_LAST_INT) {
-            return data[index + STYLE_DATA];
+            return data[index+AssetManager.STYLE_DATA];
         }
 
         final TypedValue v = mValue;
@@ -454,15 +446,15 @@
         }
 
         final int attrIndex = index;
-        index *= STYLE_NUM_ENTRIES;
+        index *= AssetManager.STYLE_NUM_ENTRIES;
 
         final int[] data = mData;
-        final int type = data[index + STYLE_TYPE];
+        final int type = data[index+AssetManager.STYLE_TYPE];
         if (type == TypedValue.TYPE_NULL) {
             return defValue;
         } else if (type >= TypedValue.TYPE_FIRST_INT
                 && type <= TypedValue.TYPE_LAST_INT) {
-            return data[index + STYLE_DATA];
+            return data[index+AssetManager.STYLE_DATA];
         } else if (type == TypedValue.TYPE_STRING) {
             final TypedValue value = mValue;
             if (getValueAt(index, value)) {
@@ -506,7 +498,7 @@
         }
 
         final TypedValue value = mValue;
-        if (getValueAt(index * STYLE_NUM_ENTRIES, value)) {
+        if (getValueAt(index*AssetManager.STYLE_NUM_ENTRIES, value)) {
             if (value.type == TypedValue.TYPE_ATTRIBUTE) {
                 throw new UnsupportedOperationException(
                         "Failed to resolve attribute at index " + index + ": " + value);
@@ -541,7 +533,7 @@
         }
 
         final TypedValue value = mValue;
-        if (getValueAt(index * STYLE_NUM_ENTRIES, value)) {
+        if (getValueAt(index*AssetManager.STYLE_NUM_ENTRIES, value)) {
             if (value.type == TypedValue.TYPE_ATTRIBUTE) {
                 throw new UnsupportedOperationException(
                         "Failed to resolve attribute at index " + index + ": " + value);
@@ -572,15 +564,15 @@
         }
 
         final int attrIndex = index;
-        index *= STYLE_NUM_ENTRIES;
+        index *= AssetManager.STYLE_NUM_ENTRIES;
 
         final int[] data = mData;
-        final int type = data[index + STYLE_TYPE];
+        final int type = data[index+AssetManager.STYLE_TYPE];
         if (type == TypedValue.TYPE_NULL) {
             return defValue;
         } else if (type >= TypedValue.TYPE_FIRST_INT
                 && type <= TypedValue.TYPE_LAST_INT) {
-            return data[index + STYLE_DATA];
+            return data[index+AssetManager.STYLE_DATA];
         } else if (type == TypedValue.TYPE_ATTRIBUTE) {
             final TypedValue value = mValue;
             getValueAt(index, value);
@@ -620,14 +612,15 @@
         }
 
         final int attrIndex = index;
-        index *= STYLE_NUM_ENTRIES;
+        index *= AssetManager.STYLE_NUM_ENTRIES;
 
         final int[] data = mData;
-        final int type = data[index + STYLE_TYPE];
+        final int type = data[index+AssetManager.STYLE_TYPE];
         if (type == TypedValue.TYPE_NULL) {
             return defValue;
         } else if (type == TypedValue.TYPE_DIMENSION) {
-            return TypedValue.complexToDimension(data[index + STYLE_DATA], mMetrics);
+            return TypedValue.complexToDimension(
+                    data[index + AssetManager.STYLE_DATA], mMetrics);
         } else if (type == TypedValue.TYPE_ATTRIBUTE) {
             final TypedValue value = mValue;
             getValueAt(index, value);
@@ -668,14 +661,15 @@
         }
 
         final int attrIndex = index;
-        index *= STYLE_NUM_ENTRIES;
+        index *= AssetManager.STYLE_NUM_ENTRIES;
 
         final int[] data = mData;
-        final int type = data[index + STYLE_TYPE];
+        final int type = data[index+AssetManager.STYLE_TYPE];
         if (type == TypedValue.TYPE_NULL) {
             return defValue;
         } else if (type == TypedValue.TYPE_DIMENSION) {
-            return TypedValue.complexToDimensionPixelOffset(data[index + STYLE_DATA], mMetrics);
+            return TypedValue.complexToDimensionPixelOffset(
+                    data[index + AssetManager.STYLE_DATA], mMetrics);
         } else if (type == TypedValue.TYPE_ATTRIBUTE) {
             final TypedValue value = mValue;
             getValueAt(index, value);
@@ -717,14 +711,15 @@
         }
 
         final int attrIndex = index;
-        index *= STYLE_NUM_ENTRIES;
+        index *= AssetManager.STYLE_NUM_ENTRIES;
 
         final int[] data = mData;
-        final int type = data[index + STYLE_TYPE];
+        final int type = data[index+AssetManager.STYLE_TYPE];
         if (type == TypedValue.TYPE_NULL) {
             return defValue;
         } else if (type == TypedValue.TYPE_DIMENSION) {
-            return TypedValue.complexToDimensionPixelSize(data[index + STYLE_DATA], mMetrics);
+            return TypedValue.complexToDimensionPixelSize(
+                data[index+AssetManager.STYLE_DATA], mMetrics);
         } else if (type == TypedValue.TYPE_ATTRIBUTE) {
             final TypedValue value = mValue;
             getValueAt(index, value);
@@ -760,15 +755,16 @@
         }
 
         final int attrIndex = index;
-        index *= STYLE_NUM_ENTRIES;
+        index *= AssetManager.STYLE_NUM_ENTRIES;
 
         final int[] data = mData;
-        final int type = data[index + STYLE_TYPE];
+        final int type = data[index+AssetManager.STYLE_TYPE];
         if (type >= TypedValue.TYPE_FIRST_INT
                 && type <= TypedValue.TYPE_LAST_INT) {
-            return data[index + STYLE_DATA];
+            return data[index+AssetManager.STYLE_DATA];
         } else if (type == TypedValue.TYPE_DIMENSION) {
-            return TypedValue.complexToDimensionPixelSize(data[index + STYLE_DATA], mMetrics);
+            return TypedValue.complexToDimensionPixelSize(
+                data[index+AssetManager.STYLE_DATA], mMetrics);
         } else if (type == TypedValue.TYPE_ATTRIBUTE) {
             final TypedValue value = mValue;
             getValueAt(index, value);
@@ -799,14 +795,15 @@
             throw new RuntimeException("Cannot make calls to a recycled instance!");
         }
 
-        index *= STYLE_NUM_ENTRIES;
+        index *= AssetManager.STYLE_NUM_ENTRIES;
         final int[] data = mData;
-        final int type = data[index + STYLE_TYPE];
+        final int type = data[index+AssetManager.STYLE_TYPE];
         if (type >= TypedValue.TYPE_FIRST_INT
                 && type <= TypedValue.TYPE_LAST_INT) {
-            return data[index + STYLE_DATA];
+            return data[index+AssetManager.STYLE_DATA];
         } else if (type == TypedValue.TYPE_DIMENSION) {
-            return TypedValue.complexToDimensionPixelSize(data[index + STYLE_DATA], mMetrics);
+            return TypedValue.complexToDimensionPixelSize(
+                    data[index + AssetManager.STYLE_DATA], mMetrics);
         }
 
         return defValue;
@@ -836,14 +833,15 @@
         }
 
         final int attrIndex = index;
-        index *= STYLE_NUM_ENTRIES;
+        index *= AssetManager.STYLE_NUM_ENTRIES;
 
         final int[] data = mData;
-        final int type = data[index + STYLE_TYPE];
+        final int type = data[index+AssetManager.STYLE_TYPE];
         if (type == TypedValue.TYPE_NULL) {
             return defValue;
         } else if (type == TypedValue.TYPE_FRACTION) {
-            return TypedValue.complexToFraction(data[index + STYLE_DATA], base, pbase);
+            return TypedValue.complexToFraction(
+                data[index+AssetManager.STYLE_DATA], base, pbase);
         } else if (type == TypedValue.TYPE_ATTRIBUTE) {
             final TypedValue value = mValue;
             getValueAt(index, value);
@@ -876,10 +874,10 @@
             throw new RuntimeException("Cannot make calls to a recycled instance!");
         }
 
-        index *= STYLE_NUM_ENTRIES;
+        index *= AssetManager.STYLE_NUM_ENTRIES;
         final int[] data = mData;
-        if (data[index + STYLE_TYPE] != TypedValue.TYPE_NULL) {
-            final int resid = data[index + STYLE_RESOURCE_ID];
+        if (data[index+AssetManager.STYLE_TYPE] != TypedValue.TYPE_NULL) {
+            final int resid = data[index+AssetManager.STYLE_RESOURCE_ID];
             if (resid != 0) {
                 return resid;
             }
@@ -904,10 +902,10 @@
             throw new RuntimeException("Cannot make calls to a recycled instance!");
         }
 
-        index *= STYLE_NUM_ENTRIES;
+        index *= AssetManager.STYLE_NUM_ENTRIES;
         final int[] data = mData;
-        if (data[index + STYLE_TYPE] == TypedValue.TYPE_ATTRIBUTE) {
-            return data[index + STYLE_DATA];
+        if (data[index + AssetManager.STYLE_TYPE] == TypedValue.TYPE_ATTRIBUTE) {
+            return data[index + AssetManager.STYLE_DATA];
         }
         return defValue;
     }
@@ -941,7 +939,7 @@
         }
 
         final TypedValue value = mValue;
-        if (getValueAt(index * STYLE_NUM_ENTRIES, value)) {
+        if (getValueAt(index*AssetManager.STYLE_NUM_ENTRIES, value)) {
             if (value.type == TypedValue.TYPE_ATTRIBUTE) {
                 throw new UnsupportedOperationException(
                         "Failed to resolve attribute at index " + index + ": " + value);
@@ -977,7 +975,7 @@
         }
 
         final TypedValue value = mValue;
-        if (getValueAt(index * STYLE_NUM_ENTRIES, value)) {
+        if (getValueAt(index*AssetManager.STYLE_NUM_ENTRIES, value)) {
             if (value.type == TypedValue.TYPE_ATTRIBUTE) {
                 throw new UnsupportedOperationException(
                         "Failed to resolve attribute at index " + index + ": " + value);
@@ -1008,7 +1006,7 @@
         }
 
         final TypedValue value = mValue;
-        if (getValueAt(index * STYLE_NUM_ENTRIES, value)) {
+        if (getValueAt(index*AssetManager.STYLE_NUM_ENTRIES, value)) {
             return mResources.getTextArray(value.resourceId);
         }
         return null;
@@ -1029,7 +1027,7 @@
             throw new RuntimeException("Cannot make calls to a recycled instance!");
         }
 
-        return getValueAt(index * STYLE_NUM_ENTRIES, outValue);
+        return getValueAt(index*AssetManager.STYLE_NUM_ENTRIES, outValue);
     }
 
     /**
@@ -1045,8 +1043,8 @@
             throw new RuntimeException("Cannot make calls to a recycled instance!");
         }
 
-        index *= STYLE_NUM_ENTRIES;
-        return mData[index + STYLE_TYPE];
+        index *= AssetManager.STYLE_NUM_ENTRIES;
+        return mData[index + AssetManager.STYLE_TYPE];
     }
 
     /**
@@ -1065,9 +1063,9 @@
             throw new RuntimeException("Cannot make calls to a recycled instance!");
         }
 
-        index *= STYLE_NUM_ENTRIES;
+        index *= AssetManager.STYLE_NUM_ENTRIES;
         final int[] data = mData;
-        final int type = data[index + STYLE_TYPE];
+        final int type = data[index+AssetManager.STYLE_TYPE];
         return type != TypedValue.TYPE_NULL;
     }
 
@@ -1086,11 +1084,11 @@
             throw new RuntimeException("Cannot make calls to a recycled instance!");
         }
 
-        index *= STYLE_NUM_ENTRIES;
+        index *= AssetManager.STYLE_NUM_ENTRIES;
         final int[] data = mData;
-        final int type = data[index + STYLE_TYPE];
+        final int type = data[index+AssetManager.STYLE_TYPE];
         return type != TypedValue.TYPE_NULL
-                || data[index + STYLE_DATA] == TypedValue.DATA_NULL_EMPTY;
+                || data[index+AssetManager.STYLE_DATA] == TypedValue.DATA_NULL_EMPTY;
     }
 
     /**
@@ -1111,7 +1109,7 @@
         }
 
         final TypedValue value = mValue;
-        if (getValueAt(index * STYLE_NUM_ENTRIES, value)) {
+        if (getValueAt(index*AssetManager.STYLE_NUM_ENTRIES, value)) {
             return value;
         }
         return null;
@@ -1183,16 +1181,16 @@
         final int[] data = mData;
         final int N = length();
         for (int i = 0; i < N; i++) {
-            final int index = i * STYLE_NUM_ENTRIES;
-            if (data[index + STYLE_TYPE] != TypedValue.TYPE_ATTRIBUTE) {
+            final int index = i * AssetManager.STYLE_NUM_ENTRIES;
+            if (data[index + AssetManager.STYLE_TYPE] != TypedValue.TYPE_ATTRIBUTE) {
                 // Not an attribute, ignore.
                 continue;
             }
 
             // Null the entry so that we can safely call getZzz().
-            data[index + STYLE_TYPE] = TypedValue.TYPE_NULL;
+            data[index + AssetManager.STYLE_TYPE] = TypedValue.TYPE_NULL;
 
-            final int attr = data[index + STYLE_DATA];
+            final int attr = data[index + AssetManager.STYLE_DATA];
             if (attr == 0) {
                 // Useless data, ignore.
                 continue;
@@ -1233,44 +1231,45 @@
         final int[] data = mData;
         final int N = length();
         for (int i = 0; i < N; i++) {
-            final int index = i * STYLE_NUM_ENTRIES;
-            final int type = data[index + STYLE_TYPE];
+            final int index = i * AssetManager.STYLE_NUM_ENTRIES;
+            final int type = data[index + AssetManager.STYLE_TYPE];
             if (type == TypedValue.TYPE_NULL) {
                 continue;
             }
             changingConfig |= ActivityInfo.activityInfoConfigNativeToJava(
-                    data[index + STYLE_CHANGING_CONFIGURATIONS]);
+                    data[index + AssetManager.STYLE_CHANGING_CONFIGURATIONS]);
         }
         return changingConfig;
     }
 
     private boolean getValueAt(int index, TypedValue outValue) {
         final int[] data = mData;
-        final int type = data[index + STYLE_TYPE];
+        final int type = data[index+AssetManager.STYLE_TYPE];
         if (type == TypedValue.TYPE_NULL) {
             return false;
         }
         outValue.type = type;
-        outValue.data = data[index + STYLE_DATA];
-        outValue.assetCookie = data[index + STYLE_ASSET_COOKIE];
-        outValue.resourceId = data[index + STYLE_RESOURCE_ID];
+        outValue.data = data[index+AssetManager.STYLE_DATA];
+        outValue.assetCookie = data[index+AssetManager.STYLE_ASSET_COOKIE];
+        outValue.resourceId = data[index+AssetManager.STYLE_RESOURCE_ID];
         outValue.changingConfigurations = ActivityInfo.activityInfoConfigNativeToJava(
-                data[index + STYLE_CHANGING_CONFIGURATIONS]);
-        outValue.density = data[index + STYLE_DENSITY];
+                data[index + AssetManager.STYLE_CHANGING_CONFIGURATIONS]);
+        outValue.density = data[index+AssetManager.STYLE_DENSITY];
         outValue.string = (type == TypedValue.TYPE_STRING) ? loadStringValueAt(index) : null;
         return true;
     }
 
     private CharSequence loadStringValueAt(int index) {
         final int[] data = mData;
-        final int cookie = data[index + STYLE_ASSET_COOKIE];
+        final int cookie = data[index+AssetManager.STYLE_ASSET_COOKIE];
         if (cookie < 0) {
             if (mXml != null) {
-                return mXml.getPooledString(data[index + STYLE_DATA]);
+                return mXml.getPooledString(
+                    data[index+AssetManager.STYLE_DATA]);
             }
             return null;
         }
-        return mAssets.getPooledStringForCookie(cookie, data[index + STYLE_DATA]);
+        return mAssets.getPooledStringForCookie(cookie, data[index+AssetManager.STYLE_DATA]);
     }
 
     /** @hide */
diff --git a/core/java/android/content/res/XmlBlock.java b/core/java/android/content/res/XmlBlock.java
index d4ccffb..e6b95741 100644
--- a/core/java/android/content/res/XmlBlock.java
+++ b/core/java/android/content/res/XmlBlock.java
@@ -16,7 +16,6 @@
 
 package android.content.res;
 
-import android.annotation.Nullable;
 import android.util.TypedValue;
 
 import com.android.internal.util.XmlUtils;
@@ -34,7 +33,7 @@
  * 
  * {@hide}
  */
-final class XmlBlock implements AutoCloseable {
+final class XmlBlock {
     private static final boolean DEBUG=false;
 
     public XmlBlock(byte[] data) {
@@ -49,7 +48,6 @@
         mStrings = new StringBlock(nativeGetStringBlock(mNative), false);
     }
 
-    @Override
     public void close() {
         synchronized (this) {
             if (mOpen) {
@@ -480,13 +478,13 @@
      *  are doing!  The given native object must exist for the entire lifetime
      *  of this newly creating XmlBlock.
      */
-    XmlBlock(@Nullable AssetManager assets, long xmlBlock) {
+    XmlBlock(AssetManager assets, long xmlBlock) {
         mAssets = assets;
         mNative = xmlBlock;
         mStrings = new StringBlock(nativeGetStringBlock(xmlBlock), false);
     }
 
-    private @Nullable final AssetManager mAssets;
+    private final AssetManager mAssets;
     private final long mNative;
     /*package*/ final StringBlock mStrings;
     private boolean mOpen = true;
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index 96d043c..3f8eaa9 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -1372,9 +1372,6 @@
      * <p>The origin for {@link CameraCharacteristics#LENS_POSE_TRANSLATION android.lens.poseTranslation}.</p>
      * <p>Different calibration methods and use cases can produce better or worse results
      * depending on the selected coordinate origin.</p>
-     * <p>For devices designed to support the MOTION_TRACKING capability, the GYROSCOPE origin
-     * makes device calibration and later usage by applications combining camera and gyroscope
-     * information together simpler.</p>
      * <p><b>Possible values:</b>
      * <ul>
      *   <li>{@link #LENS_POSE_REFERENCE_PRIMARY_CAMERA PRIMARY_CAMERA}</li>
diff --git a/core/java/android/hardware/camera2/CameraDevice.java b/core/java/android/hardware/camera2/CameraDevice.java
index df64401..fd285ae 100644
--- a/core/java/android/hardware/camera2/CameraDevice.java
+++ b/core/java/android/hardware/camera2/CameraDevice.java
@@ -145,37 +145,6 @@
      */
     public static final int TEMPLATE_MANUAL = 6;
 
-    /**
-     * A template for selecting camera parameters that match TEMPLATE_PREVIEW as closely as
-     * possible while improving the camera output for motion tracking use cases.
-     *
-     * <p>This template is best used by applications that are frequently switching between motion
-     * tracking use cases and regular still capture use cases, to minimize the IQ changes
-     * when swapping use cases.</p>
-     *
-     * <p>This template is guaranteed to be supported on camera devices that support the
-     * {@link CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_MOTION_TRACKING MOTION_TRACKING}
-     * capability.</p>
-     *
-     * @see #createCaptureRequest
-     */
-    public static final int TEMPLATE_MOTION_TRACKING_PREVIEW = 7;
-
-    /**
-     * A template for selecting camera parameters that maximize the quality of camera output for
-     * motion tracking use cases.
-     *
-     * <p>This template is best used by applications dedicated to motion tracking applications,
-     * which aren't concerned about fast switches between motion tracking and other use cases.</p>
-     *
-     * <p>This template is guaranteed to be supported on camera devices that support the
-     * {@link CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_MOTION_TRACKING MOTION_TRACKING}
-     * capability.</p>
-     *
-     * @see #createCaptureRequest
-     */
-    public static final int TEMPLATE_MOTION_TRACKING_BEST = 8;
-
      /** @hide */
      @Retention(RetentionPolicy.SOURCE)
      @IntDef(prefix = {"TEMPLATE_"}, value =
@@ -184,9 +153,7 @@
           TEMPLATE_RECORD,
           TEMPLATE_VIDEO_SNAPSHOT,
           TEMPLATE_ZERO_SHUTTER_LAG,
-          TEMPLATE_MANUAL,
-          TEMPLATE_MOTION_TRACKING_PREVIEW,
-          TEMPLATE_MOTION_TRACKING_BEST})
+          TEMPLATE_MANUAL})
      public @interface RequestTemplate {};
 
     /**
@@ -420,27 +387,6 @@
      * </table><br>
      * </p>
      *
-     * <p>MOTION_TRACKING-capability ({@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES}
-     * includes
-     * {@link CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_MOTION_TRACKING MOTION_TRACKING})
-     * devices support at least the below stream combinations in addition to those for
-     * {@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED LIMITED} devices. The
-     * {@code FULL FOV 640} entry means that the device will support a resolution that's 640 pixels
-     * wide, with the height set so that the resolution aspect ratio matches the MAXIMUM output
-     * aspect ratio, rounded down.  So for a device with a 4:3 image sensor, this will be 640x480,
-     * and for a device with a 16:9 sensor, this will be 640x360, and so on. And the
-     * {@code MAX 30FPS} entry means the largest JPEG resolution on the device for which
-     * {@link android.hardware.camera2.params.StreamConfigurationMap#getOutputMinFrameDuration}
-     * returns a value less than or equal to 1/30s.
-     *
-     * <table>
-     * <tr><th colspan="7">MOTION_TRACKING-capability additional guaranteed configurations</th></tr>
-     * <tr><th colspan="2" id="rb">Target 1</th><th colspan="2" id="rb">Target 2</th><th colspan="2" id="rb">Target 3</th><th rowspan="2">Sample use case(s)</th> </tr>
-     * <tr><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th></tr>
-     * <tr> <td>{@code YUV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV }</td><td id="rb">{@code FULL FOV 640}</td> <td>{@code JPEG}</td><td id="rb">{@code MAX 30FPS}</td> <td>Preview with a tracking YUV output and a as-large-as-possible JPEG for still captures.</td> </tr>
-     * </table><br>
-     * </p>
-     *
      * <p>BURST-capability ({@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES} includes
      * {@link CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE BURST_CAPTURE}) devices
      * support at least the below stream combinations in addition to those for
diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java
index e7c8961..732f6a5 100644
--- a/core/java/android/hardware/camera2/CameraMetadata.java
+++ b/core/java/android/hardware/camera2/CameraMetadata.java
@@ -342,7 +342,7 @@
     /**
      * <p>The value of {@link CameraCharacteristics#LENS_POSE_TRANSLATION android.lens.poseTranslation} is relative to the optical center of
      * the largest camera device facing the same direction as this camera.</p>
-     * <p>This default value for API levels before Android P.</p>
+     * <p>This is the default value for API levels before Android P.</p>
      *
      * @see CameraCharacteristics#LENS_POSE_TRANSLATION
      * @see CameraCharacteristics#LENS_POSE_REFERENCE
@@ -352,7 +352,6 @@
     /**
      * <p>The value of {@link CameraCharacteristics#LENS_POSE_TRANSLATION android.lens.poseTranslation} is relative to the position of the
      * primary gyroscope of this Android device.</p>
-     * <p>This is the value reported by all devices that support the MOTION_TRACKING capability.</p>
      *
      * @see CameraCharacteristics#LENS_POSE_TRANSLATION
      * @see CameraCharacteristics#LENS_POSE_REFERENCE
@@ -801,46 +800,12 @@
     public static final int REQUEST_AVAILABLE_CAPABILITIES_CONSTRAINED_HIGH_SPEED_VIDEO = 9;
 
     /**
-     * <p>The device supports controls and metadata required for accurate motion tracking for
-     * use cases such as augmented reality, electronic image stabilization, and so on.</p>
-     * <p>This means this camera device has accurate optical calibration and timestamps relative
-     * to the inertial sensors.</p>
-     * <p>This capability requires the camera device to support the following:</p>
-     * <ul>
-     * <li>Capture request templates {@link android.hardware.camera2.CameraDevice#TEMPLATE_MOTION_TRACKING_PREVIEW } and {@link android.hardware.camera2.CameraDevice#TEMPLATE_MOTION_TRACKING_BEST } are defined.</li>
-     * <li>The stream configurations listed in {@link android.hardware.camera2.CameraDevice#createCaptureSession } for MOTION_TRACKING are
-     *   supported, either at 30 or 60fps maximum frame rate.</li>
-     * <li>The following camera characteristics and capture result metadata are provided:<ul>
-     * <li>{@link CameraCharacteristics#LENS_INTRINSIC_CALIBRATION android.lens.intrinsicCalibration}</li>
-     * <li>{@link CameraCharacteristics#LENS_RADIAL_DISTORTION android.lens.radialDistortion}</li>
-     * <li>{@link CameraCharacteristics#LENS_POSE_ROTATION android.lens.poseRotation}</li>
-     * <li>{@link CameraCharacteristics#LENS_POSE_TRANSLATION android.lens.poseTranslation}</li>
-     * <li>{@link CameraCharacteristics#LENS_POSE_REFERENCE android.lens.poseReference} with value GYROSCOPE</li>
-     * </ul>
-     * </li>
-     * <li>The {@link CameraCharacteristics#SENSOR_INFO_TIMESTAMP_SOURCE android.sensor.info.timestampSource} field has value <code>REALTIME</code>. When compared to
-     *   timestamps from the device's gyroscopes, the clock difference for events occuring at
-     *   the same actual time instant will be less than 1 ms.</li>
-     * <li>The value of the {@link CaptureResult#SENSOR_ROLLING_SHUTTER_SKEW android.sensor.rollingShutterSkew} field is accurate to within 1 ms.</li>
-     * <li>The value of {@link CaptureRequest#SENSOR_EXPOSURE_TIME android.sensor.exposureTime} is guaranteed to be available in the
-     *   capture result.</li>
-     * <li>The {@link CaptureRequest#CONTROL_CAPTURE_INTENT android.control.captureIntent} control supports MOTION_TRACKING to limit maximum
-     *   exposure to 20 milliseconds.</li>
-     * <li>The stream configurations required for MOTION_TRACKING (listed at {@link android.hardware.camera2.CameraDevice#createCaptureSession }) can operate at least at
-     *   30fps; optionally, they can operate at 60fps, and '[60, 60]' is listed in
-     *   {@link CameraCharacteristics#CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES android.control.aeAvailableTargetFpsRanges}.</li>
-     * </ul>
+     * <p>The camera device supports the MOTION_TRACKING value for
+     * {@link CaptureRequest#CONTROL_CAPTURE_INTENT android.control.captureIntent}, which limits maximum exposure time to 20 ms.</p>
+     * <p>This limits the motion blur of capture images, resulting in better image tracking
+     * results for use cases such as image stabilization or augmented reality.</p>
      *
-     * @see CameraCharacteristics#CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES
      * @see CaptureRequest#CONTROL_CAPTURE_INTENT
-     * @see CameraCharacteristics#LENS_INTRINSIC_CALIBRATION
-     * @see CameraCharacteristics#LENS_POSE_REFERENCE
-     * @see CameraCharacteristics#LENS_POSE_ROTATION
-     * @see CameraCharacteristics#LENS_POSE_TRANSLATION
-     * @see CameraCharacteristics#LENS_RADIAL_DISTORTION
-     * @see CaptureRequest#SENSOR_EXPOSURE_TIME
-     * @see CameraCharacteristics#SENSOR_INFO_TIMESTAMP_SOURCE
-     * @see CaptureResult#SENSOR_ROLLING_SHUTTER_SKEW
      * @see CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES
      */
     public static final int REQUEST_AVAILABLE_CAPABILITIES_MOTION_TRACKING = 10;
diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java
index 481b764..3ed533a 100644
--- a/core/java/android/hardware/camera2/CaptureRequest.java
+++ b/core/java/android/hardware/camera2/CaptureRequest.java
@@ -2757,11 +2757,11 @@
             new Key<Integer>("android.statistics.lensShadingMapMode", int.class);
 
     /**
-     * <p>Whether the camera device outputs the OIS data in output
+     * <p>A control for selecting whether OIS position information is included in output
      * result metadata.</p>
      * <p>When set to ON,
      * {@link CaptureResult#STATISTICS_OIS_TIMESTAMPS android.statistics.oisTimestamps}, android.statistics.oisShiftPixelX,
-     * android.statistics.oisShiftPixelY will provide OIS data in the output result metadata.</p>
+     * and android.statistics.oisShiftPixelY provide OIS data in the output result metadata.</p>
      * <p><b>Possible values:</b>
      * <ul>
      *   <li>{@link #STATISTICS_OIS_DATA_MODE_OFF OFF}</li>
diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java
index d730fa8..c332d30 100644
--- a/core/java/android/hardware/camera2/CaptureResult.java
+++ b/core/java/android/hardware/camera2/CaptureResult.java
@@ -3909,11 +3909,11 @@
             new Key<Integer>("android.statistics.lensShadingMapMode", int.class);
 
     /**
-     * <p>Whether the camera device outputs the OIS data in output
+     * <p>A control for selecting whether OIS position information is included in output
      * result metadata.</p>
      * <p>When set to ON,
      * {@link CaptureResult#STATISTICS_OIS_TIMESTAMPS android.statistics.oisTimestamps}, android.statistics.oisShiftPixelX,
-     * android.statistics.oisShiftPixelY will provide OIS data in the output result metadata.</p>
+     * and android.statistics.oisShiftPixelY provide OIS data in the output result metadata.</p>
      * <p><b>Possible values:</b>
      * <ul>
      *   <li>{@link #STATISTICS_OIS_DATA_MODE_OFF OFF}</li>
diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java
index 24a078f..b609847 100644
--- a/core/java/android/net/IpSecManager.java
+++ b/core/java/android/net/IpSecManager.java
@@ -19,6 +19,7 @@
 
 import android.annotation.IntDef;
 import android.annotation.NonNull;
+import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
 import android.annotation.TestApi;
@@ -761,6 +762,7 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.NETWORK_STACK)
     public IpSecTunnelInterface createIpSecTunnelInterface(@NonNull InetAddress localAddress,
             @NonNull InetAddress remoteAddress, @NonNull Network underlyingNetwork)
             throws ResourceUnavailableException, IOException {
@@ -780,6 +782,7 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.NETWORK_STACK)
     public void applyTunnelModeTransform(IpSecTunnelInterface tunnel, int direction,
             IpSecTransform transform) throws IOException {
         try {
diff --git a/core/java/android/net/IpSecTransform.java b/core/java/android/net/IpSecTransform.java
index 0829b4a..38759a9 100644
--- a/core/java/android/net/IpSecTransform.java
+++ b/core/java/android/net/IpSecTransform.java
@@ -21,6 +21,7 @@
 
 import android.annotation.IntDef;
 import android.annotation.NonNull;
+import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.content.Context;
 import android.os.Binder;
@@ -266,6 +267,10 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.NETWORK_STACK,
+            android.Manifest.permission.PACKET_KEEPALIVE_OFFLOAD
+    })
     public void startNattKeepalive(@NonNull NattKeepaliveCallback userCallback,
             int intervalSeconds, @NonNull Handler handler) throws IOException {
         checkNotNull(userCallback);
@@ -305,6 +310,10 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.NETWORK_STACK,
+            android.Manifest.permission.PACKET_KEEPALIVE_OFFLOAD
+    })
     public void stopNattKeepalive() {
         synchronized (mKeepaliveCallback) {
             if (mKeepalive == null) {
@@ -449,6 +458,7 @@
          * @hide
          */
         @SystemApi
+        @RequiresPermission(android.Manifest.permission.NETWORK_STACK)
         public IpSecTransform buildTunnelModeTransform(
                 @NonNull InetAddress sourceAddress,
                 @NonNull IpSecManager.SecurityParameterIndex spi)
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index fc78861..48f5684 100644
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -894,14 +894,6 @@
 
         /**
          * P.
-         *
-         * <p>Applications targeting this or a later release will get these
-         * new changes in behavior:</p>
-         * <ul>
-         * <li>{@link android.app.Service#startForeground Service.startForeground} requires
-         * that apps hold the permission
-         * {@link android.Manifest.permission#FOREGROUND_SERVICE}.</li>
-         * </ul>
          */
         public static final int P = CUR_DEVELOPMENT; // STOPSHIP Replace with the real version.
     }
diff --git a/core/java/android/os/UpdateEngine.java b/core/java/android/os/UpdateEngine.java
index c6149be..24c9c91 100644
--- a/core/java/android/os/UpdateEngine.java
+++ b/core/java/android/os/UpdateEngine.java
@@ -271,4 +271,22 @@
             }
         }
     }
+
+    /**
+     * Verifies that a payload associated with the given payload metadata
+     * {@code payloadMetadataFilename} can be safely applied to ths device.
+     * Returns {@code true} if the update can successfully be applied and
+     * returns {@code false} otherwise.
+     *
+     * @param payloadMetadataFilename the location of the metadata without the
+     * {@code file://} prefix.
+     */
+    @SystemApi
+    public boolean verifyPayloadMetadata(String payloadMetadataFilename) {
+        try {
+            return mUpdateEngine.verifyPayloadApplicable(payloadMetadataFilename);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
 }
diff --git a/core/java/android/preference/OWNERS b/core/java/android/preference/OWNERS
new file mode 100644
index 0000000..d20511f
--- /dev/null
+++ b/core/java/android/preference/OWNERS
@@ -0,0 +1,2 @@
+pavlis@google.com
+clarabayarri@google.com
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 84996e0..fef6495 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -8563,9 +8563,8 @@
          *
          * @see android.service.euicc.EuiccService
          * @hide
-         *
-         * TODO(b/35851809): Make this a SystemApi.
          */
+        @SystemApi
         public static final String DEFAULT_SM_DP_PLUS = "default_sm_dp_plus";
 
         /**
@@ -10506,6 +10505,16 @@
         public static final String BATTERY_STATS_CONSTANTS = "battery_stats_constants";
 
         /**
+         * SyncManager specific settings.
+         *
+         * <p>
+         * Type: string
+         * @hide
+         * @see com.android.server.content.SyncManagerConstants
+         */
+        public static final String SYNC_MANAGER_CONSTANTS = "sync_manager_constants";
+
+        /**
          * Whether or not App Standby feature is enabled. This controls throttling of apps
          * based on usage patterns and predictions.
          * Type: int (0 for false, 1 for true)
@@ -12089,11 +12098,22 @@
                 "zram_enabled";
 
         /**
-         * Whether smart replies in notifications are enabled.
+         * Configuration flags for smart replies in notifications.
+         * This is encoded as a key=value list, separated by commas. Ex:
+         *
+         * "enabled=1,max_squeeze_remeasure_count=3"
+         *
+         * The following keys are supported:
+         *
+         * <pre>
+         * enabled                         (boolean)
+         * max_squeeze_remeasure_attempts  (int)
+         * </pre>
+         * @see com.android.systemui.statusbar.policy.SmartReplyConstants
          * @hide
          */
-        public static final String ENABLE_SMART_REPLIES_IN_NOTIFICATIONS =
-                "enable_smart_replies_in_notifications";
+        public static final String SMART_REPLIES_IN_NOTIFICATIONS_FLAGS =
+                "smart_replies_in_notifications_flags";
 
         /**
          * If nonzero, crashes in foreground processes will bring up a dialog.
diff --git a/core/java/android/service/euicc/EuiccProfileInfo.java b/core/java/android/service/euicc/EuiccProfileInfo.java
index 8e752d1..cb4f104 100644
--- a/core/java/android/service/euicc/EuiccProfileInfo.java
+++ b/core/java/android/service/euicc/EuiccProfileInfo.java
@@ -17,6 +17,7 @@
 
 import android.annotation.IntDef;
 import android.annotation.Nullable;
+import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.service.carrier.CarrierIdentifier;
@@ -26,15 +27,15 @@
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.Arrays;
+import java.util.List;
 import java.util.Objects;
 
 /**
  * Information about an embedded profile (subscription) on an eUICC.
  *
  * @hide
- *
- * TODO(b/35851809): Make this a SystemApi.
  */
+@SystemApi
 public final class EuiccProfileInfo implements Parcelable {
 
     /** Profile policy rules (bit mask) */
@@ -44,6 +45,7 @@
             POLICY_RULE_DO_NOT_DELETE,
             POLICY_RULE_DELETE_AFTER_DISABLING
     })
+    /** @hide */
     public @interface PolicyRule {}
     /** Once this profile is enabled, it cannot be disabled. */
     public static final int POLICY_RULE_DO_NOT_DISABLE = 1;
@@ -60,6 +62,7 @@
             PROFILE_CLASS_OPERATIONAL,
             PROFILE_CLASS_UNSET
     })
+    /** @hide */
     public @interface ProfileClass {}
     /** Testing profiles */
     public static final int PROFILE_CLASS_TESTING = 0;
@@ -80,6 +83,7 @@
             PROFILE_STATE_ENABLED,
             PROFILE_STATE_UNSET
     })
+    /** @hide */
     public @interface ProfileState {}
     /** Disabled profiles */
     public static final int PROFILE_STATE_DISABLED = 0;
@@ -92,34 +96,34 @@
     public static final int PROFILE_STATE_UNSET = -1;
 
     /** The iccid of the subscription. */
-    public final String iccid;
+    private final String mIccid;
 
     /** An optional nickname for the subscription. */
-    public final @Nullable String nickname;
+    private final @Nullable String mNickname;
 
     /** The service provider name for the subscription. */
-    public final String serviceProviderName;
+    private final String mServiceProviderName;
 
     /** The profile name for the subscription. */
-    public final String profileName;
+    private final String mProfileName;
 
     /** Profile class for the subscription. */
-    @ProfileClass public final int profileClass;
+    @ProfileClass private final int mProfileClass;
 
     /** The profile state of the subscription. */
-    @ProfileState public final int state;
+    @ProfileState private final int mState;
 
     /** The operator Id of the subscription. */
-    public final CarrierIdentifier carrierIdentifier;
+    private final CarrierIdentifier mCarrierIdentifier;
 
     /** The policy rules of the subscription. */
-    @PolicyRule public final int policyRules;
+    @PolicyRule private final int mPolicyRules;
 
     /**
      * Optional access rules defining which apps can manage this subscription. If unset, only the
      * platform can manage it.
      */
-    public final @Nullable UiccAccessRule[] accessRules;
+    private final @Nullable UiccAccessRule[] mAccessRules;
 
     public static final Creator<EuiccProfileInfo> CREATOR = new Creator<EuiccProfileInfo>() {
         @Override
@@ -144,51 +148,51 @@
         if (!TextUtils.isDigitsOnly(iccid)) {
             throw new IllegalArgumentException("iccid contains invalid characters: " + iccid);
         }
-        this.iccid = iccid;
-        this.accessRules = accessRules;
-        this.nickname = nickname;
+        this.mIccid = iccid;
+        this.mAccessRules = accessRules;
+        this.mNickname = nickname;
 
-        this.serviceProviderName = null;
-        this.profileName = null;
-        this.profileClass = PROFILE_CLASS_UNSET;
-        this.state = PROFILE_CLASS_UNSET;
-        this.carrierIdentifier = null;
-        this.policyRules = 0;
+        this.mServiceProviderName = null;
+        this.mProfileName = null;
+        this.mProfileClass = PROFILE_CLASS_UNSET;
+        this.mState = PROFILE_STATE_UNSET;
+        this.mCarrierIdentifier = null;
+        this.mPolicyRules = 0;
     }
 
     private EuiccProfileInfo(Parcel in) {
-        iccid = in.readString();
-        nickname = in.readString();
-        serviceProviderName = in.readString();
-        profileName = in.readString();
-        profileClass = in.readInt();
-        state = in.readInt();
+        mIccid = in.readString();
+        mNickname = in.readString();
+        mServiceProviderName = in.readString();
+        mProfileName = in.readString();
+        mProfileClass = in.readInt();
+        mState = in.readInt();
         byte exist = in.readByte();
         if (exist == (byte) 1) {
-            carrierIdentifier = CarrierIdentifier.CREATOR.createFromParcel(in);
+            mCarrierIdentifier = CarrierIdentifier.CREATOR.createFromParcel(in);
         } else {
-            carrierIdentifier = null;
+            mCarrierIdentifier = null;
         }
-        policyRules = in.readInt();
-        accessRules = in.createTypedArray(UiccAccessRule.CREATOR);
+        mPolicyRules = in.readInt();
+        mAccessRules = in.createTypedArray(UiccAccessRule.CREATOR);
     }
 
     @Override
     public void writeToParcel(Parcel dest, int flags) {
-        dest.writeString(iccid);
-        dest.writeString(nickname);
-        dest.writeString(serviceProviderName);
-        dest.writeString(profileName);
-        dest.writeInt(profileClass);
-        dest.writeInt(state);
-        if (carrierIdentifier != null) {
+        dest.writeString(mIccid);
+        dest.writeString(mNickname);
+        dest.writeString(mServiceProviderName);
+        dest.writeString(mProfileName);
+        dest.writeInt(mProfileClass);
+        dest.writeInt(mState);
+        if (mCarrierIdentifier != null) {
             dest.writeByte((byte) 1);
-            carrierIdentifier.writeToParcel(dest, flags);
+            mCarrierIdentifier.writeToParcel(dest, flags);
         } else {
             dest.writeByte((byte) 0);
         }
-        dest.writeInt(policyRules);
-        dest.writeTypedArray(accessRules, flags);
+        dest.writeInt(mPolicyRules);
+        dest.writeTypedArray(mAccessRules, flags);
     }
 
     @Override
@@ -198,45 +202,50 @@
 
     /** The builder to build a new {@link EuiccProfileInfo} instance. */
     public static final class Builder {
-        public String iccid;
-        public UiccAccessRule[] accessRules;
-        public String nickname;
-        public String serviceProviderName;
-        public String profileName;
-        @ProfileClass public int profileClass;
-        @ProfileState public int state;
-        public CarrierIdentifier carrierIdentifier;
-        @PolicyRule public int policyRules;
+        private String mIccid;
+        private List<UiccAccessRule> mAccessRules;
+        private String mNickname;
+        private String mServiceProviderName;
+        private String mProfileName;
+        @ProfileClass private int mProfileClass;
+        @ProfileState private int mState;
+        private CarrierIdentifier mCarrierIdentifier;
+        @PolicyRule private int mPolicyRules;
 
-        public Builder() {}
+        public Builder(String value) {
+            if (!TextUtils.isDigitsOnly(value)) {
+                throw new IllegalArgumentException("iccid contains invalid characters: " + value);
+            }
+            mIccid = value;
+        }
 
         public Builder(EuiccProfileInfo baseProfile) {
-            iccid = baseProfile.iccid;
-            nickname = baseProfile.nickname;
-            serviceProviderName = baseProfile.serviceProviderName;
-            profileName = baseProfile.profileName;
-            profileClass = baseProfile.profileClass;
-            state = baseProfile.state;
-            carrierIdentifier = baseProfile.carrierIdentifier;
-            policyRules = baseProfile.policyRules;
-            accessRules = baseProfile.accessRules;
+            mIccid = baseProfile.mIccid;
+            mNickname = baseProfile.mNickname;
+            mServiceProviderName = baseProfile.mServiceProviderName;
+            mProfileName = baseProfile.mProfileName;
+            mProfileClass = baseProfile.mProfileClass;
+            mState = baseProfile.mState;
+            mCarrierIdentifier = baseProfile.mCarrierIdentifier;
+            mPolicyRules = baseProfile.mPolicyRules;
+            mAccessRules = Arrays.asList(baseProfile.mAccessRules);
         }
 
         /** Builds the profile instance. */
         public EuiccProfileInfo build() {
-            if (iccid == null) {
+            if (mIccid == null) {
                 throw new IllegalStateException("ICCID must be set for a profile.");
             }
             return new EuiccProfileInfo(
-                    iccid,
-                    nickname,
-                    serviceProviderName,
-                    profileName,
-                    profileClass,
-                    state,
-                    carrierIdentifier,
-                    policyRules,
-                    accessRules);
+                    mIccid,
+                    mNickname,
+                    mServiceProviderName,
+                    mProfileName,
+                    mProfileClass,
+                    mState,
+                    mCarrierIdentifier,
+                    mPolicyRules,
+                    mAccessRules);
         }
 
         /** Sets the iccId of the subscription. */
@@ -244,55 +253,55 @@
             if (!TextUtils.isDigitsOnly(value)) {
                 throw new IllegalArgumentException("iccid contains invalid characters: " + value);
             }
-            iccid = value;
+            mIccid = value;
             return this;
         }
 
         /** Sets the nickname of the subscription. */
         public Builder setNickname(String value) {
-            nickname = value;
+            mNickname = value;
             return this;
         }
 
         /** Sets the service provider name of the subscription. */
         public Builder setServiceProviderName(String value) {
-            serviceProviderName = value;
+            mServiceProviderName = value;
             return this;
         }
 
         /** Sets the profile name of the subscription. */
         public Builder setProfileName(String value) {
-            profileName = value;
+            mProfileName = value;
             return this;
         }
 
         /** Sets the profile class of the subscription. */
         public Builder setProfileClass(@ProfileClass int value) {
-            profileClass = value;
+            mProfileClass = value;
             return this;
         }
 
         /** Sets the state of the subscription. */
         public Builder setState(@ProfileState int value) {
-            state = value;
+            mState = value;
             return this;
         }
 
         /** Sets the carrier identifier of the subscription. */
         public Builder setCarrierIdentifier(CarrierIdentifier value) {
-            carrierIdentifier = value;
+            mCarrierIdentifier = value;
             return this;
         }
 
         /** Sets the policy rules of the subscription. */
         public Builder setPolicyRules(@PolicyRule int value) {
-            policyRules = value;
+            mPolicyRules = value;
             return this;
         }
 
         /** Sets the access rules of the subscription. */
-        public Builder setUiccAccessRule(@Nullable UiccAccessRule[] value) {
-            accessRules = value;
+        public Builder setUiccAccessRule(@Nullable List<UiccAccessRule> value) {
+            mAccessRules = value;
             return this;
         }
     }
@@ -306,75 +315,81 @@
             @ProfileState int state,
             CarrierIdentifier carrierIdentifier,
             @PolicyRule int policyRules,
-            @Nullable UiccAccessRule[] accessRules) {
-        this.iccid = iccid;
-        this.nickname = nickname;
-        this.serviceProviderName = serviceProviderName;
-        this.profileName = profileName;
-        this.profileClass = profileClass;
-        this.state = state;
-        this.carrierIdentifier = carrierIdentifier;
-        this.policyRules = policyRules;
-        this.accessRules = accessRules;
+            @Nullable List<UiccAccessRule> accessRules) {
+        this.mIccid = iccid;
+        this.mNickname = nickname;
+        this.mServiceProviderName = serviceProviderName;
+        this.mProfileName = profileName;
+        this.mProfileClass = profileClass;
+        this.mState = state;
+        this.mCarrierIdentifier = carrierIdentifier;
+        this.mPolicyRules = policyRules;
+        if (accessRules != null && accessRules.size() > 0) {
+            this.mAccessRules = accessRules.toArray(new UiccAccessRule[accessRules.size()]);
+        } else {
+            this.mAccessRules = null;
+        }
     }
 
     /** Gets the ICCID string. */
     public String getIccid() {
-        return iccid;
+        return mIccid;
     }
 
     /** Gets the access rules. */
     @Nullable
-    public UiccAccessRule[] getUiccAccessRules() {
-        return accessRules;
+    public List<UiccAccessRule> getUiccAccessRules() {
+        if (mAccessRules == null) return null;
+        return Arrays.asList(mAccessRules);
     }
 
     /** Gets the nickname. */
+    @Nullable
     public String getNickname() {
-        return nickname;
+        return mNickname;
     }
 
     /** Gets the service provider name. */
     public String getServiceProviderName() {
-        return serviceProviderName;
+        return mServiceProviderName;
     }
 
     /** Gets the profile name. */
     public String getProfileName() {
-        return profileName;
+        return mProfileName;
     }
 
     /** Gets the profile class. */
     @ProfileClass
     public int getProfileClass() {
-        return profileClass;
+        return mProfileClass;
     }
 
     /** Gets the state of the subscription. */
     @ProfileState
     public int getState() {
-        return state;
+        return mState;
     }
 
     /** Gets the carrier identifier. */
     public CarrierIdentifier getCarrierIdentifier() {
-        return carrierIdentifier;
+        return mCarrierIdentifier;
     }
 
     /** Gets the policy rules. */
     @PolicyRule
     public int getPolicyRules() {
-        return policyRules;
+        return mPolicyRules;
     }
 
     /** Returns whether any policy rule exists. */
     public boolean hasPolicyRules() {
-        return policyRules != 0;
+        return mPolicyRules != 0;
     }
 
     /** Checks whether a certain policy rule exists. */
     public boolean hasPolicyRule(@PolicyRule int policy) {
-        return (policyRules & policy) != 0;
+        return (mPolicyRules & policy) != 0;
     }
 
     @Override
@@ -387,50 +402,50 @@
         }
 
         EuiccProfileInfo that = (EuiccProfileInfo) obj;
-        return Objects.equals(iccid, that.iccid)
-                && Objects.equals(nickname, that.nickname)
-                && Objects.equals(serviceProviderName, that.serviceProviderName)
-                && Objects.equals(profileName, that.profileName)
-                && profileClass == that.profileClass
-                && state == that.state
-                && Objects.equals(carrierIdentifier, that.carrierIdentifier)
-                && policyRules == that.policyRules
-                && Arrays.equals(accessRules, that.accessRules);
+        return Objects.equals(mIccid, that.mIccid)
+                && Objects.equals(mNickname, that.mNickname)
+                && Objects.equals(mServiceProviderName, that.mServiceProviderName)
+                && Objects.equals(mProfileName, that.mProfileName)
+                && mProfileClass == that.mProfileClass
+                && mState == that.mState
+                && Objects.equals(mCarrierIdentifier, that.mCarrierIdentifier)
+                && mPolicyRules == that.mPolicyRules
+                && Arrays.equals(mAccessRules, that.mAccessRules);
     }
 
     @Override
     public int hashCode() {
         int result = 1;
-        result = 31 * result + Objects.hashCode(iccid);
-        result = 31 * result + Objects.hashCode(nickname);
-        result = 31 * result + Objects.hashCode(serviceProviderName);
-        result = 31 * result + Objects.hashCode(profileName);
-        result = 31 * result + profileClass;
-        result = 31 * result + state;
-        result = 31 * result + Objects.hashCode(carrierIdentifier);
-        result = 31 * result + policyRules;
-        result = 31 * result + Arrays.hashCode(accessRules);
+        result = 31 * result + Objects.hashCode(mIccid);
+        result = 31 * result + Objects.hashCode(mNickname);
+        result = 31 * result + Objects.hashCode(mServiceProviderName);
+        result = 31 * result + Objects.hashCode(mProfileName);
+        result = 31 * result + mProfileClass;
+        result = 31 * result + mState;
+        result = 31 * result + Objects.hashCode(mCarrierIdentifier);
+        result = 31 * result + mPolicyRules;
+        result = 31 * result + Arrays.hashCode(mAccessRules);
         return result;
     }
 
     @Override
     public String toString() {
         return "EuiccProfileInfo (nickname="
-                + nickname
+                + mNickname
                 + ", serviceProviderName="
-                + serviceProviderName
+                + mServiceProviderName
                 + ", profileName="
-                + profileName
+                + mProfileName
                 + ", profileClass="
-                + profileClass
+                + mProfileClass
                 + ", state="
-                + state
+                + mState
                 + ", CarrierIdentifier="
-                + carrierIdentifier.toString()
+                + mCarrierIdentifier.toString()
                 + ", policyRules="
-                + policyRules
+                + mPolicyRules
                 + ", accessRules="
-                + Arrays.toString(accessRules)
+                + Arrays.toString(mAccessRules)
                 + ")";
     }
 }
diff --git a/core/java/android/service/euicc/EuiccService.java b/core/java/android/service/euicc/EuiccService.java
index be85800..b87faef 100644
--- a/core/java/android/service/euicc/EuiccService.java
+++ b/core/java/android/service/euicc/EuiccService.java
@@ -17,6 +17,7 @@
 
 import android.annotation.CallSuper;
 import android.annotation.Nullable;
+import android.annotation.SystemApi;
 import android.app.Service;
 import android.content.Intent;
 import android.os.IBinder;
@@ -41,8 +42,11 @@
  * <p>To implement the LPA backend, you must extend this class and declare this service in your
  * manifest file. The service must require the
  * {@link android.Manifest.permission#BIND_EUICC_SERVICE} permission and include an intent filter
- * with the {@link #EUICC_SERVICE_INTERFACE} action. The priority of the intent filter must be set
- * to a non-zero value in case multiple implementations are present on the device. For example:
+ * with the {@link #EUICC_SERVICE_INTERFACE} action. It's suggested that the priority of the intent
+ * filter to be set to a non-zero value in case multiple implementations are present on the device.
+ * See the below example. Note that there will be problem if two LPAs are present and they have the
+ * same priority.
+ * Example:
  *
  * <pre>{@code
  * <service android:name=".MyEuiccService"
@@ -65,9 +69,9 @@
  * filter with the appropriate action, the {@link #CATEGORY_EUICC_UI} category, and a non-zero
  * priority.
  *
- * TODO(b/35851809): Make this a SystemApi.
  * @hide
  */
+@SystemApi
 public abstract class EuiccService extends Service {
     /** Action which must be included in this service's intent filter. */
     public static final String EUICC_SERVICE_INTERFACE = "android.service.euicc.EuiccService";
@@ -77,7 +81,10 @@
 
     // LUI actions. These are passthroughs of the corresponding EuiccManager actions.
 
-    /** @see android.telephony.euicc.EuiccManager#ACTION_MANAGE_EMBEDDED_SUBSCRIPTIONS */
+    /**
+     * @see android.telephony.euicc.EuiccManager#ACTION_MANAGE_EMBEDDED_SUBSCRIPTIONS
+     * The difference is this one is used by system to bring up the LUI.
+     */
     public static final String ACTION_MANAGE_EMBEDDED_SUBSCRIPTIONS =
             "android.service.euicc.action.MANAGE_EMBEDDED_SUBSCRIPTIONS";
     /** @see android.telephony.euicc.EuiccManager#ACTION_PROVISION_EMBEDDED_SUBSCRIPTION */
@@ -88,7 +95,10 @@
     // require user interaction.
     // TODO(b/33075886): Define extras for any input parameters to these dialogs once they are
     // more scoped out.
-    /** Alert the user that this action will result in an active SIM being deactivated. */
+    /**
+     * Alert the user that this action will result in an active SIM being deactivated.
+     * To implement the LUI triggered by the system, you need to define this in AndroidManifest.xml.
+     */
     public static final String ACTION_RESOLVE_DEACTIVATE_SIM =
             "android.service.euicc.action.RESOLVE_DEACTIVATE_SIM";
     /**
@@ -102,7 +112,11 @@
     public static final String ACTION_RESOLVE_CONFIRMATION_CODE =
             "android.service.euicc.action.RESOLVE_CONFIRMATION_CODE";
 
-    /** Intent extra set for resolution requests containing the package name of the calling app. */
+    /**
+     * Intent extra set for resolution requests containing the package name of the calling app.
+     * This is used by the above actions including ACTION_RESOLVE_DEACTIVATE_SIM,
+     * ACTION_RESOLVE_NO_PRIVILEGES and ACTION_RESOLVE_CONFIRMATION_CODE.
+     */
     public static final String EXTRA_RESOLUTION_CALLING_PACKAGE =
             "android.service.euicc.extra.RESOLUTION_CALLING_PACKAGE";
 
@@ -136,10 +150,18 @@
         RESOLUTION_ACTIONS.add(EuiccService.ACTION_RESOLVE_CONFIRMATION_CODE);
     }
 
-    /** Boolean extra for resolution actions indicating whether the user granted consent. */
-    public static final String RESOLUTION_EXTRA_CONSENT = "consent";
-    /** String extra for resolution actions indicating the carrier confirmation code. */
-    public static final String RESOLUTION_EXTRA_CONFIRMATION_CODE = "confirmation_code";
+    /**
+     * Boolean extra for resolution actions indicating whether the user granted consent.
+     * This is used and set by the implementation and used in {@code EuiccOperation}.
+     */
+    public static final String EXTRA_RESOLUTION_CONSENT =
+            "android.service.euicc.extra.RESOLUTION_CONSENT";
+    /**
+     * String extra for resolution actions indicating the carrier confirmation code.
+     * This is used and set by the implementation and used in {@code EuiccOperation}.
+     */
+    public static final String EXTRA_RESOLUTION_CONFIRMATION_CODE =
+            "android.service.euicc.extra.RESOLUTION_CONFIRMATION_CODE";
 
     private final IEuiccService.Stub mStubWrapper;
 
@@ -199,9 +221,9 @@
      *
      * @see IEuiccService#startOtaIfNecessary
      */
-    public interface OtaStatusChangedCallback {
+    public abstract static class OtaStatusChangedCallback {
         /** Called when OTA status is changed. */
-        void onOtaStatusChanged(int status);
+        public abstract void onOtaStatusChanged(int status);
     }
 
     /**
@@ -238,8 +260,7 @@
     /**
      * Populate {@link DownloadableSubscription} metadata for the given downloadable subscription.
      *
-     * @param slotId ID of the SIM slot to use for the operation. This is currently not populated
-     *     but is here to future-proof the APIs.
+     * @param slotId ID of the SIM slot to use for the operation.
      * @param subscription A subscription whose metadata needs to be populated.
      * @param forceDeactivateSim If true, and if an active SIM must be deactivated to access the
      *     eUICC, perform this action automatically. Otherwise, {@link #RESULT_MUST_DEACTIVATE_SIM)}
@@ -267,8 +288,7 @@
     /**
      * Download the given subscription.
      *
-     * @param slotId ID of the SIM slot to use for the operation. This is currently not populated
-     *     but is here to future-proof the APIs.
+     * @param slotId ID of the SIM slot to use for the operation.
      * @param subscription The subscription to download.
      * @param switchAfterDownload If true, the subscription should be enabled upon successful
      *     download.
@@ -286,8 +306,7 @@
     /**
      * Return a list of all @link EuiccProfileInfo}s.
      *
-     * @param slotId ID of the SIM slot to use for the operation. This is currently not populated
-     *     but is here to future-proof the APIs.
+     * @param slotId ID of the SIM slot to use for the operation.
      * @return The result of the operation.
      * @see android.telephony.SubscriptionManager#getAvailableSubscriptionInfoList
      * @see android.telephony.SubscriptionManager#getAccessibleSubscriptionInfoList
@@ -297,8 +316,7 @@
     /**
      * Return info about the eUICC chip/device.
      *
-     * @param slotId ID of the SIM slot to use for the operation. This is currently not populated
-     *     but is here to future-proof the APIs.
+     * @param slotId ID of the SIM slot to use for the operation.
      * @return the {@link EuiccInfo} for the eUICC chip/device.
      * @see android.telephony.euicc.EuiccManager#getEuiccInfo
      */
@@ -310,8 +328,7 @@
      * <p>If the subscription is currently active, it should be deactivated first (equivalent to a
      * physical SIM being ejected).
      *
-     * @param slotId ID of the SIM slot to use for the operation. This is currently not populated
-     *     but is here to future-proof the APIs.
+     * @param slotId ID of the SIM slot to use for the operation.
      * @param iccid the ICCID of the subscription to delete.
      * @return the result of the delete operation. May be one of the predefined {@code RESULT_}
      *     constants or any implementation-specific code starting with {@link #RESULT_FIRST_USER}.
@@ -322,8 +339,7 @@
     /**
      * Switch to the given subscription.
      *
-     * @param slotId ID of the SIM slot to use for the operation. This is currently not populated
-     *     but is here to future-proof the APIs.
+     * @param slotId ID of the SIM slot to use for the operation.
      * @param iccid the ICCID of the subscription to enable. May be null, in which case the current
      *     profile should be deactivated and no profile should be activated to replace it - this is
      *     equivalent to a physical SIM being ejected.
@@ -340,8 +356,7 @@
     /**
      * Update the nickname of the given subscription.
      *
-     * @param slotId ID of the SIM slot to use for the operation. This is currently not populated
-     *     but is here to future-proof the APIs.
+     * @param slotId ID of the SIM slot to use for the operation.
      * @param iccid the ICCID of the subscription to update.
      * @param nickname the new nickname to apply.
      * @return the result of the update operation. May be one of the predefined {@code RESULT_}
diff --git a/core/java/android/service/euicc/GetDefaultDownloadableSubscriptionListResult.java b/core/java/android/service/euicc/GetDefaultDownloadableSubscriptionListResult.java
index 5a24492..e2171ae 100644
--- a/core/java/android/service/euicc/GetDefaultDownloadableSubscriptionListResult.java
+++ b/core/java/android/service/euicc/GetDefaultDownloadableSubscriptionListResult.java
@@ -16,16 +16,19 @@
 package android.service.euicc;
 
 import android.annotation.Nullable;
+import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.telephony.euicc.DownloadableSubscription;
 
+import java.util.Arrays;
+import java.util.List;
+
 /**
  * Result of a {@link EuiccService#onGetDefaultDownloadableSubscriptionList} operation.
  * @hide
- *
- * TODO(b/35851809): Make this a SystemApi.
  */
+@SystemApi
 public final class GetDefaultDownloadableSubscriptionListResult implements Parcelable {
 
     public static final Creator<GetDefaultDownloadableSubscriptionListResult> CREATOR =
@@ -42,20 +45,35 @@
     };
 
     /**
-     * Result of the operation.
+     * @hide
+     * @deprecated - Do no use. Use getResult() instead.
+     */
+    @Deprecated
+    public final int result;
+
+    @Nullable
+    private final DownloadableSubscription[] mSubscriptions;
+
+    /**
+     * Gets the result of the operation.
      *
      * <p>May be one of the predefined {@code RESULT_} constants in EuiccService or any
      * implementation-specific code starting with {@link EuiccService#RESULT_FIRST_USER}.
      */
-    public final int result;
+    public int getResult() {
+        return result;
+    }
 
     /**
-     * The available {@link DownloadableSubscription}s (with filled-in metadata).
+     * Gets the available {@link DownloadableSubscription}s (with filled-in metadata).
      *
      * <p>Only non-null if {@link #result} is {@link EuiccService#RESULT_OK}.
      */
     @Nullable
-    public final DownloadableSubscription[] subscriptions;
+    public List<DownloadableSubscription> getDownloadableSubscriptions() {
+        if (mSubscriptions == null) return null;
+        return Arrays.asList(mSubscriptions);
+    }
 
     /**
      * Construct a new {@link GetDefaultDownloadableSubscriptionListResult}.
@@ -70,25 +88,25 @@
             @Nullable DownloadableSubscription[] subscriptions) {
         this.result = result;
         if (this.result == EuiccService.RESULT_OK) {
-            this.subscriptions = subscriptions;
+            this.mSubscriptions = subscriptions;
         } else {
             if (subscriptions != null) {
                 throw new IllegalArgumentException(
                         "Error result with non-null subscriptions: " + result);
             }
-            this.subscriptions = null;
+            this.mSubscriptions = null;
         }
     }
 
     private GetDefaultDownloadableSubscriptionListResult(Parcel in) {
         this.result = in.readInt();
-        this.subscriptions = in.createTypedArray(DownloadableSubscription.CREATOR);
+        this.mSubscriptions = in.createTypedArray(DownloadableSubscription.CREATOR);
     }
 
     @Override
     public void writeToParcel(Parcel dest, int flags) {
         dest.writeInt(result);
-        dest.writeTypedArray(subscriptions, flags);
+        dest.writeTypedArray(mSubscriptions, flags);
     }
 
     @Override
diff --git a/core/java/android/service/euicc/GetDownloadableSubscriptionMetadataResult.java b/core/java/android/service/euicc/GetDownloadableSubscriptionMetadataResult.java
index de8a307..1edb539 100644
--- a/core/java/android/service/euicc/GetDownloadableSubscriptionMetadataResult.java
+++ b/core/java/android/service/euicc/GetDownloadableSubscriptionMetadataResult.java
@@ -16,6 +16,7 @@
 package android.service.euicc;
 
 import android.annotation.Nullable;
+import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.telephony.euicc.DownloadableSubscription;
@@ -23,9 +24,8 @@
 /**
  * Result of a {@link EuiccService#onGetDownloadableSubscriptionMetadata} operation.
  * @hide
- *
- * TODO(b/35851809): Make this a SystemApi.
  */
+@SystemApi
 public final class GetDownloadableSubscriptionMetadataResult implements Parcelable {
 
     public static final Creator<GetDownloadableSubscriptionMetadataResult> CREATOR =
@@ -42,20 +42,34 @@
     };
 
     /**
-     * Result of the operation.
+     * @hide
+     * @deprecated - Do no use. Use getResult() instead.
+     */
+    @Deprecated
+    public final int result;
+
+    @Nullable
+    private final DownloadableSubscription mSubscription;
+
+    /**
+     * Gets the result of the operation.
      *
      * <p>May be one of the predefined {@code RESULT_} constants in EuiccService or any
      * implementation-specific code starting with {@link EuiccService#RESULT_FIRST_USER}.
      */
-    public final int result;
+    public int getResult() {
+        return result;
+    }
 
     /**
-     * The {@link DownloadableSubscription} with filled-in metadata.
+     * Gets the {@link DownloadableSubscription} with filled-in metadata.
      *
      * <p>Only non-null if {@link #result} is {@link EuiccService#RESULT_OK}.
      */
     @Nullable
-    public final DownloadableSubscription subscription;
+    public DownloadableSubscription getDownloadableSubscription() {
+        return mSubscription;
+    }
 
     /**
      * Construct a new {@link GetDownloadableSubscriptionMetadataResult}.
@@ -70,25 +84,25 @@
             @Nullable DownloadableSubscription subscription) {
         this.result = result;
         if (this.result == EuiccService.RESULT_OK) {
-            this.subscription = subscription;
+            this.mSubscription = subscription;
         } else {
             if (subscription != null) {
                 throw new IllegalArgumentException(
                         "Error result with non-null subscription: " + result);
             }
-            this.subscription = null;
+            this.mSubscription = null;
         }
     }
 
     private GetDownloadableSubscriptionMetadataResult(Parcel in) {
         this.result = in.readInt();
-        this.subscription = in.readTypedObject(DownloadableSubscription.CREATOR);
+        this.mSubscription = in.readTypedObject(DownloadableSubscription.CREATOR);
     }
 
     @Override
     public void writeToParcel(Parcel dest, int flags) {
         dest.writeInt(result);
-        dest.writeTypedObject(this.subscription, flags);
+        dest.writeTypedObject(this.mSubscription, flags);
     }
 
     @Override
diff --git a/core/java/android/service/euicc/GetEuiccProfileInfoListResult.java b/core/java/android/service/euicc/GetEuiccProfileInfoListResult.java
index 7ad8488..464d136 100644
--- a/core/java/android/service/euicc/GetEuiccProfileInfoListResult.java
+++ b/core/java/android/service/euicc/GetEuiccProfileInfoListResult.java
@@ -16,15 +16,18 @@
 package android.service.euicc;
 
 import android.annotation.Nullable;
+import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 
+import java.util.Arrays;
+import java.util.List;
+
 /**
  * Result of a {@link EuiccService#onGetEuiccProfileInfoList} operation.
  * @hide
- *
- * TODO(b/35851809): Make this a SystemApi.
  */
+@SystemApi
 public final class GetEuiccProfileInfoListResult implements Parcelable {
 
     public static final Creator<GetEuiccProfileInfoListResult> CREATOR =
@@ -41,19 +44,38 @@
             };
 
     /**
-     * Result of the operation.
+     * @hide
+     * @deprecated - Do no use. Use getResult() instead.
+     */
+    @Deprecated
+    public final int result;
+
+    @Nullable
+    private final EuiccProfileInfo[] mProfiles;
+
+    private final boolean mIsRemovable;
+
+    /**
+     * Gets the result of the operation.
      *
      * <p>May be one of the predefined {@code RESULT_} constants in EuiccService or any
      * implementation-specific code starting with {@link EuiccService#RESULT_FIRST_USER}.
      */
-    public final int result;
+    public int getResult() {
+        return result;
+    }
 
-    /** The profile list (only upon success). */
+    /** Gets the profile list (only upon success). */
     @Nullable
-    public final EuiccProfileInfo[] profiles;
+    public List<EuiccProfileInfo> getProfiles() {
+        if (mProfiles == null) return null;
+        return Arrays.asList(mProfiles);
+    }
 
-    /** Whether the eUICC is removable. */
-    public final boolean isRemovable;
+    /** Gets whether the eUICC is removable. */
+    public boolean getIsRemovable() {
+        return mIsRemovable;
+    }
 
     /**
      * Construct a new {@link GetEuiccProfileInfoListResult}.
@@ -71,30 +93,29 @@
     public GetEuiccProfileInfoListResult(
             int result, @Nullable EuiccProfileInfo[] profiles, boolean isRemovable) {
         this.result = result;
-        this.isRemovable = isRemovable;
+        this.mIsRemovable = isRemovable;
         if (this.result == EuiccService.RESULT_OK) {
-            this.profiles = profiles;
+            this.mProfiles = profiles;
         } else {
             if (profiles != null) {
                 throw new IllegalArgumentException(
                         "Error result with non-null profiles: " + result);
             }
-            this.profiles = null;
+            this.mProfiles = null;
         }
-
     }
 
     private GetEuiccProfileInfoListResult(Parcel in) {
         this.result = in.readInt();
-        this.profiles = in.createTypedArray(EuiccProfileInfo.CREATOR);
-        this.isRemovable = in.readBoolean();
+        this.mProfiles = in.createTypedArray(EuiccProfileInfo.CREATOR);
+        this.mIsRemovable = in.readBoolean();
     }
 
     @Override
     public void writeToParcel(Parcel dest, int flags) {
         dest.writeInt(result);
-        dest.writeTypedArray(profiles, flags);
-        dest.writeBoolean(isRemovable);
+        dest.writeTypedArray(mProfiles, flags);
+        dest.writeBoolean(mIsRemovable);
     }
 
     @Override
diff --git a/core/java/android/speech/tts/SynthesisPlaybackQueueItem.java b/core/java/android/speech/tts/SynthesisPlaybackQueueItem.java
index 704a1da..2ed618b 100644
--- a/core/java/android/speech/tts/SynthesisPlaybackQueueItem.java
+++ b/core/java/android/speech/tts/SynthesisPlaybackQueueItem.java
@@ -15,17 +15,17 @@
  */
 package android.speech.tts;
 
+import android.media.AudioTrack;
 import android.speech.tts.TextToSpeechService.AudioOutputParams;
 import android.speech.tts.TextToSpeechService.UtteranceProgressDispatcher;
-import android.media.AudioTrack;
 import android.util.Log;
 
 import java.util.LinkedList;
+import java.util.concurrent.ConcurrentLinkedQueue;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.locks.Condition;
 import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReentrantLock;
-import java.util.concurrent.ConcurrentLinkedQueue;
 
 /**
  * Manages the playback of a list of byte arrays representing audio data that are queued by the
@@ -157,9 +157,16 @@
             mStopped = true;
             mStatusCode = statusCode;
 
+            // Wake up the synthesis thread if it was waiting on put(). Its
+            // buffers will no longer be copied since mStopped is true. The
+            // PlaybackSynthesisCallback that this synthesis corresponds to
+            // would also have been stopped, and so all calls to
+            // Callback.onDataAvailable( ) will return errors too.
+            mNotFull.signal();
+
             if (mRunState.getAndSet(STOP_CALLED) == NOT_RUN) {
-                // Dispatch the status code and just finish without signaling
-                // if run() has not even started.
+                // Dispatch the status code and just finish. Signaling audio
+                // playback is not necessary because run() hasn't started.
                 dispatchEndStatus();
                 return;
             }
@@ -168,13 +175,6 @@
             // take() will return null since mStopped was true, and will then
             // break out of the data write loop.
             mReadReady.signal();
-
-            // Wake up the synthesis thread if it was waiting on put(). Its
-            // buffers will no longer be copied since mStopped is true. The
-            // PlaybackSynthesisCallback that this synthesis corresponds to
-            // would also have been stopped, and so all calls to
-            // Callback.onDataAvailable( ) will return errors too.
-            mNotFull.signal();
         } finally {
             mListLock.unlock();
         }
diff --git a/core/java/android/text/BoringLayout.java b/core/java/android/text/BoringLayout.java
index 6fa5312..dbe4157 100644
--- a/core/java/android/text/BoringLayout.java
+++ b/core/java/android/text/BoringLayout.java
@@ -322,6 +322,12 @@
      */
     public static Metrics isBoring(CharSequence text, TextPaint paint,
             TextDirectionHeuristic textDir, Metrics metrics) {
+        return isBoring(text, null /* precomputed */, paint, textDir, metrics);
+    }
+
+    /** @hide */
+    public static Metrics isBoring(CharSequence text, PrecomputedText precomputed, TextPaint paint,
+            TextDirectionHeuristic textDir, Metrics metrics) {
         final int textLength = text.length();
         if (hasAnyInterestingChars(text, textLength)) {
            return null;  // There are some interesting characters. Not boring.
@@ -344,18 +350,17 @@
             fm.reset();
         }
 
-        TextLine line = TextLine.obtain();
-        line.set(paint, text, 0, textLength, Layout.DIR_LEFT_TO_RIGHT,
-                Layout.DIRS_ALL_LEFT_TO_RIGHT, false, null);
-        if (text instanceof MeasuredText) {
-            MeasuredText mt = (MeasuredText) text;
+        if (precomputed != null) {
             // Reaching here means there is only one paragraph.
-            MeasuredParagraph mp = mt.getMeasuredParagraph(0);
+            MeasuredParagraph mp = precomputed.getMeasuredParagraph(0);
             fm.width = (int) Math.ceil(mp.getWidth(0, mp.getTextLength()));
         } else {
+            TextLine line = TextLine.obtain();
+            line.set(paint, text, 0, textLength, Layout.DIR_LEFT_TO_RIGHT,
+                    Layout.DIRS_ALL_LEFT_TO_RIGHT, false, null);
             fm.width = (int) Math.ceil(line.metrics(fm));
+            TextLine.recycle(line);
         }
-        TextLine.recycle(line);
 
         return fm;
     }
diff --git a/core/java/android/text/DynamicLayout.java b/core/java/android/text/DynamicLayout.java
index 18431ca..10444f0 100644
--- a/core/java/android/text/DynamicLayout.java
+++ b/core/java/android/text/DynamicLayout.java
@@ -363,7 +363,7 @@
                          @JustificationMode int justificationMode,
                          @Nullable TextUtils.TruncateAt ellipsize,
                          @IntRange(from = 0) int ellipsizedWidth) {
-        super(createEllipsizer(ellipsize, display),
+        super(createEllipsizer(ellipsize, display), null /* precomputed */,
               paint, width, align, textDir, spacingmult, spacingadd);
 
         final Builder b = Builder.obtain(base, paint, width)
diff --git a/core/java/android/text/Layout.java b/core/java/android/text/Layout.java
index aa97b2a..d5d3590 100644
--- a/core/java/android/text/Layout.java
+++ b/core/java/android/text/Layout.java
@@ -245,6 +245,13 @@
     protected Layout(CharSequence text, TextPaint paint,
                      int width, Alignment align, TextDirectionHeuristic textDir,
                      float spacingMult, float spacingAdd) {
+        this(text, null /* precomputed */, paint, width, align, textDir, spacingMult, spacingAdd);
+    }
+
+    /** @hide */
+    protected Layout(CharSequence text, PrecomputedText precomputed, TextPaint paint,
+                     int width, Alignment align, TextDirectionHeuristic textDir,
+                     float spacingMult, float spacingAdd) {
 
         if (width < 0)
             throw new IllegalArgumentException("Layout: " + width + " < 0");
@@ -259,6 +266,7 @@
         }
 
         mText = text;
+        mPrecomputed = precomputed;
         mPaint = paint;
         mWidth = width;
         mAlignment = align;
@@ -562,7 +570,7 @@
                 // XXX: assumes there's nothing additional to be done
                 canvas.drawText(buf, start, end, x, lbaseline, paint);
             } else {
-                tl.set(paint, buf, start, end, dir, directions, hasTab, tabStops);
+                tl.set(paint, buf, mPrecomputed, start, end, dir, directions, hasTab, tabStops);
                 if (justify) {
                     tl.justify(right - left - indentWidth);
                 }
@@ -2264,6 +2272,7 @@
     }
 
     private CharSequence mText;
+    private PrecomputedText mPrecomputed;
     private TextPaint mPaint;
     private TextPaint mWorkPaint = new TextPaint();
     private int mWidth;
diff --git a/core/java/android/text/MeasuredText.java b/core/java/android/text/MeasuredText.java
deleted file mode 100644
index bb7a9e0..0000000
--- a/core/java/android/text/MeasuredText.java
+++ /dev/null
@@ -1,427 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text;
-
-import android.annotation.IntRange;
-import android.annotation.NonNull;
-import android.util.IntArray;
-
-import com.android.internal.util.ArrayUtils;
-import com.android.internal.util.Preconditions;
-
-import java.util.ArrayList;
-
-/**
- * A text which has already been measured.
- */
-public class MeasuredText implements Spanned {
-    private static final char LINE_FEED = '\n';
-
-    // The original text.
-    private final @NonNull CharSequence mText;
-
-    // The inclusive start offset of the measuring target.
-    private final @IntRange(from = 0) int mStart;
-
-    // The exclusive end offset of the measuring target.
-    private final @IntRange(from = 0) int mEnd;
-
-    // The TextPaint used for measurement.
-    private final @NonNull TextPaint mPaint;
-
-    // The requested text direction.
-    private final @NonNull TextDirectionHeuristic mTextDir;
-
-    // The measured paragraph texts.
-    private final @NonNull MeasuredParagraph[] mMeasuredParagraphs;
-
-    // The sorted paragraph end offsets.
-    private final @NonNull int[] mParagraphBreakPoints;
-
-    // The break strategy for this measured text.
-    private final @Layout.BreakStrategy int mBreakStrategy;
-
-    // The hyphenation frequency for this measured text.
-    private final @Layout.HyphenationFrequency int mHyphenationFrequency;
-
-    /**
-     * A Builder for MeasuredText
-     */
-    public static final class Builder {
-        // Mandatory parameters.
-        private final @NonNull CharSequence mText;
-        private final @NonNull TextPaint mPaint;
-
-        // Members to be updated by setters.
-        private @IntRange(from = 0) int mStart;
-        private @IntRange(from = 0) int mEnd;
-        private TextDirectionHeuristic mTextDir = TextDirectionHeuristics.FIRSTSTRONG_LTR;
-        private @Layout.BreakStrategy int mBreakStrategy = Layout.BREAK_STRATEGY_HIGH_QUALITY;
-        private @Layout.HyphenationFrequency int mHyphenationFrequency =
-                Layout.HYPHENATION_FREQUENCY_NORMAL;
-
-
-        /**
-         * Builder constructor
-         *
-         * @param text The text to be measured.
-         * @param paint The paint to be used for drawing.
-         */
-        public Builder(@NonNull CharSequence text, @NonNull TextPaint paint) {
-            Preconditions.checkNotNull(text);
-            Preconditions.checkNotNull(paint);
-
-            mText = text;
-            mPaint = paint;
-            mStart = 0;
-            mEnd = text.length();
-        }
-
-        /**
-         * Set the range of measuring target.
-         *
-         * @param start The measuring target start offset in the text.
-         * @param end The measuring target end offset in the text.
-         */
-        public @NonNull Builder setRange(@IntRange(from = 0) int start,
-                                         @IntRange(from = 0) int end) {
-            Preconditions.checkArgumentInRange(start, 0, mText.length(), "start");
-            Preconditions.checkArgumentInRange(end, 0, mText.length(), "end");
-            Preconditions.checkArgument(start <= end, "The range is reversed.");
-
-            mStart = start;
-            mEnd = end;
-            return this;
-        }
-
-        /**
-         * Set the text direction heuristic
-         *
-         * The default value is {@link TextDirectionHeuristics#FIRSTSTRONG_LTR}.
-         *
-         * @param textDir The text direction heuristic for resolving bidi behavior.
-         * @return this builder, useful for chaining.
-         */
-        public @NonNull Builder setTextDirection(@NonNull TextDirectionHeuristic textDir) {
-            Preconditions.checkNotNull(textDir);
-            mTextDir = textDir;
-            return this;
-        }
-
-        /**
-         * Set the break strategy
-         *
-         * The default value is {@link Layout#BREAK_STRATEGY_HIGH_QUALITY}.
-         *
-         * @param breakStrategy The break strategy.
-         * @return this builder, useful for chaining.
-         */
-        public @NonNull Builder setBreakStrategy(@Layout.BreakStrategy int breakStrategy) {
-            mBreakStrategy = breakStrategy;
-            return this;
-        }
-
-        /**
-         * Set the hyphenation frequency
-         *
-         * The default value is {@link Layout#HYPHENATION_FREQUENCY_NORMAL}.
-         *
-         * @param hyphenationFrequency The hyphenation frequency.
-         * @return this builder, useful for chaining.
-         */
-        public @NonNull Builder setHyphenationFrequency(
-                @Layout.HyphenationFrequency int hyphenationFrequency) {
-            mHyphenationFrequency = hyphenationFrequency;
-            return this;
-        }
-
-        /**
-         * Build the measured text
-         *
-         * @return the measured text.
-         */
-        public @NonNull MeasuredText build() {
-            return build(true /* build full layout result */);
-        }
-
-        /** @hide */
-        public @NonNull MeasuredText build(boolean computeLayout) {
-            final boolean needHyphenation = mBreakStrategy != Layout.BREAK_STRATEGY_SIMPLE
-                    && mHyphenationFrequency != Layout.HYPHENATION_FREQUENCY_NONE;
-
-            final IntArray paragraphEnds = new IntArray();
-            final ArrayList<MeasuredParagraph> measuredTexts = new ArrayList<>();
-
-            int paraEnd = 0;
-            for (int paraStart = mStart; paraStart < mEnd; paraStart = paraEnd) {
-                paraEnd = TextUtils.indexOf(mText, LINE_FEED, paraStart, mEnd);
-                if (paraEnd < 0) {
-                    // No LINE_FEED(U+000A) character found. Use end of the text as the paragraph
-                    // end.
-                    paraEnd = mEnd;
-                } else {
-                    paraEnd++;  // Includes LINE_FEED(U+000A) to the prev paragraph.
-                }
-
-                paragraphEnds.add(paraEnd);
-                measuredTexts.add(MeasuredParagraph.buildForStaticLayout(
-                        mPaint, mText, paraStart, paraEnd, mTextDir, needHyphenation,
-                        computeLayout, null /* no recycle */));
-            }
-
-            return new MeasuredText(mText, mStart, mEnd, mPaint, mTextDir, mBreakStrategy,
-                                    mHyphenationFrequency, measuredTexts.toArray(
-                                            new MeasuredParagraph[measuredTexts.size()]),
-                                    paragraphEnds.toArray());
-        }
-    };
-
-    // Use MeasuredText.Builder instead.
-    private MeasuredText(@NonNull CharSequence text,
-                         @IntRange(from = 0) int start,
-                         @IntRange(from = 0) int end,
-                         @NonNull TextPaint paint,
-                         @NonNull TextDirectionHeuristic textDir,
-                         @Layout.BreakStrategy int breakStrategy,
-                         @Layout.HyphenationFrequency int frequency,
-                         @NonNull MeasuredParagraph[] measuredTexts,
-                         @NonNull int[] paragraphBreakPoints) {
-        mText = text;
-        mStart = start;
-        mEnd = end;
-        // Copy the paint so that we can keep the reference of typeface in native layout result.
-        mPaint = new TextPaint(paint);
-        mMeasuredParagraphs = measuredTexts;
-        mParagraphBreakPoints = paragraphBreakPoints;
-        mTextDir = textDir;
-        mBreakStrategy = breakStrategy;
-        mHyphenationFrequency = frequency;
-    }
-
-    /**
-     * Return the underlying text.
-     */
-    public @NonNull CharSequence getText() {
-        return mText;
-    }
-
-    /**
-     * Returns the inclusive start offset of measured region.
-     */
-    public @IntRange(from = 0) int getStart() {
-        return mStart;
-    }
-
-    /**
-     * Returns the exclusive end offset of measured region.
-     */
-    public @IntRange(from = 0) int getEnd() {
-        return mEnd;
-    }
-
-    /**
-     * Returns the text direction associated with char sequence.
-     */
-    public @NonNull TextDirectionHeuristic getTextDir() {
-        return mTextDir;
-    }
-
-    /**
-     * Returns the paint used to measure this text.
-     */
-    public @NonNull TextPaint getPaint() {
-        return mPaint;
-    }
-
-    /**
-     * Returns the length of the paragraph of this text.
-     */
-    public @IntRange(from = 0) int getParagraphCount() {
-        return mParagraphBreakPoints.length;
-    }
-
-    /**
-     * Returns the paragraph start offset of the text.
-     */
-    public @IntRange(from = 0) int getParagraphStart(@IntRange(from = 0) int paraIndex) {
-        Preconditions.checkArgumentInRange(paraIndex, 0, getParagraphCount(), "paraIndex");
-        return paraIndex == 0 ? mStart : mParagraphBreakPoints[paraIndex - 1];
-    }
-
-    /**
-     * Returns the paragraph end offset of the text.
-     */
-    public @IntRange(from = 0) int getParagraphEnd(@IntRange(from = 0) int paraIndex) {
-        Preconditions.checkArgumentInRange(paraIndex, 0, getParagraphCount(), "paraIndex");
-        return mParagraphBreakPoints[paraIndex];
-    }
-
-    /** @hide */
-    public @NonNull MeasuredParagraph getMeasuredParagraph(@IntRange(from = 0) int paraIndex) {
-        return mMeasuredParagraphs[paraIndex];
-    }
-
-    /**
-     * Returns the break strategy for this text.
-     */
-    public @Layout.BreakStrategy int getBreakStrategy() {
-        return mBreakStrategy;
-    }
-
-    /**
-     * Returns the hyphenation frequency for this text.
-     */
-    public @Layout.HyphenationFrequency int getHyphenationFrequency() {
-        return mHyphenationFrequency;
-    }
-
-    /**
-     * Returns true if the given TextPaint gives the same result of text layout for this text.
-     * @hide
-     */
-    public boolean canUseMeasuredResult(@NonNull TextPaint paint) {
-        return mPaint.getTextSize() == paint.getTextSize()
-            && mPaint.getTextSkewX() == paint.getTextSkewX()
-            && mPaint.getTextScaleX() == paint.getTextScaleX()
-            && mPaint.getLetterSpacing() == paint.getLetterSpacing()
-            && mPaint.getWordSpacing() == paint.getWordSpacing()
-            && mPaint.getFlags() == paint.getFlags()  // Maybe not all flag affects text layout.
-            && mPaint.getTextLocales() == paint.getTextLocales()  // need to be equals?
-            && mPaint.getFontVariationSettings() == paint.getFontVariationSettings()
-            && mPaint.getTypeface() == paint.getTypeface()
-            && TextUtils.equals(mPaint.getFontFeatureSettings(), paint.getFontFeatureSettings());
-    }
-
-    /** @hide */
-    public int findParaIndex(@IntRange(from = 0) int pos) {
-        // TODO: Maybe good to remove paragraph concept from MeasuredText and add substring layout
-        //       support to StaticLayout.
-        for (int i = 0; i < mParagraphBreakPoints.length; ++i) {
-            if (pos < mParagraphBreakPoints[i]) {
-                return i;
-            }
-        }
-        throw new IndexOutOfBoundsException(
-            "pos must be less than " + mParagraphBreakPoints[mParagraphBreakPoints.length - 1]
-            + ", gave " + pos);
-    }
-
-    /** @hide */
-    public float getWidth(@IntRange(from = 0) int start, @IntRange(from = 0) int end) {
-        final int paraIndex = findParaIndex(start);
-        final int paraStart = getParagraphStart(paraIndex);
-        final int paraEnd = getParagraphEnd(paraIndex);
-        if (start < paraStart || paraEnd < end) {
-            throw new RuntimeException("Cannot measured across the paragraph:"
-                + "para: (" + paraStart + ", " + paraEnd + "), "
-                + "request: (" + start + ", " + end + ")");
-        }
-        return getMeasuredParagraph(paraIndex).getWidth(start - paraStart, end - paraStart);
-    }
-
-    /**
-     * Returns the size of native MeasuredText memory usage
-     *
-     * Note that this may not be aculate. Must be used only for testing purposes.
-     * @hide
-     */
-    public int getMemoryUsage() {
-        int r = 0;
-        for (int i = 0; i < getParagraphCount(); ++i) {
-            r += getMeasuredParagraph(i).getMemoryUsage();
-        }
-        return r;
-    }
-
-    ///////////////////////////////////////////////////////////////////////////////////////////////
-    // Spanned overrides
-    //
-    // Just proxy for underlying mText if appropriate.
-
-    @Override
-    public <T> T[] getSpans(int start, int end, Class<T> type) {
-        if (mText instanceof Spanned) {
-            return ((Spanned) mText).getSpans(start, end, type);
-        } else {
-            return ArrayUtils.emptyArray(type);
-        }
-    }
-
-    @Override
-    public int getSpanStart(Object tag) {
-        if (mText instanceof Spanned) {
-            return ((Spanned) mText).getSpanStart(tag);
-        } else {
-            return -1;
-        }
-    }
-
-    @Override
-    public int getSpanEnd(Object tag) {
-        if (mText instanceof Spanned) {
-            return ((Spanned) mText).getSpanEnd(tag);
-        } else {
-            return -1;
-        }
-    }
-
-    @Override
-    public int getSpanFlags(Object tag) {
-        if (mText instanceof Spanned) {
-            return ((Spanned) mText).getSpanFlags(tag);
-        } else {
-            return 0;
-        }
-    }
-
-    @Override
-    public int nextSpanTransition(int start, int limit, Class type) {
-        if (mText instanceof Spanned) {
-            return ((Spanned) mText).nextSpanTransition(start, limit, type);
-        } else {
-            return mText.length();
-        }
-    }
-
-    ///////////////////////////////////////////////////////////////////////////////////////////////
-    // CharSequence overrides.
-    //
-    // Just proxy for underlying mText.
-
-    @Override
-    public int length() {
-        return mText.length();
-    }
-
-    @Override
-    public char charAt(int index) {
-        // TODO: Should this be index + mStart ?
-        return mText.charAt(index);
-    }
-
-    @Override
-    public CharSequence subSequence(int start, int end) {
-        // TODO: return MeasuredText.
-        // TODO: Should this be index + mStart, end + mStart ?
-        return mText.subSequence(start, end);
-    }
-
-    @Override
-    public String toString() {
-        return mText.toString();
-    }
-}
diff --git a/core/java/android/text/PrecomputedText.java b/core/java/android/text/PrecomputedText.java
new file mode 100644
index 0000000..39fc2bd
--- /dev/null
+++ b/core/java/android/text/PrecomputedText.java
@@ -0,0 +1,412 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.text;
+
+import android.annotation.IntRange;
+import android.annotation.NonNull;
+import android.util.IntArray;
+
+import com.android.internal.util.Preconditions;
+
+import java.util.ArrayList;
+
+/**
+ * A text which has the character metrics data
+ *
+ * This text holds a part of the text layout result. You can accelerate
+ * {@link android.widget.TextView} or {@link StaticLayout} by using this text.
+ *
+ * <pre>
+ * Example of background measurement.
+ * <code>
+ *  void asyncSetText(final TextView textView, final String expensiveLongString, Handler handler) {
+ *      final PrecomputedText.Params params = textView.getTextParams();
+ *      handler.post(() -> {
+ *          final PrecomputedText precomputedText
+ *                  = PrecomputedText.create(expensiveLongString, params);
+ *          textView.post(() -> {
+ *              textView.setPrecomputedTextOrThrow(precomputedText);
+ *          });
+ *      });
+ *  }
+ * </code>
+ * </pre>
+ *
+ * Note that the {@link PrecomputedText} created from different parameters of the target
+ * {@link android.widget.TextView} will be rejected internally and compute the text layout again
+ * with the current {@link android.widget.TextView} parameters.
+ */
+public class PrecomputedText {
+    private static final char LINE_FEED = '\n';
+
+    /**
+     * The information required for building {@link PrecomputedText}.
+     *
+     * Contains information required for precomputing text measurement metadata, so it can be done
+     * in isolation of a {@link android.widget.TextView} or {@link StaticLayout}, when final layout
+     * constraints are not known.
+     */
+    public static class Params {
+        // The TextPaint used for measurement.
+        private final @NonNull TextPaint mPaint;
+
+        // The requested text direction.
+        private final @NonNull TextDirectionHeuristic mTextDir;
+
+        // The break strategy for this measured text.
+        private final @Layout.BreakStrategy int mBreakStrategy;
+
+        // The hyphenation frequency for this measured text.
+        private final @Layout.HyphenationFrequency int mHyphenationFrequency;
+
+        /**
+         * A builder for creating {@link Params}.
+         */
+        public static class Builder {
+            // The TextPaint used for measurement.
+            private final @NonNull TextPaint mPaint;
+
+            // The requested text direction.
+            private TextDirectionHeuristic mTextDir = TextDirectionHeuristics.FIRSTSTRONG_LTR;
+
+            // The break strategy for this measured text.
+            private @Layout.BreakStrategy int mBreakStrategy = Layout.BREAK_STRATEGY_HIGH_QUALITY;
+
+            // The hyphenation frequency for this measured text.
+            private @Layout.HyphenationFrequency int mHyphenationFrequency =
+                    Layout.HYPHENATION_FREQUENCY_NORMAL;
+
+            /**
+             * Builder constructor
+             *
+             * @param paint The paint to be used for drawing
+             */
+            public Builder(@NonNull TextPaint paint) {
+                mPaint = paint;
+            }
+
+            /**
+             * Set the line break strategy
+             *
+             * The default value is {@link Layout#BREAK_STRATEGY_HIGH_QUALITY}.
+             *
+             * @param strategy The break strategy
+             * @return this builder, useful for chaining
+             */
+            public Builder setBreakStrategy(@Layout.BreakStrategy int strategy) {
+                mBreakStrategy = strategy;
+                return this;
+            }
+
+            /**
+             * Set the hyphenation frequency
+             *
+             * The default value is {@link Layout#HYPHENATION_FREQUENCY_NORMAL}.
+             *
+             * @param frequency The hyphenation frequency
+             * @return this builder, useful for chaining
+             */
+            public Builder setHyphenationFrequency(@Layout.HyphenationFrequency int frequency) {
+                mHyphenationFrequency = frequency;
+                return this;
+            }
+
+            /**
+             * Set the text direction heuristic
+             *
+             * The default value is {@link TextDirectionHeuristics#FIRSTSTRONG_LTR}.
+             *
+             * @param textDir The text direction heuristic for resolving bidi behavior
+             * @return this builder, useful for chaining
+             */
+            public Builder setTextDirection(@NonNull TextDirectionHeuristic textDir) {
+                mTextDir = textDir;
+                return this;
+            }
+
+            /**
+             * Build the {@link Params}
+             *
+             * @return the layout parameter
+             */
+            public @NonNull Params build() {
+                return new Params(mPaint, mTextDir, mBreakStrategy, mHyphenationFrequency);
+            }
+        }
+
+        // Use Builder instead.
+        /** @hide */
+        public Params(@NonNull TextPaint paint, @NonNull TextDirectionHeuristic textDir,
+                @Layout.BreakStrategy int strategy, @Layout.HyphenationFrequency int frequency) {
+            mPaint = paint;
+            mTextDir = textDir;
+            mBreakStrategy = strategy;
+            mHyphenationFrequency = frequency;
+        }
+
+        /**
+         * Returns the {@link TextPaint} for this text
+         *
+         * @return A {@link TextPaint}
+         */
+        public @NonNull TextPaint getTextPaint() {
+            return mPaint;
+        }
+
+        /**
+         * Returns the {@link TextDirectionHeuristic} for this text
+         *
+         * @return A {@link TextDirectionHeuristic}
+         */
+        public @NonNull TextDirectionHeuristic getTextDirection() {
+            return mTextDir;
+        }
+
+        /**
+         * Returns the break strategy for this text
+         *
+         * @return A line break strategy
+         */
+        public @Layout.BreakStrategy int getBreakStrategy() {
+            return mBreakStrategy;
+        }
+
+        /**
+         * Returns the hyphenation frequency for this text
+         *
+         * @return A hyphenation frequency
+         */
+        public @Layout.HyphenationFrequency int getHyphenationFrequency() {
+            return mHyphenationFrequency;
+        }
+
+        private boolean sameTextMetricsInternal(@NonNull TextPaint paint,
+                @NonNull TextDirectionHeuristic textDir, @Layout.BreakStrategy int strategy,
+                @Layout.HyphenationFrequency int frequency) {
+            return mTextDir == textDir
+                && mBreakStrategy == strategy
+                && mHyphenationFrequency == frequency
+                && mPaint.equalsForTextMeasurement(paint);
+        }
+
+        /**
+         * Check if the same text layout.
+         *
+         * @return true if this and the given param result in the same text layout
+         */
+        public boolean sameTextMetrics(@NonNull Params param) {
+            return sameTextMetricsInternal(param.mPaint, param.mTextDir, param.mBreakStrategy,
+                    param.mHyphenationFrequency);
+        }
+    };
+
+    // The original text.
+    private final @NonNull CharSequence mText;
+
+    // The inclusive start offset of the measuring target.
+    private final @IntRange(from = 0) int mStart;
+
+    // The exclusive end offset of the measuring target.
+    private final @IntRange(from = 0) int mEnd;
+
+    private final @NonNull Params mParams;
+
+    // The measured paragraph texts.
+    private final @NonNull MeasuredParagraph[] mMeasuredParagraphs;
+
+    // The sorted paragraph end offsets.
+    private final @NonNull int[] mParagraphBreakPoints;
+
+    /**
+     * Create a new {@link PrecomputedText} which will pre-compute text measurement and glyph
+     * positioning information.
+     * <p>
+     * This can be expensive, so computing this on a background thread before your text will be
+     * presented can save work on the UI thread.
+     * </p>
+     *
+     * @param text The text to be measured
+     * @param param Parameters that define how text will be precomputed
+     * @return A {@link PrecomputedText}
+     */
+    public static PrecomputedText create(@NonNull CharSequence text, @NonNull Params param) {
+        return createInternal(text, param, 0, text.length(), true /* compute full Layout */);
+    }
+
+
+    /** @hide */
+    public static PrecomputedText createWidthOnly(@NonNull CharSequence text, @NonNull Params param,
+            @IntRange(from = 0) int start, @IntRange(from = 0) int end) {
+        return createInternal(text, param, start, end, false /* compute width only */);
+    }
+
+    private static PrecomputedText createInternal(@NonNull CharSequence text, @NonNull Params param,
+            @IntRange(from = 0) int start, @IntRange(from = 0) int end, boolean computeLayout) {
+        Preconditions.checkNotNull(text);
+        Preconditions.checkNotNull(param);
+        final boolean needHyphenation = param.getBreakStrategy() != Layout.BREAK_STRATEGY_SIMPLE
+                && param.getHyphenationFrequency() != Layout.HYPHENATION_FREQUENCY_NONE;
+
+        final IntArray paragraphEnds = new IntArray();
+        final ArrayList<MeasuredParagraph> measuredTexts = new ArrayList<>();
+
+        int paraEnd = 0;
+        for (int paraStart = start; paraStart < end; paraStart = paraEnd) {
+            paraEnd = TextUtils.indexOf(text, LINE_FEED, paraStart, end);
+            if (paraEnd < 0) {
+                // No LINE_FEED(U+000A) character found. Use end of the text as the paragraph
+                // end.
+                paraEnd = end;
+            } else {
+                paraEnd++;  // Includes LINE_FEED(U+000A) to the prev paragraph.
+            }
+
+            paragraphEnds.add(paraEnd);
+            measuredTexts.add(MeasuredParagraph.buildForStaticLayout(
+                    param.getTextPaint(), text, paraStart, paraEnd, param.getTextDirection(),
+                    needHyphenation, computeLayout, null /* no recycle */));
+        }
+
+        return new PrecomputedText(text, start, end, param,
+                                measuredTexts.toArray(new MeasuredParagraph[measuredTexts.size()]),
+                                paragraphEnds.toArray());
+    }
+
+    // Use PrecomputedText.create instead.
+    private PrecomputedText(@NonNull CharSequence text, @IntRange(from = 0) int start,
+            @IntRange(from = 0) int end, @NonNull Params param,
+            @NonNull MeasuredParagraph[] measuredTexts, @NonNull int[] paragraphBreakPoints) {
+        mText = TextUtils.stringOrSpannedString(text);
+        mStart = start;
+        mEnd = end;
+        mParams = param;
+        mMeasuredParagraphs = measuredTexts;
+        mParagraphBreakPoints = paragraphBreakPoints;
+    }
+
+    /**
+     * Return the underlying text.
+     */
+    public @NonNull CharSequence getText() {
+        return mText;
+    }
+
+    /**
+     * Returns the inclusive start offset of measured region.
+     * @hide
+     */
+    public @IntRange(from = 0) int getStart() {
+        return mStart;
+    }
+
+    /**
+     * Returns the exclusive end offset of measured region.
+     * @hide
+     */
+    public @IntRange(from = 0) int getEnd() {
+        return mEnd;
+    }
+
+    /**
+     * Returns the layout parameters used to measure this text.
+     */
+    public @NonNull Params getParams() {
+        return mParams;
+    }
+
+    /**
+     * Returns the length of the paragraph of this text.
+     */
+    public @IntRange(from = 0) int getParagraphCount() {
+        return mParagraphBreakPoints.length;
+    }
+
+    /**
+     * Returns the paragraph start offset of the text.
+     */
+    public @IntRange(from = 0) int getParagraphStart(@IntRange(from = 0) int paraIndex) {
+        Preconditions.checkArgumentInRange(paraIndex, 0, getParagraphCount(), "paraIndex");
+        return paraIndex == 0 ? mStart : mParagraphBreakPoints[paraIndex - 1];
+    }
+
+    /**
+     * Returns the paragraph end offset of the text.
+     */
+    public @IntRange(from = 0) int getParagraphEnd(@IntRange(from = 0) int paraIndex) {
+        Preconditions.checkArgumentInRange(paraIndex, 0, getParagraphCount(), "paraIndex");
+        return mParagraphBreakPoints[paraIndex];
+    }
+
+    /** @hide */
+    public @NonNull MeasuredParagraph getMeasuredParagraph(@IntRange(from = 0) int paraIndex) {
+        return mMeasuredParagraphs[paraIndex];
+    }
+
+    /**
+     * Returns true if the given TextPaint gives the same result of text layout for this text.
+     * @hide
+     */
+    public boolean canUseMeasuredResult(@IntRange(from = 0) int start, @IntRange(from = 0) int end,
+            @NonNull TextDirectionHeuristic textDir, @NonNull TextPaint paint,
+            @Layout.BreakStrategy int strategy, @Layout.HyphenationFrequency int frequency) {
+        final TextPaint mtPaint = mParams.getTextPaint();
+        return mStart == start
+            && mEnd == end
+            && mParams.sameTextMetricsInternal(paint, textDir, strategy, frequency);
+    }
+
+    /** @hide */
+    public int findParaIndex(@IntRange(from = 0) int pos) {
+        // TODO: Maybe good to remove paragraph concept from PrecomputedText and add substring
+        //       layout support to StaticLayout.
+        for (int i = 0; i < mParagraphBreakPoints.length; ++i) {
+            if (pos < mParagraphBreakPoints[i]) {
+                return i;
+            }
+        }
+        throw new IndexOutOfBoundsException(
+            "pos must be less than " + mParagraphBreakPoints[mParagraphBreakPoints.length - 1]
+            + ", gave " + pos);
+    }
+
+    /** @hide */
+    public float getWidth(@IntRange(from = 0) int start, @IntRange(from = 0) int end) {
+        final int paraIndex = findParaIndex(start);
+        final int paraStart = getParagraphStart(paraIndex);
+        final int paraEnd = getParagraphEnd(paraIndex);
+        if (start < paraStart || paraEnd < end) {
+            throw new RuntimeException("Cannot measured across the paragraph:"
+                + "para: (" + paraStart + ", " + paraEnd + "), "
+                + "request: (" + start + ", " + end + ")");
+        }
+        return getMeasuredParagraph(paraIndex).getWidth(start - paraStart, end - paraStart);
+    }
+
+    /**
+     * Returns the size of native PrecomputedText memory usage
+     *
+     * Note that this is not guaranteed to be accurate. Must be used only for testing purposes.
+     * @hide
+     */
+    public int getMemoryUsage() {
+        int r = 0;
+        for (int i = 0; i < getParagraphCount(); ++i) {
+            r += getMeasuredParagraph(i).getMemoryUsage();
+        }
+        return r;
+    }
+}
diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java
index e62f421..5869802 100644
--- a/core/java/android/text/StaticLayout.java
+++ b/core/java/android/text/StaticLayout.java
@@ -78,6 +78,23 @@
         /**
          * Obtain a builder for constructing StaticLayout objects.
          *
+         * @param source The precomputed text.
+         * @param start The index of the start of the text
+         * @param end The index + 1 of the end of the text
+         * @param paint The base paint used for layout
+         * @param width The width in pixels
+         * @return a builder object used for constructing the StaticLayout
+         */
+        @NonNull
+        public static Builder obtain(@NonNull PrecomputedText source, @IntRange(from = 0) int start,
+                @IntRange(from = 0) int end, @NonNull TextPaint paint,
+                @IntRange(from = 0) int width) {
+            return obtain(source.getText(), source, start, end, paint, width);
+        }
+
+        /**
+         * Obtain a builder for constructing StaticLayout objects.
+         *
          * @param source The text to be laid out, optionally with spans
          * @param start The index of the start of the text
          * @param end The index + 1 of the end of the text
@@ -89,6 +106,12 @@
         public static Builder obtain(@NonNull CharSequence source, @IntRange(from = 0) int start,
                 @IntRange(from = 0) int end, @NonNull TextPaint paint,
                 @IntRange(from = 0) int width) {
+            return obtain(source, null, start, end, paint, width);
+        }
+
+        private static Builder obtain(@NonNull CharSequence source, @Nullable PrecomputedText text,
+                @IntRange(from = 0) int start, @IntRange(from = 0) int end,
+                @NonNull TextPaint paint, @IntRange(from = 0) int width) {
             Builder b = sPool.acquire();
             if (b == null) {
                 b = new Builder();
@@ -96,6 +119,7 @@
 
             // set default initial values
             b.mText = source;
+            b.mPrecomputed = text;
             b.mStart = start;
             b.mEnd = end;
             b.mPaint = paint;
@@ -428,6 +452,7 @@
         }
 
         private CharSequence mText;
+        private PrecomputedText mPrecomputed;
         private int mStart;
         private int mEnd;
         private TextPaint mPaint;
@@ -490,7 +515,7 @@
             float spacingmult, float spacingadd,
             boolean includepad,
             TextUtils.TruncateAt ellipsize, int ellipsizedWidth) {
-        this(source, bufstart, bufend, paint, outerwidth, align,
+        this(source, null /* precomputed */, bufstart, bufend, paint, outerwidth, align,
                 TextDirectionHeuristics.FIRSTSTRONG_LTR,
                 spacingmult, spacingadd, includepad, ellipsize, ellipsizedWidth, Integer.MAX_VALUE);
     }
@@ -500,7 +525,16 @@
      * @deprecated Use {@link Builder} instead.
      */
     @Deprecated
-    public StaticLayout(CharSequence source, int bufstart, int bufend,
+    public StaticLayout(CharSequence source, int bufstart, int bufend, TextPaint paint,
+                        int outerwidth, Alignment align, TextDirectionHeuristic textDir,
+                        float spacingmult, float spacingadd, boolean includepad,
+                        TextUtils.TruncateAt ellipsize, int ellipsizedWidth, int maxLines) {
+        this(source, null /* precomputed */, bufstart, bufend, paint, outerwidth, align, textDir,
+                spacingmult, spacingadd, includepad, ellipsize, ellipsizedWidth, maxLines);
+    }
+
+    /** @hide */
+    public StaticLayout(CharSequence source, PrecomputedText precomputed, int bufstart, int bufend,
                         TextPaint paint, int outerwidth,
                         Alignment align, TextDirectionHeuristic textDir,
                         float spacingmult, float spacingadd,
@@ -511,6 +545,7 @@
                 : (source instanceof Spanned)
                     ? new SpannedEllipsizer(source)
                     : new Ellipsizer(source),
+              (ellipsize == null) ? precomputed : null,
               paint, outerwidth, align, textDir, spacingmult, spacingadd);
 
         Builder b = Builder.obtain(source, bufstart, bufend, paint, outerwidth)
@@ -651,43 +686,20 @@
                 b.mJustificationMode != Layout.JUSTIFICATION_MODE_NONE,
                 indents, mLeftPaddings, mRightPaddings);
 
-        MeasuredText measured = null;
-        final Spanned spanned;
-        final boolean canUseMeasuredText;
-        if (source instanceof MeasuredText) {
-            measured = (MeasuredText) source;
-
-            if (bufStart != measured.getStart() || bufEnd != measured.getEnd()) {
-                // The buffer position has changed. Re-measure here.
-                canUseMeasuredText = false;
-            } else if (b.mBreakStrategy != measured.getBreakStrategy()
-                    || b.mHyphenationFrequency != measured.getHyphenationFrequency()) {
-                // The computed hyphenation pieces may not be able to used. Re-measure it.
-                canUseMeasuredText = false;
-            } else {
-                // We can use measured information.
-                canUseMeasuredText = true;
+        PrecomputedText measured = null;
+        final Spanned spanned = (b.mText instanceof Spanned) ? (Spanned) b.mText : null;
+        if (b.mPrecomputed != null) {
+            if (b.mPrecomputed.canUseMeasuredResult(bufStart, bufEnd, textDir, paint,
+                      b.mBreakStrategy, b.mHyphenationFrequency)) {
+                measured = b.mPrecomputed;
             }
-        } else {
-            canUseMeasuredText = false;
+        }
+        if (measured == null) {
+            final PrecomputedText.Params param = new PrecomputedText.Params(paint, textDir,
+                    b.mBreakStrategy, b.mHyphenationFrequency);
+            measured = PrecomputedText.createWidthOnly(source, param, bufStart, bufEnd);
         }
 
-        if (!canUseMeasuredText) {
-            measured = new MeasuredText.Builder(source, paint)
-                    .setRange(bufStart, bufEnd)
-                    .setTextDirection(textDir)
-                    .setBreakStrategy(b.mBreakStrategy)
-                    .setHyphenationFrequency(b.mHyphenationFrequency)
-                    .build(false /* full layout is not necessary for line breaking */);
-            spanned = (source instanceof Spanned) ? (Spanned) source : null;
-        } else {
-            final CharSequence original = measured.getText();
-            spanned = (original instanceof Spanned) ? (Spanned) original : null;
-            // Overwrite with the one when measured.
-            // TODO: Give an option for developer not to overwrite and measure again here?
-            textDir = measured.getTextDir();
-            paint = measured.getPaint();
-        }
 
         try {
             for (int paraIndex = 0; paraIndex < measured.getParagraphCount(); paraIndex++) {
diff --git a/core/java/android/text/TextLine.java b/core/java/android/text/TextLine.java
index 55367dc..be5bb4d 100644
--- a/core/java/android/text/TextLine.java
+++ b/core/java/android/text/TextLine.java
@@ -16,6 +16,7 @@
 
 package android.text;
 
+import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.graphics.Canvas;
@@ -60,7 +61,7 @@
     private char[] mChars;
     private boolean mCharsValid;
     private Spanned mSpanned;
-    private MeasuredText mMeasured;
+    private PrecomputedText mComputed;
 
     // Additional width of whitespace for justification. This value is per whitespace, thus
     // the line width will increase by mAddedWidth x (number of stretchable whitespaces).
@@ -119,7 +120,7 @@
         tl.mSpanned = null;
         tl.mTabs = null;
         tl.mChars = null;
-        tl.mMeasured = null;
+        tl.mComputed = null;
 
         tl.mMetricAffectingSpanSpanSet.recycle();
         tl.mCharacterStyleSpanSet.recycle();
@@ -149,10 +150,31 @@
      * @param tabStops the tabStops. Can be null.
      */
     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
-    public void set(TextPaint paint, CharSequence text, int start, int limit, int dir,
-            Directions directions, boolean hasTabs, TabStops tabStops) {
+    public void set(TextPaint paint, CharSequence text, int start,
+            int limit, int dir, Directions directions, boolean hasTabs, TabStops tabStops) {
+        set(paint, text, null, start, limit, dir, directions, hasTabs, tabStops);
+    }
+
+    /**
+     * Initializes a TextLine and prepares it for use.
+     *
+     * @param paint the base paint for the line
+     * @param text the text, can be Styled
+     * @param precomputed the precomputed text
+     * @param start the start of the line relative to the text
+     * @param limit the limit of the line relative to the text
+     * @param dir the paragraph direction of this line
+     * @param directions the directions information of this line
+     * @param hasTabs true if the line might contain tabs
+     * @param tabStops the tabStops.
+     */
+    public void set(@NonNull TextPaint paint, @NonNull CharSequence text,
+            @Nullable PrecomputedText precomputed, @IntRange(from = 0) int start,
+            @IntRange(from = 0) int limit, int dir, @NonNull Directions directions, boolean hasTabs,
+            @Nullable TabStops tabStops) {
         mPaint = paint;
         mText = text;
+        mComputed = precomputed;
         mStart = start;
         mLen = limit - start;
         mDir = dir;
@@ -170,14 +192,6 @@
             hasReplacement = mReplacementSpanSpanSet.numberOfSpans > 0;
         }
 
-        mMeasured = null;
-        if (text instanceof MeasuredText) {
-            MeasuredText mt = (MeasuredText) text;
-            if (mt.canUseMeasuredResult(paint)) {
-                mMeasured = mt;
-            }
-        }
-
         mCharsValid = hasReplacement || hasTabs || directions != Layout.DIRS_ALL_LEFT_TO_RIGHT;
 
         if (mCharsValid) {
@@ -746,12 +760,12 @@
             return wp.getRunAdvance(mChars, start, end, contextStart, contextEnd, runIsRtl, offset);
         } else {
             final int delta = mStart;
-            if (mMeasured == null) {
+            if (mComputed == null) {
                 // TODO: Enable measured getRunAdvance for ReplacementSpan and RTL text.
                 return wp.getRunAdvance(mText, delta + start, delta + end,
                         delta + contextStart, delta + contextEnd, runIsRtl, delta + offset);
             } else {
-                return mMeasured.getWidth(start + delta, end + delta);
+                return mComputed.getWidth(start + delta, end + delta);
             }
         }
     }
diff --git a/core/java/android/transition/TransitionUtils.java b/core/java/android/transition/TransitionUtils.java
index 60b77bc..46c9e0c 100644
--- a/core/java/android/transition/TransitionUtils.java
+++ b/core/java/android/transition/TransitionUtils.java
@@ -20,14 +20,13 @@
 import android.animation.AnimatorSet;
 import android.animation.TypeEvaluator;
 import android.graphics.Bitmap;
+import android.graphics.Canvas;
 import android.graphics.Matrix;
+import android.graphics.Picture;
 import android.graphics.Rect;
 import android.graphics.RectF;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
-import android.view.DisplayListCanvas;
-import android.view.RenderNode;
-import android.view.ThreadedRenderer;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.ImageView;
@@ -128,10 +127,8 @@
         }
         int bitmapWidth = (int) (width * scale);
         int bitmapHeight = (int) (height * scale);
-        final RenderNode node = RenderNode.create("TransitionUtils", hostView);
-        node.setLeftTopRightBottom(0, 0, width, height);
-        node.setClipToBounds(false);
-        final DisplayListCanvas canvas = node.start(width, height);
+        final Picture picture = new Picture();
+        final Canvas canvas = picture.beginRecording(width, height);
         // Do stuff with the canvas
         Rect existingBounds = drawable.getBounds();
         int left = existingBounds.left;
@@ -141,8 +138,8 @@
         drawable.setBounds(0, 0, bitmapWidth, bitmapHeight);
         drawable.draw(canvas);
         drawable.setBounds(left, top, right, bottom);
-        node.end(canvas);
-        return ThreadedRenderer.createHardwareBitmap(node, width, height);
+        picture.endRecording();
+        return Bitmap.createBitmap(picture);
     }
 
     /**
@@ -183,14 +180,12 @@
             matrix.postTranslate(-bounds.left, -bounds.top);
             matrix.postScale(scale, scale);
 
-            final RenderNode node = RenderNode.create("TransitionUtils", view);
-            node.setLeftTopRightBottom(0, 0, bitmapWidth, bitmapHeight);
-            node.setClipToBounds(false);
-            final DisplayListCanvas canvas = node.start(bitmapWidth, bitmapHeight);
+            final Picture picture = new Picture();
+            final Canvas canvas = picture.beginRecording(bitmapWidth, bitmapHeight);
             canvas.concat(matrix);
             view.draw(canvas);
-            node.end(canvas);
-            bitmap = ThreadedRenderer.createHardwareBitmap(node, bitmapWidth, bitmapHeight);
+            picture.endRecording();
+            bitmap = Bitmap.createBitmap(picture);
         }
         if (addToOverlay) {
             sceneRoot.getOverlay().remove(view);
diff --git a/core/java/android/util/MemoryIntArray.java b/core/java/android/util/MemoryIntArray.java
index 5970892..bf33519 100644
--- a/core/java/android/util/MemoryIntArray.java
+++ b/core/java/android/util/MemoryIntArray.java
@@ -16,18 +16,12 @@
 
 package android.util;
 
-import static android.os.Process.FIRST_APPLICATION_UID;
-
 import android.os.Parcel;
 import android.os.ParcelFileDescriptor;
 import android.os.Parcelable;
-import android.os.Process;
-
-import com.android.internal.annotations.GuardedBy;
-
-import dalvik.system.CloseGuard;
 
 import libcore.io.IoUtils;
+import dalvik.system.CloseGuard;
 
 import java.io.Closeable;
 import java.io.IOException;
@@ -55,18 +49,13 @@
  */
 public final class MemoryIntArray implements Parcelable, Closeable {
     private static final String TAG = "MemoryIntArray";
-    private static final boolean DEBUG = Process.myUid() < FIRST_APPLICATION_UID;
 
     private static final int MAX_SIZE = 1024;
 
-    private final Object mLock = new Object();
     private final CloseGuard mCloseGuard = CloseGuard.get();
 
     private final boolean mIsOwner;
     private final long mMemoryAddr;
-
-    /** Fd for the shared memory object, -1 when closed */
-    @GuardedBy("mLock")
     private int mFd = -1;
 
     /**
@@ -85,7 +74,6 @@
         mFd = nativeCreate(name, size);
         mMemoryAddr = nativeOpen(mFd, mIsOwner);
         mCloseGuard.open("close");
-        if (DEBUG) Log.i(TAG, "created " + getString());
     }
 
     private MemoryIntArray(Parcel parcel) throws IOException {
@@ -97,8 +85,6 @@
         mFd = pfd.detachFd();
         mMemoryAddr = nativeOpen(mFd, mIsOwner);
         mCloseGuard.open("close");
-
-        if (DEBUG) Log.i(TAG, "created from parcel " + getString());
     }
 
     /**
@@ -155,33 +141,13 @@
      */
     @Override
     public void close() throws IOException {
-        synchronized (mLock) {
-            if (!isClosed()) {
-                if (DEBUG) {
-                    try {
-                        throw new Exception();
-                    } catch (Exception here) {
-                        Log.i(TAG, "closing " + getString(), here);
-                    }
-                }
-                nativeClose(mFd, mMemoryAddr, mIsOwner);
-                mFd = -1;
-                mCloseGuard.close();
-            } else {
-                try {
-                    throw new Exception();
-                } catch (Exception here) {
-                    if (DEBUG) Log.i(TAG, getString() + " already closed", here);
-                }
-            }
+        if (!isClosed()) {
+            nativeClose(mFd, mMemoryAddr, mIsOwner);
+            mFd = -1;
+            mCloseGuard.close();
         }
     }
 
-    private String getString() {
-        return this.getClass().getSimpleName() + "@" + System.identityHashCode(this)
-                + " mMemoryAddr=" + mMemoryAddr + " mFd=" + mFd;
-    }
-
     /**
      * @return Whether this array is closed and shouldn't be used.
      */
@@ -196,9 +162,7 @@
                 mCloseGuard.warnIfOpen();
             }
 
-            if (!isClosed()) {
-                IoUtils.closeQuietly(this);
-            }
+            IoUtils.closeQuietly(this);
         } finally {
             super.finalize();
         }
@@ -242,8 +206,7 @@
 
     private void enforceNotClosed() {
         if (isClosed()) {
-            throw new IllegalStateException("cannot interact with a closed instance "
-                    + getString());
+            throw new IllegalStateException("cannot interact with a closed instance");
         }
     }
 
diff --git a/core/java/android/view/PointerIcon.java b/core/java/android/view/PointerIcon.java
index 8cb46b7..3fd4696 100644
--- a/core/java/android/view/PointerIcon.java
+++ b/core/java/android/view/PointerIcon.java
@@ -23,10 +23,6 @@
 import android.content.res.TypedArray;
 import android.content.res.XmlResourceParser;
 import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.Rect;
-import android.graphics.RectF;
 import android.graphics.drawable.AnimationDrawable;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
@@ -400,33 +396,6 @@
         return true;
     }
 
-    /**
-     *  Get the Bitmap from the Drawable.
-     *
-     *  If the Bitmap needed to be scaled up to account for density, BitmapDrawable
-     *  handles this at draw time. But this class doesn't actually draw the Bitmap;
-     *  it is just a holder for native code to access its SkBitmap. So this needs to
-     *  get a version that is scaled to account for density.
-     */
-    private Bitmap getBitmapFromDrawable(BitmapDrawable bitmapDrawable) {
-        Bitmap bitmap = bitmapDrawable.getBitmap();
-        final int scaledWidth  = bitmapDrawable.getIntrinsicWidth();
-        final int scaledHeight = bitmapDrawable.getIntrinsicHeight();
-        if (scaledWidth == bitmap.getWidth() && scaledHeight == bitmap.getHeight()) {
-            return bitmap;
-        }
-
-        Rect src = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
-        RectF dst = new RectF(0, 0, scaledWidth, scaledHeight);
-
-        Bitmap scaled = Bitmap.createBitmap(scaledWidth, scaledHeight, bitmap.getConfig());
-        Canvas canvas = new Canvas(scaled);
-        Paint paint = new Paint();
-        paint.setFilterBitmap(true);
-        canvas.drawBitmap(bitmap, src, dst, paint);
-        return scaled;
-    }
-
     private void loadResource(Context context, Resources resources, @XmlRes int resourceId) {
         final XmlResourceParser parser = resources.getXml(resourceId);
         final int bitmapRes;
@@ -483,8 +452,7 @@
                                 + "is different. All frames should have the exact same size and "
                                 + "share the same hotspot.");
                     }
-                    BitmapDrawable bitmapDrawableFrame = (BitmapDrawable) drawableFrame;
-                    mBitmapFrames[i - 1] = getBitmapFromDrawable(bitmapDrawableFrame);
+                    mBitmapFrames[i - 1] = ((BitmapDrawable)drawableFrame).getBitmap();
                 }
             }
         }
@@ -493,8 +461,7 @@
                     + "refer to a bitmap drawable.");
         }
 
-        BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
-        final Bitmap bitmap = getBitmapFromDrawable(bitmapDrawable);
+        final Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();
         validateHotSpot(bitmap, hotSpotX, hotSpotY);
         // Set the properties now that we have successfully loaded the icon.
         mBitmap = bitmap;
diff --git a/core/java/android/view/RecordingCanvas.java b/core/java/android/view/RecordingCanvas.java
index fbb862b..fc7d828 100644
--- a/core/java/android/view/RecordingCanvas.java
+++ b/core/java/android/view/RecordingCanvas.java
@@ -34,7 +34,7 @@
 import android.graphics.RectF;
 import android.graphics.TemporaryBuffer;
 import android.text.GraphicsOperations;
-import android.text.MeasuredText;
+import android.text.PrecomputedText;
 import android.text.SpannableString;
 import android.text.SpannedString;
 import android.text.TextUtils;
@@ -507,8 +507,8 @@
             TextUtils.getChars(text, contextStart, contextEnd, buf, 0);
             long measuredTextPtr = 0;
             int measuredTextOffset = 0;
-            if (text instanceof MeasuredText) {
-                MeasuredText mt = (MeasuredText) text;
+            if (text instanceof PrecomputedText) {
+                PrecomputedText mt = (PrecomputedText) text;
                 int paraIndex = mt.findParaIndex(start);
                 if (end <= mt.getParagraphEnd(paraIndex)) {
                     // Only support if the target is in the same paragraph.
@@ -641,7 +641,7 @@
     @FastNative
     private static native void nDrawTextRun(long nativeCanvas, char[] text, int start, int count,
             int contextStart, int contextCount, float x, float y, boolean isRtl, long nativePaint,
-            long nativeMeasuredText, int measuredTextOffset);
+            long nativePrecomputedText, int measuredTextOffset);
 
     @FastNative
     private static native void nDrawTextOnPath(long nativeCanvas, char[] text, int index, int count,
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 5de25ba..2af2467 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -7308,6 +7308,10 @@
         return mAccessibilityPaneTitle;
     }
 
+    private boolean isAccessibilityPane() {
+        return !TextUtils.isEmpty(mAccessibilityPaneTitle);
+    }
+
     /**
      * Sends an accessibility event of the given type. If accessibility is
      * not enabled this method has no effect. The default implementation calls
@@ -7871,6 +7875,7 @@
                 structure.setAutofillHints(getAutofillHints());
                 structure.setAutofillValue(getAutofillValue());
             }
+            structure.setImportantForAutofill(getImportantForAutofill());
         }
 
         int ignoredParentLeft = 0;
@@ -8366,6 +8371,11 @@
             }
         }
 
+        // If the app developer explicitly set hints for it, it's important.
+        if (getAutofillHints() != null) {
+            return true;
+        }
+
         // Otherwise, assume it's not important...
         return false;
     }
@@ -11631,7 +11641,7 @@
         return mode == IMPORTANT_FOR_ACCESSIBILITY_YES || isActionableForAccessibility()
                 || hasListenersForAccessibility() || getAccessibilityNodeProvider() != null
                 || getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE
-                || (mAccessibilityPaneTitle != null);
+                || isAccessibilityPane();
     }
 
     /**
@@ -11728,18 +11738,26 @@
 
         // Changes to views with a pane title count as window state changes, as the pane title
         // marks them as significant parts of the UI.
-        if (!TextUtils.isEmpty(getAccessibilityPaneTitle())) {
-            final AccessibilityEvent event = AccessibilityEvent.obtain();
-            event.setEventType(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
-            event.setContentChangeTypes(changeType);
-            onPopulateAccessibilityEvent(event);
-            if (mParent != null) {
-                try {
-                    mParent.requestSendAccessibilityEvent(this, event);
-                } catch (AbstractMethodError e) {
-                    Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName()
-                            + " does not fully implement ViewParent", e);
+        if ((changeType != AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE)
+                && isAccessibilityPane()) {
+            // If the pane isn't visible, content changed events are sufficient unless we're
+            // reporting that the view just disappeared
+            if ((getVisibility() == VISIBLE)
+                    || (changeType == AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_DISAPPEARED)) {
+                final AccessibilityEvent event = AccessibilityEvent.obtain();
+                event.setEventType(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
+                event.setContentChangeTypes(changeType);
+                event.setSource(this);
+                onPopulateAccessibilityEvent(event);
+                if (mParent != null) {
+                    try {
+                        mParent.requestSendAccessibilityEvent(this, event);
+                    } catch (AbstractMethodError e) {
+                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName()
+                                + " does not fully implement ViewParent", e);
+                    }
                 }
+                return;
             }
         }
 
@@ -14029,6 +14047,11 @@
         }
 
         if (accessibilityEnabled) {
+            // If we're an accessibility pane and the visibility changed, we already have sent
+            // a state change, so we really don't need to report other changes.
+            if (isAccessibilityPane()) {
+                changed &= ~VISIBILITY_MASK;
+            }
             if ((changed & FOCUSABLE) != 0 || (changed & VISIBILITY_MASK) != 0
                     || (changed & CLICKABLE) != 0 || (changed & LONG_CLICKABLE) != 0
                     || (changed & CONTEXT_CLICKABLE) != 0) {
diff --git a/core/java/android/view/ViewDebug.java b/core/java/android/view/ViewDebug.java
index b09934e..276f50a 100644
--- a/core/java/android/view/ViewDebug.java
+++ b/core/java/android/view/ViewDebug.java
@@ -21,7 +21,7 @@
 import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
-import android.graphics.Point;
+import android.graphics.Picture;
 import android.graphics.Rect;
 import android.os.Debug;
 import android.os.Handler;
@@ -1782,27 +1782,18 @@
      * @hide
      */
     public static class HardwareCanvasProvider implements CanvasProvider {
-
-        private View mView;
-        private Point mSize;
-        private RenderNode mNode;
-        private DisplayListCanvas mCanvas;
+        private Picture mPicture;
 
         @Override
         public Canvas getCanvas(View view, int width, int height) {
-            mView = view;
-            mSize = new Point(width, height);
-            mNode = RenderNode.create("ViewDebug", mView);
-            mNode.setLeftTopRightBottom(0, 0, width, height);
-            mNode.setClipToBounds(false);
-            mCanvas = mNode.start(width, height);
-            return mCanvas;
+            mPicture = new Picture();
+            return mPicture.beginRecording(width, height);
         }
 
         @Override
         public Bitmap createBitmap() {
-            mNode.end(mCanvas);
-            return ThreadedRenderer.createHardwareBitmap(mNode, mSize.x, mSize.y);
+            mPicture.endRecording();
+            return Bitmap.createBitmap(mPicture);
         }
     }
 
diff --git a/core/java/android/view/ViewStructure.java b/core/java/android/view/ViewStructure.java
index 1d94abe..3f7ab2a 100644
--- a/core/java/android/view/ViewStructure.java
+++ b/core/java/android/view/ViewStructure.java
@@ -23,6 +23,8 @@
 import android.os.Bundle;
 import android.os.LocaleList;
 import android.util.Pair;
+import android.view.View.AutofillImportance;
+import android.view.ViewStructure.HtmlInfo;
 import android.view.autofill.AutofillId;
 import android.view.autofill.AutofillValue;
 
@@ -347,6 +349,12 @@
     public abstract void setAutofillOptions(CharSequence[] options);
 
     /**
+     * Sets the {@link View#setImportantForAutofill(int) importantForAutofill mode} of the
+     * view associated with this node.
+     */
+    public void setImportantForAutofill(@AutofillImportance int mode) {}
+
+    /**
      * Sets the {@link android.text.InputType} bits of this node.
      *
      * @param inputType inputType bits as defined by {@link android.text.InputType}.
diff --git a/core/java/android/view/WindowInfo.java b/core/java/android/view/WindowInfo.java
index bb9e391..7bae28a 100644
--- a/core/java/android/view/WindowInfo.java
+++ b/core/java/android/view/WindowInfo.java
@@ -21,6 +21,7 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.Pools;
+import android.view.accessibility.AccessibilityNodeInfo;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -46,7 +47,7 @@
     public final Rect boundsInScreen = new Rect();
     public List<IBinder> childTokens;
     public CharSequence title;
-    public int accessibilityIdOfAnchor = View.NO_ID;
+    public long accessibilityIdOfAnchor = AccessibilityNodeInfo.UNDEFINED_NODE_ID;
     public boolean inPictureInPicture;
 
     private WindowInfo() {
@@ -105,7 +106,7 @@
         parcel.writeInt(focused ? 1 : 0);
         boundsInScreen.writeToParcel(parcel, flags);
         parcel.writeCharSequence(title);
-        parcel.writeInt(accessibilityIdOfAnchor);
+        parcel.writeLong(accessibilityIdOfAnchor);
         parcel.writeInt(inPictureInPicture ? 1 : 0);
 
         if (childTokens != null && !childTokens.isEmpty()) {
@@ -142,7 +143,7 @@
         focused = (parcel.readInt() == 1);
         boundsInScreen.readFromParcel(parcel);
         title = parcel.readCharSequence();
-        accessibilityIdOfAnchor = parcel.readInt();
+        accessibilityIdOfAnchor = parcel.readLong();
         inPictureInPicture = (parcel.readInt() == 1);
 
         final boolean hasChildren = (parcel.readInt() == 1);
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 1c5e871..c0a9666 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -63,6 +63,7 @@
 import android.text.TextUtils;
 import android.util.Log;
 import android.util.proto.ProtoOutputStream;
+import android.view.accessibility.AccessibilityNodeInfo;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -2344,7 +2345,7 @@
          *
          * @hide
          */
-        public int accessibilityIdOfAnchor = -1;
+        public long accessibilityIdOfAnchor = AccessibilityNodeInfo.UNDEFINED_NODE_ID;
 
         /**
          * The window title isn't kept in sync with what is displayed in the title bar, so we
@@ -2538,7 +2539,7 @@
             out.writeInt(hasManualSurfaceInsets ? 1 : 0);
             out.writeInt(preservePreviousSurfaceInsets ? 1 : 0);
             out.writeInt(needsMenuKey);
-            out.writeInt(accessibilityIdOfAnchor);
+            out.writeLong(accessibilityIdOfAnchor);
             TextUtils.writeToParcel(accessibilityTitle, out, parcelableFlags);
             out.writeInt(mColorMode);
             out.writeLong(hideTimeoutMilliseconds);
@@ -2594,7 +2595,7 @@
             hasManualSurfaceInsets = in.readInt() != 0;
             preservePreviousSurfaceInsets = in.readInt() != 0;
             needsMenuKey = in.readInt();
-            accessibilityIdOfAnchor = in.readInt();
+            accessibilityIdOfAnchor = in.readLong();
             accessibilityTitle = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
             mColorMode = in.readInt();
             hideTimeoutMilliseconds = in.readLong();
diff --git a/core/java/android/view/textclassifier/TextClassification.java b/core/java/android/view/textclassifier/TextClassification.java
index a6a2a94..8fe1d8f 100644
--- a/core/java/android/view/textclassifier/TextClassification.java
+++ b/core/java/android/view/textclassifier/TextClassification.java
@@ -22,6 +22,7 @@
 import android.annotation.Nullable;
 import android.content.Context;
 import android.content.Intent;
+import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.drawable.BitmapDrawable;
@@ -378,7 +379,7 @@
         final List<Drawable> drawables = new ArrayList<>(bitmaps.size());
         for (Bitmap bitmap : bitmaps) {
             if (bitmap != null) {
-                drawables.add(new BitmapDrawable(null, bitmap));
+                drawables.add(new BitmapDrawable(Resources.getSystem(), bitmap));
             } else {
                 drawables.add(null);
             }
@@ -681,7 +682,8 @@
     private TextClassification(Parcel in) {
         mText = in.readString();
         mPrimaryIcon = in.readInt() == 0
-                ? null : new BitmapDrawable(null, Bitmap.CREATOR.createFromParcel(in));
+                ? null
+                : new BitmapDrawable(Resources.getSystem(), Bitmap.CREATOR.createFromParcel(in));
         mPrimaryLabel = in.readString();
         mPrimaryIntent = in.readInt() == 0 ? null : Intent.CREATOR.createFromParcel(in);
         mPrimaryOnClickListener = null;  // not parcelable
diff --git a/core/java/android/view/textclassifier/logging/DefaultLogger.java b/core/java/android/view/textclassifier/logging/DefaultLogger.java
index 03a6d3a..f510879 100644
--- a/core/java/android/view/textclassifier/logging/DefaultLogger.java
+++ b/core/java/android/view/textclassifier/logging/DefaultLogger.java
@@ -80,7 +80,7 @@
         Preconditions.checkNotNull(event);
         final LogMaker log = new LogMaker(MetricsEvent.TEXT_SELECTION_SESSION)
                 .setType(getLogType(event))
-                .setSubtype(MetricsEvent.TEXT_SELECTION_INVOCATION_MANUAL)
+                .setSubtype(getLogSubType(event))
                 .setPackageName(event.getPackageName())
                 .addTaggedData(START_EVENT_DELTA, event.getDurationSinceSessionStart())
                 .addTaggedData(PREV_EVENT_DELTA, event.getDurationSincePreviousEvent())
@@ -137,6 +137,17 @@
         }
     }
 
+    private static int getLogSubType(SelectionEvent event) {
+        switch (event.getInvocationMethod()) {
+            case SelectionEvent.INVOCATION_MANUAL:
+                return MetricsEvent.TEXT_SELECTION_INVOCATION_MANUAL;
+            case SelectionEvent.INVOCATION_LINK:
+                return MetricsEvent.TEXT_SELECTION_INVOCATION_LINK;
+            default:
+                return MetricsEvent.TEXT_SELECTION_INVOCATION_UNKNOWN;
+        }
+    }
+
     private static String getLogTypeString(int logType) {
         switch (logType) {
             case MetricsEvent.ACTION_TEXT_SELECTION_OVERTYPE:
@@ -176,6 +187,17 @@
         }
     }
 
+    private static String getLogSubTypeString(int logSubType) {
+        switch (logSubType) {
+            case MetricsEvent.TEXT_SELECTION_INVOCATION_MANUAL:
+                return "MANUAL";
+            case MetricsEvent.TEXT_SELECTION_INVOCATION_LINK:
+                return "LINK";
+            default:
+                return UNKNOWN;
+        }
+    }
+
     private static void debugLog(LogMaker log) {
         if (!DEBUG_LOG_ENABLED) return;
 
@@ -193,6 +215,7 @@
         final String model = Objects.toString(log.getTaggedData(MODEL_NAME), UNKNOWN);
         final String entity = Objects.toString(log.getTaggedData(ENTITY_TYPE), UNKNOWN);
         final String type = getLogTypeString(log.getType());
+        final String subType = getLogSubTypeString(log.getSubtype());
         final int smartStart = Integer.parseInt(
                 Objects.toString(log.getTaggedData(SMART_START), ZERO));
         final int smartEnd = Integer.parseInt(
@@ -202,8 +225,9 @@
         final int eventEnd = Integer.parseInt(
                 Objects.toString(log.getTaggedData(EVENT_END), ZERO));
 
-        Log.d(LOG_TAG, String.format("%2d: %s/%s, range=%d,%d - smart_range=%d,%d (%s/%s)",
-                index, type, entity, eventStart, eventEnd, smartStart, smartEnd, widget, model));
+        Log.d(LOG_TAG, String.format("%2d: %s/%s/%s, range=%d,%d - smart_range=%d,%d (%s/%s)",
+                index, type, subType, entity, eventStart, eventEnd, smartStart, smartEnd, widget,
+                model));
     }
 
     /**
diff --git a/core/java/android/view/textclassifier/logging/Logger.java b/core/java/android/view/textclassifier/logging/Logger.java
index 40e4d8c..4448b2b 100644
--- a/core/java/android/view/textclassifier/logging/Logger.java
+++ b/core/java/android/view/textclassifier/logging/Logger.java
@@ -71,6 +71,7 @@
     public static final String WIDGET_CUSTOM_UNSELECTABLE_TEXTVIEW = "nosel-customview";
     public static final String WIDGET_UNKNOWN = "unknown";
 
+    private @SelectionEvent.InvocationMethod int mInvocationMethod;
     private SelectionEvent mPrevEvent;
     private SelectionEvent mSmartEvent;
     private SelectionEvent mStartEvent;
@@ -124,16 +125,19 @@
     /**
      * Logs a "selection started" event.
      *
+     * @param invocationMethod  the way the selection was triggered
      * @param start  the token index of the selected token
      */
-    public final void logSelectionStartedEvent(int start) {
+    public final void logSelectionStartedEvent(
+            @SelectionEvent.InvocationMethod int invocationMethod, int start) {
         if (mConfig == null) {
             return;
         }
 
+        mInvocationMethod = invocationMethod;
         logEvent(new SelectionEvent(
                 start, start + 1, SelectionEvent.EVENT_SELECTION_STARTED,
-                TextClassifier.TYPE_UNKNOWN, NO_SIGNATURE, mConfig));
+                TextClassifier.TYPE_UNKNOWN, mInvocationMethod, NO_SIGNATURE, mConfig));
     }
 
     /**
@@ -152,7 +156,7 @@
 
         logEvent(new SelectionEvent(
                 start, end, SelectionEvent.EVENT_SELECTION_MODIFIED,
-                TextClassifier.TYPE_UNKNOWN, NO_SIGNATURE, mConfig));
+                TextClassifier.TYPE_UNKNOWN, mInvocationMethod, NO_SIGNATURE, mConfig));
     }
 
     /**
@@ -179,7 +183,7 @@
         final String signature = classification.getSignature();
         logEvent(new SelectionEvent(
                 start, end, SelectionEvent.EVENT_SELECTION_MODIFIED,
-                entityType, signature, mConfig));
+                entityType, mInvocationMethod, signature, mConfig));
     }
 
     /**
@@ -213,7 +217,8 @@
                 ? selection.getEntity(0)
                 : TextClassifier.TYPE_UNKNOWN;
         final String signature = selection.getSignature();
-        logEvent(new SelectionEvent(start, end, eventType, entityType, signature, mConfig));
+        logEvent(new SelectionEvent(start, end, eventType, entityType, mInvocationMethod, signature,
+                mConfig));
     }
 
     /**
@@ -234,7 +239,8 @@
         }
 
         logEvent(new SelectionEvent(
-                start, end, actionType, TextClassifier.TYPE_UNKNOWN, NO_SIGNATURE, mConfig));
+                start, end, actionType, TextClassifier.TYPE_UNKNOWN, mInvocationMethod,
+                NO_SIGNATURE, mConfig));
     }
 
     /**
@@ -265,7 +271,8 @@
                 ? classification.getEntity(0)
                 : TextClassifier.TYPE_UNKNOWN;
         final String signature = classification.getSignature();
-        logEvent(new SelectionEvent(start, end, actionType, entityType, signature, mConfig));
+        logEvent(new SelectionEvent(start, end, actionType, entityType, mInvocationMethod,
+                signature, mConfig));
     }
 
     private void logEvent(@NonNull SelectionEvent event) {
diff --git a/core/java/android/view/textclassifier/logging/SelectionEvent.java b/core/java/android/view/textclassifier/logging/SelectionEvent.java
index f40b655..a8de308 100644
--- a/core/java/android/view/textclassifier/logging/SelectionEvent.java
+++ b/core/java/android/view/textclassifier/logging/SelectionEvent.java
@@ -98,6 +98,16 @@
     /** Something else other than User or the default TextClassifier triggered a selection. */
     public static final int EVENT_AUTO_SELECTION = 5;
 
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({INVOCATION_MANUAL, INVOCATION_LINK})
+    public @interface InvocationMethod {}
+
+    /** Selection was invoked by the user long pressing, double tapping, or dragging to select. */
+    public static final int INVOCATION_MANUAL = 1;
+    /** Selection was invoked by the user tapping on a link. */
+    public static final int INVOCATION_LINK = 2;
+
     private final int mAbsoluteStart;
     private final int mAbsoluteEnd;
     private final @EventType int mEventType;
@@ -105,6 +115,7 @@
     @Nullable private final String mWidgetVersion;
     private final String mPackageName;
     private final String mWidgetType;
+    private final @InvocationMethod int mInvocationMethod;
 
     // These fields should only be set by creator of a SelectionEvent.
     private String mSignature;
@@ -121,7 +132,7 @@
     SelectionEvent(
             int start, int end,
             @EventType int eventType, @EntityType String entityType,
-            String signature, Logger.Config config) {
+            @InvocationMethod int invocationMethod, String signature, Logger.Config config) {
         Preconditions.checkArgument(end >= start, "end cannot be less than start");
         mAbsoluteStart = start;
         mAbsoluteEnd = end;
@@ -132,6 +143,7 @@
         mWidgetVersion = config.getWidgetVersion();
         mPackageName = Preconditions.checkNotNull(config.getPackageName());
         mWidgetType = Preconditions.checkNotNull(config.getWidgetType());
+        mInvocationMethod = invocationMethod;
     }
 
     int getAbsoluteStart() {
@@ -180,6 +192,13 @@
     }
 
     /**
+     * Returns the way the selection mode was invoked.
+     */
+    public @InvocationMethod int getInvocationMethod() {
+        return mInvocationMethod;
+    }
+
+    /**
      * Returns the signature of the text classifier result associated with this event.
      */
     public String getSignature() {
diff --git a/core/java/android/widget/SelectionActionModeHelper.java b/core/java/android/widget/SelectionActionModeHelper.java
index e7a4c02..6ab09d6 100644
--- a/core/java/android/widget/SelectionActionModeHelper.java
+++ b/core/java/android/widget/SelectionActionModeHelper.java
@@ -111,7 +111,8 @@
         mSelectionTracker.onOriginalSelection(
                 getText(mTextView),
                 mTextView.getSelectionStart(),
-                mTextView.getSelectionEnd());
+                mTextView.getSelectionEnd(),
+                false /*isLink*/);
         cancelAsyncTask();
         if (skipTextClassification()) {
             startSelectionActionMode(null);
@@ -134,7 +135,11 @@
      * Starts Link ActionMode.
      */
     public void startLinkActionModeAsync(TextLinks.TextLink textLink) {
-        //TODO: tracking/logging
+        mSelectionTracker.onOriginalSelection(
+                getText(mTextView),
+                mTextView.getSelectionStart(),
+                mTextView.getSelectionEnd(),
+                true /*isLink*/);
         cancelAsyncTask();
         if (skipTextClassification()) {
             startLinkActionMode(null);
@@ -487,7 +492,8 @@
         /**
          * Called when the original selection happens, before smart selection is triggered.
          */
-        public void onOriginalSelection(CharSequence text, int selectionStart, int selectionEnd) {
+        public void onOriginalSelection(
+                CharSequence text, int selectionStart, int selectionEnd, boolean isLink) {
             // If we abandoned a selection and created a new one very shortly after, we may still
             // have a pending request to log ABANDON, which we flush here.
             mDelayedLogAbandon.flush();
@@ -496,7 +502,8 @@
             mOriginalEnd = mSelectionEnd = selectionEnd;
             mAllowReset = false;
             maybeInvalidateLogger();
-            mLogger.logSelectionStarted(text, selectionStart);
+            mLogger.logSelectionStarted(text, selectionStart,
+                    isLink ? SelectionEvent.INVOCATION_LINK : SelectionEvent.INVOCATION_MANUAL);
         }
 
         /**
@@ -679,7 +686,9 @@
             return Logger.WIDGET_UNSELECTABLE_TEXTVIEW;
         }
 
-        public void logSelectionStarted(CharSequence text, int index) {
+        public void logSelectionStarted(
+                CharSequence text, int index,
+                @SelectionEvent.InvocationMethod int invocationMethod) {
             try {
                 Preconditions.checkNotNull(text);
                 Preconditions.checkArgumentInRange(index, 0, text.length(), "index");
@@ -688,7 +697,7 @@
                 }
                 mTokenIterator.setText(mText);
                 mStartIndex = index;
-                mLogger.logSelectionStartedEvent(0);
+                mLogger.logSelectionStartedEvent(invocationMethod, 0);
             } catch (Exception e) {
                 // Avoid crashes due to logging.
                 Log.d(LOG_TAG, e.getMessage());
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 5710db3..f6e771a 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -80,8 +80,8 @@
 import android.text.InputFilter;
 import android.text.InputType;
 import android.text.Layout;
-import android.text.MeasuredText;
 import android.text.ParcelableSpan;
+import android.text.PrecomputedText;
 import android.text.Selection;
 import android.text.SpanWatcher;
 import android.text.Spannable;
@@ -637,6 +637,7 @@
     private CharSequence mText;
     private CharSequence mTransformed;
     private BufferType mBufferType = BufferType.NORMAL;
+    private PrecomputedText mPrecomputed;
 
     private CharSequence mHint;
     private Layout mHintLayout;
@@ -4085,6 +4086,80 @@
     }
 
     /**
+     * Gets the parameters for text layout precomputation, for use with {@link PrecomputedText}
+     *
+     * @return A current {@link PrecomputedText.Params}
+     */
+    public @NonNull PrecomputedText.Params getTextMetricsParams() {
+        return new PrecomputedText.Params(new TextPaint(mTextPaint), getTextDirectionHeuristic(),
+                mBreakStrategy, mHyphenationFrequency);
+    }
+
+    /**
+     * Apply the text layout parameter.
+     */
+    public void setTextMetricsParams(@NonNull PrecomputedText.Params params) {
+        mTextPaint.set(params.getTextPaint());
+        mTextDir = params.getTextDirection();
+        mBreakStrategy = params.getBreakStrategy();
+        mHyphenationFrequency = params.getHyphenationFrequency();
+        if (mLayout != null) {
+            nullLayouts();
+            requestLayout();
+            invalidate();
+        }
+    }
+
+    /**
+     * Sets the precomputed text.
+     *
+     * If the parameters for the precomputed text is different from current text view parameters,
+     * apply the parameteres to the text view too.
+     *
+     * @param text A precomputed text.
+     */
+    public void setPrecomputedTextAndParams(@NonNull PrecomputedText text) {
+        Preconditions.checkNotNull(text);
+        final PrecomputedText.Params params = text.getParams();
+        if (!params.sameTextMetrics(getTextMetricsParams())) {
+            setTextMetricsParams(params);
+        }
+        setText(text.getText());
+        if (mTransformed != text.getText()) {
+            // setText modified given text for some reasons, selection, transformation, etc.
+            // Can't use computed result.
+            return;
+        } else {
+            mPrecomputed = text;
+        }
+    }
+
+    /**
+     * Sets the precomputed text.
+     *
+     * If the parameters for the precomputed text is different from current text view parameters,
+     * throws {@link IllegalArgumentException}.
+     *
+     * @param text A precomputed text.
+     */
+    public void setPrecomputedTextOrThrow(@NonNull PrecomputedText text) {
+        Preconditions.checkNotNull(text);
+        final PrecomputedText.Params params = text.getParams();
+        if (!params.sameTextMetrics(getTextMetricsParams())) {
+            throw new IllegalArgumentException(
+                "The precomputed configuration is different from this TextView.");
+        }
+        setText(text.getText());
+        if (mTransformed != text.getText()) {
+            // setText modified given text for some reasons, selection, transformation, etc.
+            // Can't use computed result.
+            // TODO: Do we throw an exception here too?
+        } else {
+            mPrecomputed = text;
+        }
+    }
+
+    /**
      * Set justification mode. The default value is {@link Layout#JUSTIFICATION_MODE_NONE}. If the
      * last line is too short for justification, the last line will be displayed with the
      * alignment set by {@link android.view.View#setTextAlignment}.
@@ -5519,6 +5594,7 @@
 
     private void setText(CharSequence text, BufferType type,
                          boolean notifyBefore, int oldlen) {
+        mPrecomputed = null;
         mTextSetFromXmlOrResourceId = false;
         if (text == null) {
             text = "";
@@ -5577,7 +5653,7 @@
             if (imm != null) imm.restartInput(this);
         } else if (type == BufferType.SPANNABLE || mMovement != null) {
             text = mSpannableFactory.newSpannable(text);
-        } else if (!(text instanceof MeasuredText || text instanceof CharWrapper)) {
+        } else if (!(text instanceof CharWrapper)) {
             text = TextUtils.stringOrSpannedString(text);
         }
 
@@ -8244,7 +8320,8 @@
             result = builder.build();
         } else {
             if (boring == UNKNOWN_BORING) {
-                boring = BoringLayout.isBoring(mTransformed, mTextPaint, mTextDir, mBoring);
+                boring = BoringLayout.isBoring(mTransformed, mPrecomputed, mTextPaint, mTextDir,
+                        mBoring);
                 if (boring != null) {
                     mBoring = boring;
                 }
@@ -8282,9 +8359,15 @@
             }
         }
         if (result == null) {
-            StaticLayout.Builder builder = StaticLayout.Builder.obtain(mTransformed,
-                    0, mTransformed.length(), mTextPaint, wantWidth)
-                    .setAlignment(alignment)
+            StaticLayout.Builder builder;
+            if (mPrecomputed != null) {
+                builder = StaticLayout.Builder.obtain(mPrecomputed, 0,
+                        mPrecomputed.getText().length(), mTextPaint, wantWidth);
+            } else {
+                builder = StaticLayout.Builder.obtain(mTransformed, 0, mTransformed.length(),
+                        mTextPaint, wantWidth);
+            }
+            builder.setAlignment(alignment)
                     .setTextDirection(mTextDir)
                     .setLineSpacing(mSpacingAdd, mSpacingMult)
                     .setIncludePad(mIncludePad)
@@ -8411,7 +8494,8 @@
             }
 
             if (des < 0) {
-                boring = BoringLayout.isBoring(mTransformed, mTextPaint, mTextDir, mBoring);
+                boring = BoringLayout.isBoring(mTransformed, mPrecomputed, mTextPaint, mTextDir,
+                        mBoring);
                 if (boring != null) {
                     mBoring = boring;
                 }
@@ -11696,6 +11780,9 @@
     }
 
     /**
+     * Returns the current {@link TextDirectionHeuristic}
+     *
+     * @return A {@link TextDirectionHeuristic}.
      * @hide
      */
     protected TextDirectionHeuristic getTextDirectionHeuristic() {
diff --git a/core/java/com/android/internal/app/ResolverListController.java b/core/java/com/android/internal/app/ResolverListController.java
index 6bd6930..61aeca6 100644
--- a/core/java/com/android/internal/app/ResolverListController.java
+++ b/core/java/com/android/internal/app/ResolverListController.java
@@ -56,9 +56,6 @@
     private static final String TAG = "ResolverListController";
     private static final boolean DEBUG = false;
 
-    Object mLock = new Object();
-
-    @GuardedBy("mLock")
     private ResolverComparator mResolverComparator;
     private boolean isComputed = false;
 
@@ -73,10 +70,8 @@
         mLaunchedFromUid = launchedFromUid;
         mTargetIntent = targetIntent;
         mReferrerPackage = referrerPackage;
-        synchronized (mLock) {
-            mResolverComparator =
-                    new ResolverComparator(mContext, mTargetIntent, mReferrerPackage, null);
-        }
+        mResolverComparator =
+                new ResolverComparator(mContext, mTargetIntent, mReferrerPackage, null);
     }
 
     @VisibleForTesting
@@ -244,29 +239,27 @@
     @VisibleForTesting
     @WorkerThread
     public void sort(List<ResolverActivity.ResolvedComponentInfo> inputList) {
-        synchronized (mLock) {
-            if (mResolverComparator == null) {
-                Log.d(TAG, "Comparator has already been destroyed; skipped.");
-                return;
+        if (mResolverComparator == null) {
+            Log.d(TAG, "Comparator has already been destroyed; skipped.");
+            return;
+        }
+        try {
+            long beforeRank = System.currentTimeMillis();
+            if (!isComputed) {
+                final CountDownLatch finishComputeSignal = new CountDownLatch(1);
+                ComputeCallback callback = new ComputeCallback(finishComputeSignal);
+                mResolverComparator.setCallBack(callback);
+                mResolverComparator.compute(inputList);
+                finishComputeSignal.await();
+                isComputed = true;
             }
-            final CountDownLatch finishComputeSignal = new CountDownLatch(1);
-            ComputeCallback callback = new ComputeCallback(finishComputeSignal);
-            mResolverComparator.setCallBack(callback);
-            try {
-                long beforeRank = System.currentTimeMillis();
-                if (!isComputed) {
-                    mResolverComparator.compute(inputList);
-                    finishComputeSignal.await();
-                    isComputed = true;
-                }
-                Collections.sort(inputList, mResolverComparator);
-                long afterRank = System.currentTimeMillis();
-                if (DEBUG) {
-                    Log.d(TAG, "Time Cost: " + Long.toString(afterRank - beforeRank));
-                }
-            } catch (InterruptedException e) {
-                Log.e(TAG, "Compute & Sort was interrupted: " + e);
+            Collections.sort(inputList, mResolverComparator);
+            long afterRank = System.currentTimeMillis();
+            if (DEBUG) {
+                Log.d(TAG, "Time Cost: " + Long.toString(afterRank - beforeRank));
             }
+        } catch (InterruptedException e) {
+            Log.e(TAG, "Compute & Sort was interrupted: " + e);
         }
     }
 
@@ -287,36 +280,18 @@
 
     @VisibleForTesting
     public float getScore(ResolverActivity.DisplayResolveInfo target) {
-        synchronized (mLock) {
-            if (mResolverComparator == null) {
-                return 0.0f;
-            }
-            return mResolverComparator.getScore(target.getResolvedComponentName());
-        }
+        return mResolverComparator.getScore(target.getResolvedComponentName());
     }
 
     public void updateModel(ComponentName componentName) {
-        synchronized (mLock) {
-            if (mResolverComparator != null) {
-                mResolverComparator.updateModel(componentName);
-            }
-        }
+        mResolverComparator.updateModel(componentName);
     }
 
     public void updateChooserCounts(String packageName, int userId, String action) {
-        synchronized (mLock) {
-            if (mResolverComparator != null) {
-                mResolverComparator.updateChooserCounts(packageName, userId, action);
-            }
-        }
+        mResolverComparator.updateChooserCounts(packageName, userId, action);
     }
 
     public void destroy() {
-        synchronized (mLock) {
-            if (mResolverComparator != null) {
-                mResolverComparator.destroy();
-            }
-            mResolverComparator = null;
-        }
+        mResolverComparator.destroy();
     }
 }
diff --git a/core/java/com/android/internal/os/KernelSingleUidTimeReader.java b/core/java/com/android/internal/os/KernelSingleUidTimeReader.java
index ebeb24c4..4283917 100644
--- a/core/java/com/android/internal/os/KernelSingleUidTimeReader.java
+++ b/core/java/com/android/internal/os/KernelSingleUidTimeReader.java
@@ -16,6 +16,7 @@
 package com.android.internal.os;
 
 import static com.android.internal.annotations.VisibleForTesting.Visibility.PACKAGE;
+import static com.android.internal.os.KernelUidCpuFreqTimeReader.UID_TIMES_PROC_FILE;
 
 import android.annotation.NonNull;
 import android.util.Slog;
@@ -54,6 +55,12 @@
     private boolean mSingleUidCpuTimesAvailable = true;
     @GuardedBy("this")
     private boolean mHasStaleData;
+    // We use the freq count obtained from /proc/uid_time_in_state to decide how many longs
+    // to read from each /proc/uid/<uid>/time_in_state. On the first read, verify if this is
+    // correct and if not, set {@link #mSingleUidCpuTimesAvailable} to false. This flag will
+    // indicate whether we checked for validity or not.
+    @GuardedBy("this")
+    private boolean mCpuFreqsCountVerified;
 
     private final Injector mInjector;
 
@@ -82,15 +89,15 @@
             final String procFile = new StringBuilder(PROC_FILE_DIR)
                     .append(uid)
                     .append(PROC_FILE_NAME).toString();
-            final long[] cpuTimesMs = new long[mCpuFreqsCount];
+            final long[] cpuTimesMs;
             try {
                 final byte[] data = mInjector.readData(procFile);
+                if (!mCpuFreqsCountVerified) {
+                    verifyCpuFreqsCount(data.length, procFile);
+                }
                 final ByteBuffer buffer = ByteBuffer.wrap(data);
                 buffer.order(ByteOrder.nativeOrder());
-                for (int i = 0; i < mCpuFreqsCount; ++i) {
-                    // Times read will be in units of 10ms
-                    cpuTimesMs[i] = buffer.getLong() * 10;
-                }
+                cpuTimesMs = readCpuTimesFromByteBuffer(buffer);
             } catch (Exception e) {
                 if (++mReadErrorCounter >= TOTAL_READ_ERROR_COUNT) {
                     mSingleUidCpuTimesAvailable = false;
@@ -103,6 +110,27 @@
         }
     }
 
+    private void verifyCpuFreqsCount(int numBytes, String procFile) {
+        final int actualCount = (numBytes / Long.BYTES);
+        if (mCpuFreqsCount != actualCount) {
+            mSingleUidCpuTimesAvailable = false;
+            throw new IllegalStateException("Freq count didn't match,"
+                    + "count from " + UID_TIMES_PROC_FILE + "=" + mCpuFreqsCount + ", but"
+                    + "count from " + procFile + "=" + actualCount);
+        }
+        mCpuFreqsCountVerified = true;
+    }
+
+    private long[] readCpuTimesFromByteBuffer(ByteBuffer buffer) {
+        final long[] cpuTimesMs;
+        cpuTimesMs = new long[mCpuFreqsCount];
+        for (int i = 0; i < mCpuFreqsCount; ++i) {
+            // Times read will be in units of 10ms
+            cpuTimesMs[i] = buffer.getLong() * 10;
+        }
+        return cpuTimesMs;
+    }
+
     /**
      * Compute and return cpu times delta of an uid using previously read cpu times and
      * {@param latestCpuTimesMs}.
diff --git a/core/java/com/android/internal/os/KernelUidCpuFreqTimeReader.java b/core/java/com/android/internal/os/KernelUidCpuFreqTimeReader.java
index b8982cc..d97538c 100644
--- a/core/java/com/android/internal/os/KernelUidCpuFreqTimeReader.java
+++ b/core/java/com/android/internal/os/KernelUidCpuFreqTimeReader.java
@@ -49,7 +49,7 @@
 public class KernelUidCpuFreqTimeReader {
     private static final boolean DEBUG = false;
     private static final String TAG = "KernelUidCpuFreqTimeReader";
-    private static final String UID_TIMES_PROC_FILE = "/proc/uid_time_in_state";
+    static final String UID_TIMES_PROC_FILE = "/proc/uid_time_in_state";
 
     public interface Callback {
         void onUidCpuFreqTime(int uid, long[] cpuFreqTimeMs);
diff --git a/core/java/com/android/internal/os/KernelUidCpuTimeReader.java b/core/java/com/android/internal/os/KernelUidCpuTimeReader.java
index 65615c0..444049e 100644
--- a/core/java/com/android/internal/os/KernelUidCpuTimeReader.java
+++ b/core/java/com/android/internal/os/KernelUidCpuTimeReader.java
@@ -78,10 +78,11 @@
                 final long userTimeUs = Long.parseLong(splitter.next(), 10);
                 final long systemTimeUs = Long.parseLong(splitter.next(), 10);
 
+                boolean notifyCallback = false;
+                long userTimeDeltaUs = userTimeUs;
+                long systemTimeDeltaUs = systemTimeUs;
                 // Only report if there is a callback and if this is not the first read.
                 if (callback != null && mLastTimeReadUs != 0) {
-                    long userTimeDeltaUs = userTimeUs;
-                    long systemTimeDeltaUs = systemTimeUs;
                     int index = mLastUserTimeUs.indexOfKey(uid);
                     if (index >= 0) {
                         userTimeDeltaUs -= mLastUserTimeUs.valueAt(index);
@@ -114,12 +115,13 @@
                         }
                     }
 
-                    if (userTimeDeltaUs != 0 || systemTimeDeltaUs != 0) {
-                        callback.onUidCpuTime(uid, userTimeDeltaUs, systemTimeDeltaUs);
-                    }
+                    notifyCallback = (userTimeDeltaUs != 0 || systemTimeDeltaUs != 0);
                 }
                 mLastUserTimeUs.put(uid, userTimeUs);
                 mLastSystemTimeUs.put(uid, systemTimeUs);
+                if (notifyCallback) {
+                    callback.onUidCpuTime(uid, userTimeDeltaUs, systemTimeDeltaUs);
+                }
             }
         } catch (IOException e) {
             Slog.e(TAG, "Failed to read uid_cputime: " + e.getMessage());
diff --git a/core/java/com/android/internal/os/RuntimeInit.java b/core/java/com/android/internal/os/RuntimeInit.java
index 66475e4..895be08 100644
--- a/core/java/com/android/internal/os/RuntimeInit.java
+++ b/core/java/com/android/internal/os/RuntimeInit.java
@@ -71,10 +71,11 @@
         public void uncaughtException(Thread t, Throwable e) {
             // Don't re-enter if KillApplicationHandler has already run
             if (mCrashing) return;
-            if (mApplicationObject == null) {
-                // The "FATAL EXCEPTION" string is still used on Android even though
-                // apps can set a custom UncaughtExceptionHandler that renders uncaught
-                // exceptions non-fatal.
+
+            // mApplicationObject is null for non-zygote java programs (e.g. "am")
+            // There are also apps running with the system UID. We don't want the
+            // first clause in either of these two cases, only for system_server.
+            if (mApplicationObject == null && (Process.SYSTEM_UID == Process.myUid())) {
                 Clog_e(TAG, "*** FATAL EXCEPTION IN SYSTEM PROCESS: " + t.getName(), e);
             } else {
                 StringBuilder message = new StringBuilder();
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index 78a3e13..33f80ce 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -110,8 +110,8 @@
         "android_util_AssetManager.cpp",
         "android_util_Binder.cpp",
         "android_util_EventLog.cpp",
-        "android_util_Log.cpp",
         "android_util_MemoryIntArray.cpp",
+        "android_util_Log.cpp",
         "android_util_PathParser.cpp",
         "android_util_Process.cpp",
         "android_util_StringBlock.cpp",
@@ -191,7 +191,6 @@
         "android_backup_FileBackupHelperBase.cpp",
         "android_backup_BackupHelperDispatcher.cpp",
         "android_app_backup_FullBackup.cpp",
-        "android_content_res_ApkAssets.cpp",
         "android_content_res_ObbScanner.cpp",
         "android_content_res_Configuration.cpp",
         "android_animation_PropertyValuesHolder.cpp",
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 4a032c4..d202173 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -123,7 +123,6 @@
 extern int register_android_util_PathParser(JNIEnv* env);
 extern int register_android_content_StringBlock(JNIEnv* env);
 extern int register_android_content_XmlBlock(JNIEnv* env);
-extern int register_android_content_res_ApkAssets(JNIEnv* env);
 extern int register_android_graphics_Canvas(JNIEnv* env);
 extern int register_android_graphics_CanvasProperty(JNIEnv* env);
 extern int register_android_graphics_ColorFilter(JNIEnv* env);
@@ -1347,7 +1346,6 @@
     REG_JNI(register_android_content_AssetManager),
     REG_JNI(register_android_content_StringBlock),
     REG_JNI(register_android_content_XmlBlock),
-    REG_JNI(register_android_content_res_ApkAssets),
     REG_JNI(register_android_text_AndroidCharacter),
     REG_JNI(register_android_text_Hyphenator),
     REG_JNI(register_android_text_MeasuredParagraph),
diff --git a/core/jni/android/graphics/FontFamily.cpp b/core/jni/android/graphics/FontFamily.cpp
index ed032c7..48aef4a 100644
--- a/core/jni/android/graphics/FontFamily.cpp
+++ b/core/jni/android/graphics/FontFamily.cpp
@@ -28,7 +28,7 @@
 #include <nativehelper/ScopedUtfChars.h>
 #include <android_runtime/AndroidRuntime.h>
 #include <android_runtime/android_util_AssetManager.h>
-#include <androidfw/AssetManager2.h>
+#include <androidfw/AssetManager.h>
 #include "Utils.h"
 #include "FontUtils.h"
 
@@ -205,8 +205,7 @@
     NPE_CHECK_RETURN_ZERO(env, jpath);
 
     NativeFamilyBuilder* builder = reinterpret_cast<NativeFamilyBuilder*>(builderPtr);
-
-    Guarded<AssetManager2>* mgr = AssetManagerForJavaObject(env, jassetMgr);
+    AssetManager* mgr = assetManagerForJavaObject(env, jassetMgr);
     if (NULL == mgr) {
         builder->axes.clear();
         return false;
@@ -218,33 +217,27 @@
         return false;
     }
 
-    std::unique_ptr<Asset> asset;
-    {
-      ScopedLock<AssetManager2> locked_mgr(*mgr);
-      if (isAsset) {
-          asset = locked_mgr->Open(str.c_str(), Asset::ACCESS_BUFFER);
-      } else if (cookie > 0) {
-          // Valid java cookies are 1-based, but AssetManager cookies are 0-based.
-          asset = locked_mgr->OpenNonAsset(str.c_str(), static_cast<ApkAssetsCookie>(cookie - 1),
-                  Asset::ACCESS_BUFFER);
-      } else {
-          asset = locked_mgr->OpenNonAsset(str.c_str(), Asset::ACCESS_BUFFER);
-      }
+    Asset* asset;
+    if (isAsset) {
+        asset = mgr->open(str.c_str(), Asset::ACCESS_BUFFER);
+    } else {
+        asset = cookie ? mgr->openNonAsset(static_cast<int32_t>(cookie), str.c_str(),
+                Asset::ACCESS_BUFFER) : mgr->openNonAsset(str.c_str(), Asset::ACCESS_BUFFER);
     }
 
-    if (nullptr == asset) {
+    if (NULL == asset) {
         builder->axes.clear();
         return false;
     }
 
     const void* buf = asset->getBuffer(false);
     if (NULL == buf) {
+        delete asset;
         builder->axes.clear();
         return false;
     }
 
-    sk_sp<SkData> data(SkData::MakeWithProc(buf, asset->getLength(), releaseAsset,
-            asset.release()));
+    sk_sp<SkData> data(SkData::MakeWithProc(buf, asset->getLength(), releaseAsset, asset));
     return addSkTypeface(builder, std::move(data), ttcIndex, weight, isItalic);
 }
 
diff --git a/core/jni/android/graphics/Paint.cpp b/core/jni/android/graphics/Paint.cpp
index 482d028..2c05d0b 100644
--- a/core/jni/android/graphics/Paint.cpp
+++ b/core/jni/android/graphics/Paint.cpp
@@ -1008,6 +1008,23 @@
         return paint->getLooper() && paint->getLooper()->asABlurShadow(nullptr);
     }
 
+    static jboolean equalsForTextMeasurement(jlong lPaint, jlong rPaint) {
+        if (lPaint == rPaint) {
+            return true;
+        }
+        Paint* leftPaint = reinterpret_cast<Paint*>(lPaint);
+        Paint* rightPaint = reinterpret_cast<Paint*>(rPaint);
+
+        const Typeface* leftTypeface = Typeface::resolveDefault(leftPaint->getAndroidTypeface());
+        const Typeface* rightTypeface = Typeface::resolveDefault(rightPaint->getAndroidTypeface());
+        minikin::MinikinPaint leftMinikinPaint
+                = MinikinUtils::prepareMinikinPaint(leftPaint, leftTypeface);
+        minikin::MinikinPaint rightMinikinPaint
+                = MinikinUtils::prepareMinikinPaint(rightPaint, rightTypeface);
+
+        return leftMinikinPaint == rightMinikinPaint;
+    }
+
 }; // namespace PaintGlue
 
 static const JNINativeMethod methods[] = {
@@ -1107,7 +1124,8 @@
     {"nGetStrikeThruPosition","(J)F", (void*) PaintGlue::getStrikeThruPosition},
     {"nGetStrikeThruThickness","(J)F", (void*) PaintGlue::getStrikeThruThickness},
     {"nSetShadowLayer", "(JFFFI)V", (void*)PaintGlue::setShadowLayer},
-    {"nHasShadowLayer", "(J)Z", (void*)PaintGlue::hasShadowLayer}
+    {"nHasShadowLayer", "(J)Z", (void*)PaintGlue::hasShadowLayer},
+    {"nEqualsForTextMeasurement", "(JJ)Z", (void*)PaintGlue::equalsForTextMeasurement},
 };
 
 int register_android_graphics_Paint(JNIEnv* env) {
diff --git a/core/jni/android_app_NativeActivity.cpp b/core/jni/android_app_NativeActivity.cpp
index 49a24a3..09e37e1 100644
--- a/core/jni/android_app_NativeActivity.cpp
+++ b/core/jni/android_app_NativeActivity.cpp
@@ -361,7 +361,7 @@
     code->sdkVersion = sdkVersion;
 
     code->javaAssetManager = env->NewGlobalRef(jAssetMgr);
-    code->assetManager = NdkAssetManagerForJavaObject(env, jAssetMgr);
+    code->assetManager = assetManagerForJavaObject(env, jAssetMgr);
 
     if (obbDir != NULL) {
         dirStr = env->GetStringUTFChars(obbDir, NULL);
diff --git a/core/jni/android_content_res_ApkAssets.cpp b/core/jni/android_content_res_ApkAssets.cpp
deleted file mode 100644
index c0f151b..0000000
--- a/core/jni/android_content_res_ApkAssets.cpp
+++ /dev/null
@@ -1,150 +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 "android-base/macros.h"
-#include "android-base/stringprintf.h"
-#include "android-base/unique_fd.h"
-#include "androidfw/ApkAssets.h"
-#include "utils/misc.h"
-
-#include "core_jni_helpers.h"
-#include "jni.h"
-#include "nativehelper/ScopedUtfChars.h"
-
-using ::android::base::unique_fd;
-
-namespace android {
-
-static jlong NativeLoad(JNIEnv* env, jclass /*clazz*/, jstring java_path, jboolean system,
-                        jboolean force_shared_lib, jboolean overlay) {
-  ScopedUtfChars path(env, java_path);
-  if (path.c_str() == nullptr) {
-    return 0;
-  }
-
-  std::unique_ptr<const ApkAssets> apk_assets;
-  if (overlay) {
-    apk_assets = ApkAssets::LoadOverlay(path.c_str(), system);
-  } else if (force_shared_lib) {
-    apk_assets = ApkAssets::LoadAsSharedLibrary(path.c_str(), system);
-  } else {
-    apk_assets = ApkAssets::Load(path.c_str(), system);
-  }
-
-  if (apk_assets == nullptr) {
-    std::string error_msg = base::StringPrintf("Failed to load asset path %s", path.c_str());
-    jniThrowException(env, "java/io/IOException", error_msg.c_str());
-    return 0;
-  }
-  return reinterpret_cast<jlong>(apk_assets.release());
-}
-
-static jlong NativeLoadFromFd(JNIEnv* env, jclass /*clazz*/, jobject file_descriptor,
-                              jstring friendly_name, jboolean system, jboolean force_shared_lib) {
-  ScopedUtfChars friendly_name_utf8(env, friendly_name);
-  if (friendly_name_utf8.c_str() == nullptr) {
-    return 0;
-  }
-
-  int fd = jniGetFDFromFileDescriptor(env, file_descriptor);
-  if (fd < 0) {
-    jniThrowException(env, "java/lang/IllegalArgumentException", "Bad FileDescriptor");
-    return 0;
-  }
-
-  unique_fd dup_fd(::dup(fd));
-  if (dup_fd < 0) {
-    jniThrowIOException(env, errno);
-    return 0;
-  }
-
-  std::unique_ptr<const ApkAssets> apk_assets = ApkAssets::LoadFromFd(std::move(dup_fd),
-                                                                      friendly_name_utf8.c_str(),
-                                                                      system, force_shared_lib);
-  if (apk_assets == nullptr) {
-    std::string error_msg = base::StringPrintf("Failed to load asset path %s from fd %d",
-                                               friendly_name_utf8.c_str(), dup_fd.get());
-    jniThrowException(env, "java/io/IOException", error_msg.c_str());
-    return 0;
-  }
-  return reinterpret_cast<jlong>(apk_assets.release());
-}
-
-static void NativeDestroy(JNIEnv* /*env*/, jclass /*clazz*/, jlong ptr) {
-  delete reinterpret_cast<ApkAssets*>(ptr);
-}
-
-static jstring NativeGetAssetPath(JNIEnv* env, jclass /*clazz*/, jlong ptr) {
-  const ApkAssets* apk_assets = reinterpret_cast<const ApkAssets*>(ptr);
-  return env->NewStringUTF(apk_assets->GetPath().c_str());
-}
-
-static jlong NativeGetStringBlock(JNIEnv* /*env*/, jclass /*clazz*/, jlong ptr) {
-  const ApkAssets* apk_assets = reinterpret_cast<const ApkAssets*>(ptr);
-  return reinterpret_cast<jlong>(apk_assets->GetLoadedArsc()->GetStringPool());
-}
-
-static jboolean NativeIsUpToDate(JNIEnv* /*env*/, jclass /*clazz*/, jlong ptr) {
-  const ApkAssets* apk_assets = reinterpret_cast<const ApkAssets*>(ptr);
-  (void)apk_assets;
-  return JNI_TRUE;
-}
-
-static jlong NativeOpenXml(JNIEnv* env, jclass /*clazz*/, jlong ptr, jstring file_name) {
-  ScopedUtfChars path_utf8(env, file_name);
-  if (path_utf8.c_str() == nullptr) {
-    return 0;
-  }
-
-  const ApkAssets* apk_assets = reinterpret_cast<const ApkAssets*>(ptr);
-  std::unique_ptr<Asset> asset = apk_assets->Open(path_utf8.c_str(),
-                                                  Asset::AccessMode::ACCESS_RANDOM);
-  if (asset == nullptr) {
-    jniThrowException(env, "java/io/FileNotFoundException", path_utf8.c_str());
-    return 0;
-  }
-
-  // DynamicRefTable is only needed when looking up resource references. Opening an XML file
-  // directly from an ApkAssets has no notion of proper resource references.
-  std::unique_ptr<ResXMLTree> xml_tree = util::make_unique<ResXMLTree>(nullptr /*dynamicRefTable*/);
-  status_t err = xml_tree->setTo(asset->getBuffer(true), asset->getLength(), true);
-  asset.reset();
-
-  if (err != NO_ERROR) {
-    jniThrowException(env, "java/io/FileNotFoundException", "Corrupt XML binary file");
-    return 0;
-  }
-  return reinterpret_cast<jlong>(xml_tree.release());
-}
-
-// JNI registration.
-static const JNINativeMethod gApkAssetsMethods[] = {
-    {"nativeLoad", "(Ljava/lang/String;ZZZ)J", (void*)NativeLoad},
-    {"nativeLoadFromFd", "(Ljava/io/FileDescriptor;Ljava/lang/String;ZZ)J",
-        (void*)NativeLoadFromFd},
-    {"nativeDestroy", "(J)V", (void*)NativeDestroy},
-    {"nativeGetAssetPath", "(J)Ljava/lang/String;", (void*)NativeGetAssetPath},
-    {"nativeGetStringBlock", "(J)J", (void*)NativeGetStringBlock},
-    {"nativeIsUpToDate", "(J)Z", (void*)NativeIsUpToDate},
-    {"nativeOpenXml", "(JLjava/lang/String;)J", (void*)NativeOpenXml},
-};
-
-int register_android_content_res_ApkAssets(JNIEnv* env) {
-  return RegisterMethodsOrDie(env, "android/content/res/ApkAssets", gApkAssetsMethods,
-                              arraysize(gApkAssetsMethods));
-}
-
-}  // namespace android
diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp
index 2334e03..683b4c4 100644
--- a/core/jni/android_util_AssetManager.cpp
+++ b/core/jni/android_util_AssetManager.cpp
@@ -1,1433 +1,1851 @@
-/*
- * Copyright 2006, 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.
- */
+/* //device/libs/android_runtime/android_util_AssetManager.cpp
+**
+** Copyright 2006, 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.
+*/
 
 #define LOG_TAG "asset"
 
+#include <android_runtime/android_util_AssetManager.h>
+
 #include <inttypes.h>
 #include <linux/capability.h>
 #include <stdio.h>
-#include <sys/stat.h>
-#include <sys/system_properties.h>
 #include <sys/types.h>
 #include <sys/wait.h>
+#include <sys/stat.h>
+#include <sys/system_properties.h>
 
 #include <private/android_filesystem_config.h> // for AID_SYSTEM
 
-#include "android-base/logging.h"
-#include "android-base/properties.h"
-#include "android-base/stringprintf.h"
-#include "android_runtime/android_util_AssetManager.h"
-#include "android_runtime/AndroidRuntime.h"
-#include "android_util_Binder.h"
 #include "androidfw/Asset.h"
 #include "androidfw/AssetManager.h"
-#include "androidfw/AssetManager2.h"
 #include "androidfw/AttributeResolution.h"
-#include "androidfw/MutexGuard.h"
 #include "androidfw/ResourceTypes.h"
+#include "android_runtime/AndroidRuntime.h"
+#include "android_util_Binder.h"
 #include "core_jni_helpers.h"
 #include "jni.h"
-#include "nativehelper/JNIHelp.h"
-#include "nativehelper/ScopedPrimitiveArray.h"
-#include "nativehelper/ScopedStringChars.h"
-#include "nativehelper/ScopedUtfChars.h"
+#include <nativehelper/JNIHelp.h>
+#include <nativehelper/ScopedStringChars.h>
+#include <nativehelper/ScopedUtfChars.h>
 #include "utils/Log.h"
-#include "utils/String8.h"
 #include "utils/misc.h"
+#include "utils/String8.h"
 
 extern "C" int capget(cap_user_header_t hdrp, cap_user_data_t datap);
 extern "C" int capset(cap_user_header_t hdrp, const cap_user_data_t datap);
 
-using ::android::base::StringPrintf;
 
 namespace android {
 
+static const bool kThrowOnBadId = false;
+
 // ----------------------------------------------------------------------------
 
-static struct typedvalue_offsets_t {
-  jfieldID mType;
-  jfieldID mData;
-  jfieldID mString;
-  jfieldID mAssetCookie;
-  jfieldID mResourceId;
-  jfieldID mChangingConfigurations;
-  jfieldID mDensity;
+static struct typedvalue_offsets_t
+{
+    jfieldID mType;
+    jfieldID mData;
+    jfieldID mString;
+    jfieldID mAssetCookie;
+    jfieldID mResourceId;
+    jfieldID mChangingConfigurations;
+    jfieldID mDensity;
 } gTypedValueOffsets;
 
-static struct assetfiledescriptor_offsets_t {
-  jfieldID mFd;
-  jfieldID mStartOffset;
-  jfieldID mLength;
+static struct assetfiledescriptor_offsets_t
+{
+    jfieldID mFd;
+    jfieldID mStartOffset;
+    jfieldID mLength;
 } gAssetFileDescriptorOffsets;
 
-static struct assetmanager_offsets_t {
-  jfieldID mObject;
+static struct assetmanager_offsets_t
+{
+    jfieldID mObject;
 } gAssetManagerOffsets;
 
-static struct {
-  jfieldID native_ptr;
-} gApkAssetsFields;
-
-static struct sparsearray_offsets_t {
-  jclass classObject;
-  jmethodID constructor;
-  jmethodID put;
+static struct sparsearray_offsets_t
+{
+    jclass classObject;
+    jmethodID constructor;
+    jmethodID put;
 } gSparseArrayOffsets;
 
-static struct configuration_offsets_t {
-  jclass classObject;
-  jmethodID constructor;
-  jfieldID mSmallestScreenWidthDpOffset;
-  jfieldID mScreenWidthDpOffset;
-  jfieldID mScreenHeightDpOffset;
+static struct configuration_offsets_t
+{
+    jclass classObject;
+    jmethodID constructor;
+    jfieldID mSmallestScreenWidthDpOffset;
+    jfieldID mScreenWidthDpOffset;
+    jfieldID mScreenHeightDpOffset;
 } gConfigurationOffsets;
 
-jclass g_stringClass = nullptr;
+jclass g_stringClass = NULL;
 
 // ----------------------------------------------------------------------------
 
-// Java asset cookies have 0 as an invalid cookie, but TypedArray expects < 0.
-constexpr inline static jint ApkAssetsCookieToJavaCookie(ApkAssetsCookie cookie) {
-  return cookie != kInvalidCookie ? static_cast<jint>(cookie + 1) : -1;
-}
+static jint copyValue(JNIEnv* env, jobject outValue, const ResTable* table,
+                      const Res_value& value, uint32_t ref, ssize_t block,
+                      uint32_t typeSpecFlags, ResTable_config* config = NULL);
 
-constexpr inline static ApkAssetsCookie JavaCookieToApkAssetsCookie(jint cookie) {
-  return cookie > 0 ? static_cast<ApkAssetsCookie>(cookie - 1) : kInvalidCookie;
+jint copyValue(JNIEnv* env, jobject outValue, const ResTable* table,
+               const Res_value& value, uint32_t ref, ssize_t block,
+               uint32_t typeSpecFlags, ResTable_config* config)
+{
+    env->SetIntField(outValue, gTypedValueOffsets.mType, value.dataType);
+    env->SetIntField(outValue, gTypedValueOffsets.mAssetCookie,
+                     static_cast<jint>(table->getTableCookie(block)));
+    env->SetIntField(outValue, gTypedValueOffsets.mData, value.data);
+    env->SetObjectField(outValue, gTypedValueOffsets.mString, NULL);
+    env->SetIntField(outValue, gTypedValueOffsets.mResourceId, ref);
+    env->SetIntField(outValue, gTypedValueOffsets.mChangingConfigurations,
+            typeSpecFlags);
+    if (config != NULL) {
+        env->SetIntField(outValue, gTypedValueOffsets.mDensity, config->density);
+    }
+    return block;
 }
 
 // This is called by zygote (running as user root) as part of preloadResources.
-static void NativeVerifySystemIdmaps(JNIEnv* /*env*/, jclass /*clazz*/) {
-  switch (pid_t pid = fork()) {
-    case -1:
-      PLOG(ERROR) << "failed to fork for idmap";
-      break;
+static void verifySystemIdmaps()
+{
+    pid_t pid;
+    char system_id[10];
 
-    // child
-    case 0: {
-      struct __user_cap_header_struct capheader;
-      struct __user_cap_data_struct capdata;
+    snprintf(system_id, sizeof(system_id), "%d", AID_SYSTEM);
 
-      memset(&capheader, 0, sizeof(capheader));
-      memset(&capdata, 0, sizeof(capdata));
+    switch (pid = fork()) {
+        case -1:
+            ALOGE("failed to fork for idmap: %s", strerror(errno));
+            break;
+        case 0: // child
+            {
+                struct __user_cap_header_struct capheader;
+                struct __user_cap_data_struct capdata;
 
-      capheader.version = _LINUX_CAPABILITY_VERSION;
-      capheader.pid = 0;
+                memset(&capheader, 0, sizeof(capheader));
+                memset(&capdata, 0, sizeof(capdata));
 
-      if (capget(&capheader, &capdata) != 0) {
-        PLOG(ERROR) << "capget";
-        exit(1);
-      }
+                capheader.version = _LINUX_CAPABILITY_VERSION;
+                capheader.pid = 0;
 
-      capdata.effective = capdata.permitted;
-      if (capset(&capheader, &capdata) != 0) {
-        PLOG(ERROR) << "capset";
-        exit(1);
-      }
+                if (capget(&capheader, &capdata) != 0) {
+                    ALOGE("capget: %s\n", strerror(errno));
+                    exit(1);
+                }
 
-      if (setgid(AID_SYSTEM) != 0) {
-        PLOG(ERROR) << "setgid";
-        exit(1);
-      }
+                capdata.effective = capdata.permitted;
+                if (capset(&capheader, &capdata) != 0) {
+                    ALOGE("capset: %s\n", strerror(errno));
+                    exit(1);
+                }
 
-      if (setuid(AID_SYSTEM) != 0) {
-        PLOG(ERROR) << "setuid";
-        exit(1);
-      }
+                if (setgid(AID_SYSTEM) != 0) {
+                    ALOGE("setgid: %s\n", strerror(errno));
+                    exit(1);
+                }
 
-      // Generic idmap parameters
-      const char* argv[8];
-      int argc = 0;
-      struct stat st;
+                if (setuid(AID_SYSTEM) != 0) {
+                    ALOGE("setuid: %s\n", strerror(errno));
+                    exit(1);
+                }
 
-      memset(argv, 0, sizeof(argv));
-      argv[argc++] = AssetManager::IDMAP_BIN;
-      argv[argc++] = "--scan";
-      argv[argc++] = AssetManager::TARGET_PACKAGE_NAME;
-      argv[argc++] = AssetManager::TARGET_APK_PATH;
-      argv[argc++] = AssetManager::IDMAP_DIR;
+                // Generic idmap parameters
+                const char* argv[8];
+                int argc = 0;
+                struct stat st;
 
-      // Directories to scan for overlays: if OVERLAY_THEME_DIR_PROPERTY is defined,
-      // use OVERLAY_DIR/<value of OVERLAY_THEME_DIR_PROPERTY> in addition to OVERLAY_DIR.
-      std::string overlay_theme_path = base::GetProperty(AssetManager::OVERLAY_THEME_DIR_PROPERTY,
-                                                         "");
-      if (!overlay_theme_path.empty()) {
-        overlay_theme_path = std::string(AssetManager::OVERLAY_DIR) + "/" + overlay_theme_path;
-        if (stat(overlay_theme_path.c_str(), &st) == 0) {
-          argv[argc++] = overlay_theme_path.c_str();
-        }
-      }
+                memset(argv, NULL, sizeof(argv));
+                argv[argc++] = AssetManager::IDMAP_BIN;
+                argv[argc++] = "--scan";
+                argv[argc++] = AssetManager::TARGET_PACKAGE_NAME;
+                argv[argc++] = AssetManager::TARGET_APK_PATH;
+                argv[argc++] = AssetManager::IDMAP_DIR;
 
-      if (stat(AssetManager::OVERLAY_DIR, &st) == 0) {
-        argv[argc++] = AssetManager::OVERLAY_DIR;
-      }
+                // Directories to scan for overlays: if OVERLAY_THEME_DIR_PROPERTY is defined,
+                // use OVERLAY_DIR/<value of OVERLAY_THEME_DIR_PROPERTY> in addition to OVERLAY_DIR.
+                char subdir[PROP_VALUE_MAX];
+                int len = __system_property_get(AssetManager::OVERLAY_THEME_DIR_PROPERTY, subdir);
+                if (len > 0) {
+                    String8 overlayPath = String8(AssetManager::OVERLAY_DIR) + "/" + subdir;
+                    if (stat(overlayPath.string(), &st) == 0) {
+                        argv[argc++] = overlayPath.string();
+                    }
+                }
+                if (stat(AssetManager::OVERLAY_DIR, &st) == 0) {
+                    argv[argc++] = AssetManager::OVERLAY_DIR;
+                }
 
-      if (stat(AssetManager::PRODUCT_OVERLAY_DIR, &st) == 0) {
-        argv[argc++] = AssetManager::PRODUCT_OVERLAY_DIR;
-      }
+                if (stat(AssetManager::PRODUCT_OVERLAY_DIR, &st) == 0) {
+                    argv[argc++] = AssetManager::PRODUCT_OVERLAY_DIR;
+                }
 
-      // Finally, invoke idmap (if any overlay directory exists)
-      if (argc > 5) {
-        execv(AssetManager::IDMAP_BIN, (char* const*)argv);
-        PLOG(ERROR) << "failed to execv for idmap";
-        exit(1); // should never get here
-      } else {
-        exit(0);
-      }
-  } break;
-
-  // parent
-  default:
-    waitpid(pid, nullptr, 0);
-    break;
-  }
+                // Finally, invoke idmap (if any overlay directory exists)
+                if (argc > 5) {
+                    execv(AssetManager::IDMAP_BIN, (char* const*)argv);
+                    ALOGE("failed to execv for idmap: %s", strerror(errno));
+                    exit(1); // should never get here
+                } else {
+                    exit(0);
+                }
+            }
+            break;
+        default: // parent
+            waitpid(pid, NULL, 0);
+            break;
+    }
 }
 
-static jint CopyValue(JNIEnv* env, ApkAssetsCookie cookie, const Res_value& value, uint32_t ref,
-                      uint32_t type_spec_flags, ResTable_config* config, jobject out_typed_value) {
-  env->SetIntField(out_typed_value, gTypedValueOffsets.mType, value.dataType);
-  env->SetIntField(out_typed_value, gTypedValueOffsets.mAssetCookie,
-                   ApkAssetsCookieToJavaCookie(cookie));
-  env->SetIntField(out_typed_value, gTypedValueOffsets.mData, value.data);
-  env->SetObjectField(out_typed_value, gTypedValueOffsets.mString, nullptr);
-  env->SetIntField(out_typed_value, gTypedValueOffsets.mResourceId, ref);
-  env->SetIntField(out_typed_value, gTypedValueOffsets.mChangingConfigurations, type_spec_flags);
-  if (config != nullptr) {
-    env->SetIntField(out_typed_value, gTypedValueOffsets.mDensity, config->density);
-  }
-  return static_cast<jint>(ApkAssetsCookieToJavaCookie(cookie));
-}
 
 // ----------------------------------------------------------------------------
 
-// Let the opaque type AAssetManager refer to a guarded AssetManager2 instance.
-struct GuardedAssetManager : public ::AAssetManager {
-  Guarded<AssetManager2> guarded_assetmanager;
-};
-
-::AAssetManager* NdkAssetManagerForJavaObject(JNIEnv* env, jobject jassetmanager) {
-  jlong assetmanager_handle = env->GetLongField(jassetmanager, gAssetManagerOffsets.mObject);
-  ::AAssetManager* am = reinterpret_cast<::AAssetManager*>(assetmanager_handle);
-  if (am == nullptr) {
+// this guy is exported to other jni routines
+AssetManager* assetManagerForJavaObject(JNIEnv* env, jobject obj)
+{
+    jlong amHandle = env->GetLongField(obj, gAssetManagerOffsets.mObject);
+    AssetManager* am = reinterpret_cast<AssetManager*>(amHandle);
+    if (am != NULL) {
+        return am;
+    }
     jniThrowException(env, "java/lang/IllegalStateException", "AssetManager has been finalized!");
-    return nullptr;
-  }
-  return am;
+    return NULL;
 }
 
-Guarded<AssetManager2>* AssetManagerForNdkAssetManager(::AAssetManager* assetmanager) {
-  if (assetmanager == nullptr) {
-    return nullptr;
-  }
-  return &reinterpret_cast<GuardedAssetManager*>(assetmanager)->guarded_assetmanager;
-}
-
-Guarded<AssetManager2>* AssetManagerForJavaObject(JNIEnv* env, jobject jassetmanager) {
-  return AssetManagerForNdkAssetManager(NdkAssetManagerForJavaObject(env, jassetmanager));
-}
-
-static Guarded<AssetManager2>& AssetManagerFromLong(jlong ptr) {
-  return *AssetManagerForNdkAssetManager(reinterpret_cast<AAssetManager*>(ptr));
-}
-
-static jobject ReturnParcelFileDescriptor(JNIEnv* env, std::unique_ptr<Asset> asset,
-                                          jlongArray out_offsets) {
-  off64_t start_offset, length;
-  int fd = asset->openFileDescriptor(&start_offset, &length);
-  asset.reset();
-
-  if (fd < 0) {
-    jniThrowException(env, "java/io/FileNotFoundException",
-                      "This file can not be opened as a file descriptor; it is probably "
-                      "compressed");
-    return nullptr;
-  }
-
-  jlong* offsets = reinterpret_cast<jlong*>(env->GetPrimitiveArrayCritical(out_offsets, 0));
-  if (offsets == nullptr) {
-    close(fd);
-    return nullptr;
-  }
-
-  offsets[0] = start_offset;
-  offsets[1] = length;
-
-  env->ReleasePrimitiveArrayCritical(out_offsets, offsets, 0);
-
-  jobject file_desc = jniCreateFileDescriptor(env, fd);
-  if (file_desc == nullptr) {
-    close(fd);
-    return nullptr;
-  }
-  return newParcelFileDescriptor(env, file_desc);
-}
-
-static jint NativeGetGlobalAssetCount(JNIEnv* /*env*/, jobject /*clazz*/) {
-  return Asset::getGlobalCount();
-}
-
-static jobject NativeGetAssetAllocations(JNIEnv* env, jobject /*clazz*/) {
-  String8 alloc = Asset::getAssetAllocations();
-  if (alloc.length() <= 0) {
-    return nullptr;
-  }
-  return env->NewStringUTF(alloc.string());
-}
-
-static jint NativeGetGlobalAssetManagerCount(JNIEnv* /*env*/, jobject /*clazz*/) {
-  // TODO(adamlesinski): Switch to AssetManager2.
-  return AssetManager::getGlobalCount();
-}
-
-static jlong NativeCreate(JNIEnv* /*env*/, jclass /*clazz*/) {
-  // AssetManager2 needs to be protected by a lock. To avoid cache misses, we allocate the lock and
-  // AssetManager2 in a contiguous block (GuardedAssetManager).
-  return reinterpret_cast<jlong>(new GuardedAssetManager());
-}
-
-static void NativeDestroy(JNIEnv* /*env*/, jclass /*clazz*/, jlong ptr) {
-  delete reinterpret_cast<GuardedAssetManager*>(ptr);
-}
-
-static void NativeSetApkAssets(JNIEnv* env, jclass /*clazz*/, jlong ptr,
-                               jobjectArray apk_assets_array, jboolean invalidate_caches) {
-  const jsize apk_assets_len = env->GetArrayLength(apk_assets_array);
-  std::vector<const ApkAssets*> apk_assets;
-  apk_assets.reserve(apk_assets_len);
-  for (jsize i = 0; i < apk_assets_len; i++) {
-    jobject obj = env->GetObjectArrayElement(apk_assets_array, i);
-    if (obj == nullptr) {
-      std::string msg = StringPrintf("ApkAssets at index %d is null", i);
-      jniThrowNullPointerException(env, msg.c_str());
-      return;
+static jlong android_content_AssetManager_openAsset(JNIEnv* env, jobject clazz,
+                                                jstring fileName, jint mode)
+{
+    AssetManager* am = assetManagerForJavaObject(env, clazz);
+    if (am == NULL) {
+        return 0;
     }
 
-    jlong apk_assets_native_ptr = env->GetLongField(obj, gApkAssetsFields.native_ptr);
-    if (env->ExceptionCheck()) {
-      return;
-    }
-    apk_assets.push_back(reinterpret_cast<const ApkAssets*>(apk_assets_native_ptr));
-  }
+    ALOGV("openAsset in %p (Java object %p)\n", am, clazz);
 
-  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
-  assetmanager->SetApkAssets(apk_assets, invalidate_caches);
-}
-
-static void NativeSetConfiguration(JNIEnv* env, jclass /*clazz*/, jlong ptr, jint mcc, jint mnc,
-                                   jstring locale, jint orientation, jint touchscreen, jint density,
-                                   jint keyboard, jint keyboard_hidden, jint navigation,
-                                   jint screen_width, jint screen_height,
-                                   jint smallest_screen_width_dp, jint screen_width_dp,
-                                   jint screen_height_dp, jint screen_layout, jint ui_mode,
-                                   jint color_mode, jint major_version) {
-  ResTable_config configuration;
-  memset(&configuration, 0, sizeof(configuration));
-  configuration.mcc = static_cast<uint16_t>(mcc);
-  configuration.mnc = static_cast<uint16_t>(mnc);
-  configuration.orientation = static_cast<uint8_t>(orientation);
-  configuration.touchscreen = static_cast<uint8_t>(touchscreen);
-  configuration.density = static_cast<uint16_t>(density);
-  configuration.keyboard = static_cast<uint8_t>(keyboard);
-  configuration.inputFlags = static_cast<uint8_t>(keyboard_hidden);
-  configuration.navigation = static_cast<uint8_t>(navigation);
-  configuration.screenWidth = static_cast<uint16_t>(screen_width);
-  configuration.screenHeight = static_cast<uint16_t>(screen_height);
-  configuration.smallestScreenWidthDp = static_cast<uint16_t>(smallest_screen_width_dp);
-  configuration.screenWidthDp = static_cast<uint16_t>(screen_width_dp);
-  configuration.screenHeightDp = static_cast<uint16_t>(screen_height_dp);
-  configuration.screenLayout = static_cast<uint8_t>(screen_layout);
-  configuration.uiMode = static_cast<uint8_t>(ui_mode);
-  configuration.colorMode = static_cast<uint8_t>(color_mode);
-  configuration.sdkVersion = static_cast<uint16_t>(major_version);
-
-  if (locale != nullptr) {
-    ScopedUtfChars locale_utf8(env, locale);
-    CHECK(locale_utf8.c_str() != nullptr);
-    configuration.setBcp47Locale(locale_utf8.c_str());
-  }
-
-  // Constants duplicated from Java class android.content.res.Configuration.
-  static const jint kScreenLayoutRoundMask = 0x300;
-  static const jint kScreenLayoutRoundShift = 8;
-
-  // In Java, we use a 32bit integer for screenLayout, while we only use an 8bit integer
-  // in C++. We must extract the round qualifier out of the Java screenLayout and put it
-  // into screenLayout2.
-  configuration.screenLayout2 =
-      static_cast<uint8_t>((screen_layout & kScreenLayoutRoundMask) >> kScreenLayoutRoundShift);
-
-  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
-  assetmanager->SetConfiguration(configuration);
-}
-
-static jobject NativeGetAssignedPackageIdentifiers(JNIEnv* env, jclass /*clazz*/, jlong ptr) {
-  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
-
-  jobject sparse_array =
-        env->NewObject(gSparseArrayOffsets.classObject, gSparseArrayOffsets.constructor);
-
-  if (sparse_array == nullptr) {
-    // An exception is pending.
-    return nullptr;
-  }
-
-  assetmanager->ForEachPackage([&](const std::string& package_name, uint8_t package_id) {
-    jstring jpackage_name = env->NewStringUTF(package_name.c_str());
-    if (jpackage_name == nullptr) {
-      // An exception is pending.
-      return;
+    ScopedUtfChars fileName8(env, fileName);
+    if (fileName8.c_str() == NULL) {
+        jniThrowException(env, "java/lang/IllegalArgumentException", "Empty file name");
+        return -1;
     }
 
-    env->CallVoidMethod(sparse_array, gSparseArrayOffsets.put, static_cast<jint>(package_id),
-                        jpackage_name);
-  });
-  return sparse_array;
-}
-
-static jobjectArray NativeList(JNIEnv* env, jclass /*clazz*/, jlong ptr, jstring path) {
-  ScopedUtfChars path_utf8(env, path);
-  if (path_utf8.c_str() == nullptr) {
-    // This will throw NPE.
-    return nullptr;
-  }
-
-  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
-  std::unique_ptr<AssetDir> asset_dir =
-      assetmanager->OpenDir(path_utf8.c_str());
-  if (asset_dir == nullptr) {
-    jniThrowException(env, "java/io/FileNotFoundException", path_utf8.c_str());
-    return nullptr;
-  }
-
-  const size_t file_count = asset_dir->getFileCount();
-
-  jobjectArray array = env->NewObjectArray(file_count, g_stringClass, nullptr);
-  if (array == nullptr) {
-    return nullptr;
-  }
-
-  for (size_t i = 0; i < file_count; i++) {
-    jstring java_string = env->NewStringUTF(asset_dir->getFileName(i).string());
-
-    // Check for errors creating the strings (if malformed or no memory).
-    if (env->ExceptionCheck()) {
-     return nullptr;
+    if (mode != Asset::ACCESS_UNKNOWN && mode != Asset::ACCESS_RANDOM
+        && mode != Asset::ACCESS_STREAMING && mode != Asset::ACCESS_BUFFER) {
+        jniThrowException(env, "java/lang/IllegalArgumentException", "Bad access mode");
+        return -1;
     }
 
-    env->SetObjectArrayElement(array, i, java_string);
+    Asset* a = am->open(fileName8.c_str(), (Asset::AccessMode)mode);
 
-    // If we have a large amount of string in our array, we might overflow the
-    // local reference table of the VM.
-    env->DeleteLocalRef(java_string);
-  }
-  return array;
-}
-
-static jlong NativeOpenAsset(JNIEnv* env, jclass /*clazz*/, jlong ptr, jstring asset_path,
-                             jint access_mode) {
-  ScopedUtfChars asset_path_utf8(env, asset_path);
-  if (asset_path_utf8.c_str() == nullptr) {
-    // This will throw NPE.
-    return 0;
-  }
-
-  if (access_mode != Asset::ACCESS_UNKNOWN && access_mode != Asset::ACCESS_RANDOM &&
-      access_mode != Asset::ACCESS_STREAMING && access_mode != Asset::ACCESS_BUFFER) {
-    jniThrowException(env, "java/lang/IllegalArgumentException", "Bad access mode");
-    return 0;
-  }
-
-  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
-  std::unique_ptr<Asset> asset =
-      assetmanager->Open(asset_path_utf8.c_str(), static_cast<Asset::AccessMode>(access_mode));
-  if (!asset) {
-    jniThrowException(env, "java/io/FileNotFoundException", asset_path_utf8.c_str());
-    return 0;
-  }
-  return reinterpret_cast<jlong>(asset.release());
-}
-
-static jobject NativeOpenAssetFd(JNIEnv* env, jclass /*clazz*/, jlong ptr, jstring asset_path,
-                                 jlongArray out_offsets) {
-  ScopedUtfChars asset_path_utf8(env, asset_path);
-  if (asset_path_utf8.c_str() == nullptr) {
-    // This will throw NPE.
-    return nullptr;
-  }
-
-  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
-  std::unique_ptr<Asset> asset = assetmanager->Open(asset_path_utf8.c_str(), Asset::ACCESS_RANDOM);
-  if (!asset) {
-    jniThrowException(env, "java/io/FileNotFoundException", asset_path_utf8.c_str());
-    return nullptr;
-  }
-  return ReturnParcelFileDescriptor(env, std::move(asset), out_offsets);
-}
-
-static jlong NativeOpenNonAsset(JNIEnv* env, jclass /*clazz*/, jlong ptr, jint jcookie,
-                                jstring asset_path, jint access_mode) {
-  ApkAssetsCookie cookie = JavaCookieToApkAssetsCookie(jcookie);
-  ScopedUtfChars asset_path_utf8(env, asset_path);
-  if (asset_path_utf8.c_str() == nullptr) {
-    // This will throw NPE.
-    return 0;
-  }
-
-  if (access_mode != Asset::ACCESS_UNKNOWN && access_mode != Asset::ACCESS_RANDOM &&
-      access_mode != Asset::ACCESS_STREAMING && access_mode != Asset::ACCESS_BUFFER) {
-    jniThrowException(env, "java/lang/IllegalArgumentException", "Bad access mode");
-    return 0;
-  }
-
-  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
-  std::unique_ptr<Asset> asset;
-  if (cookie != kInvalidCookie) {
-    asset = assetmanager->OpenNonAsset(asset_path_utf8.c_str(), cookie,
-                                       static_cast<Asset::AccessMode>(access_mode));
-  } else {
-    asset = assetmanager->OpenNonAsset(asset_path_utf8.c_str(),
-                                       static_cast<Asset::AccessMode>(access_mode));
-  }
-
-  if (!asset) {
-    jniThrowException(env, "java/io/FileNotFoundException", asset_path_utf8.c_str());
-    return 0;
-  }
-  return reinterpret_cast<jlong>(asset.release());
-}
-
-static jobject NativeOpenNonAssetFd(JNIEnv* env, jclass /*clazz*/, jlong ptr, jint jcookie,
-                                    jstring asset_path, jlongArray out_offsets) {
-  ApkAssetsCookie cookie = JavaCookieToApkAssetsCookie(jcookie);
-  ScopedUtfChars asset_path_utf8(env, asset_path);
-  if (asset_path_utf8.c_str() == nullptr) {
-    // This will throw NPE.
-    return nullptr;
-  }
-
-  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
-  std::unique_ptr<Asset> asset;
-  if (cookie != kInvalidCookie) {
-    asset = assetmanager->OpenNonAsset(asset_path_utf8.c_str(), cookie, Asset::ACCESS_RANDOM);
-  } else {
-    asset = assetmanager->OpenNonAsset(asset_path_utf8.c_str(), Asset::ACCESS_RANDOM);
-  }
-
-  if (!asset) {
-    jniThrowException(env, "java/io/FileNotFoundException", asset_path_utf8.c_str());
-    return nullptr;
-  }
-  return ReturnParcelFileDescriptor(env, std::move(asset), out_offsets);
-}
-
-static jlong NativeOpenXmlAsset(JNIEnv* env, jobject /*clazz*/, jlong ptr, jint jcookie,
-                                jstring asset_path) {
-  ApkAssetsCookie cookie = JavaCookieToApkAssetsCookie(jcookie);
-  ScopedUtfChars asset_path_utf8(env, asset_path);
-  if (asset_path_utf8.c_str() == nullptr) {
-    // This will throw NPE.
-    return 0;
-  }
-
-  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
-  std::unique_ptr<Asset> asset;
-  if (cookie != kInvalidCookie) {
-    asset = assetmanager->OpenNonAsset(asset_path_utf8.c_str(), cookie, Asset::ACCESS_RANDOM);
-  } else {
-    asset = assetmanager->OpenNonAsset(asset_path_utf8.c_str(), Asset::ACCESS_RANDOM, &cookie);
-  }
-
-  if (!asset) {
-    jniThrowException(env, "java/io/FileNotFoundException", asset_path_utf8.c_str());
-    return 0;
-  }
-
-  // May be nullptr.
-  const DynamicRefTable* dynamic_ref_table = assetmanager->GetDynamicRefTableForCookie(cookie);
-
-  std::unique_ptr<ResXMLTree> xml_tree = util::make_unique<ResXMLTree>(dynamic_ref_table);
-  status_t err = xml_tree->setTo(asset->getBuffer(true), asset->getLength(), true);
-  asset.reset();
-
-  if (err != NO_ERROR) {
-    jniThrowException(env, "java/io/FileNotFoundException", "Corrupt XML binary file");
-    return 0;
-  }
-  return reinterpret_cast<jlong>(xml_tree.release());
-}
-
-static jint NativeGetResourceValue(JNIEnv* env, jclass /*clazz*/, jlong ptr, jint resid,
-                                   jshort density, jobject typed_value,
-                                   jboolean resolve_references) {
-  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
-  Res_value value;
-  ResTable_config selected_config;
-  uint32_t flags;
-  ApkAssetsCookie cookie =
-      assetmanager->GetResource(static_cast<uint32_t>(resid), false /*may_be_bag*/,
-                                static_cast<uint16_t>(density), &value, &selected_config, &flags);
-  if (cookie == kInvalidCookie) {
-    return ApkAssetsCookieToJavaCookie(kInvalidCookie);
-  }
-
-  uint32_t ref = static_cast<uint32_t>(resid);
-  if (resolve_references) {
-    cookie = assetmanager->ResolveReference(cookie, &value, &selected_config, &flags, &ref);
-    if (cookie == kInvalidCookie) {
-      return ApkAssetsCookieToJavaCookie(kInvalidCookie);
-    }
-  }
-  return CopyValue(env, cookie, value, ref, flags, &selected_config, typed_value);
-}
-
-static jint NativeGetResourceBagValue(JNIEnv* env, jclass /*clazz*/, jlong ptr, jint resid,
-                                      jint bag_entry_id, jobject typed_value) {
-  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
-  const ResolvedBag* bag = assetmanager->GetBag(static_cast<uint32_t>(resid));
-  if (bag == nullptr) {
-    return ApkAssetsCookieToJavaCookie(kInvalidCookie);
-  }
-
-  uint32_t type_spec_flags = bag->type_spec_flags;
-  ApkAssetsCookie cookie = kInvalidCookie;
-  const Res_value* bag_value = nullptr;
-  for (const ResolvedBag::Entry& entry : bag) {
-    if (entry.key == static_cast<uint32_t>(bag_entry_id)) {
-      cookie = entry.cookie;
-      bag_value = &entry.value;
-
-      // Keep searching (the old implementation did that).
-    }
-  }
-
-  if (cookie == kInvalidCookie) {
-    return ApkAssetsCookieToJavaCookie(kInvalidCookie);
-  }
-
-  Res_value value = *bag_value;
-  uint32_t ref = static_cast<uint32_t>(resid);
-  ResTable_config selected_config;
-  cookie = assetmanager->ResolveReference(cookie, &value, &selected_config, &type_spec_flags, &ref);
-  if (cookie == kInvalidCookie) {
-    return ApkAssetsCookieToJavaCookie(kInvalidCookie);
-  }
-  return CopyValue(env, cookie, value, ref, type_spec_flags, nullptr, typed_value);
-}
-
-static jintArray NativeGetStyleAttributes(JNIEnv* env, jclass /*clazz*/, jlong ptr, jint resid) {
-  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
-  const ResolvedBag* bag = assetmanager->GetBag(static_cast<uint32_t>(resid));
-  if (bag == nullptr) {
-    return nullptr;
-  }
-
-  jintArray array = env->NewIntArray(bag->entry_count);
-  if (env->ExceptionCheck()) {
-    return nullptr;
-  }
-
-  for (uint32_t i = 0; i < bag->entry_count; i++) {
-    jint attr_resid = bag->entries[i].key;
-    env->SetIntArrayRegion(array, i, 1, &attr_resid);
-  }
-  return array;
-}
-
-static jobjectArray NativeGetResourceStringArray(JNIEnv* env, jclass /*clazz*/, jlong ptr,
-                                                 jint resid) {
-  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
-  const ResolvedBag* bag = assetmanager->GetBag(static_cast<uint32_t>(resid));
-  if (bag == nullptr) {
-    return nullptr;
-  }
-
-  jobjectArray array = env->NewObjectArray(bag->entry_count, g_stringClass, nullptr);
-  if (array == nullptr) {
-    return nullptr;
-  }
-
-  for (uint32_t i = 0; i < bag->entry_count; i++) {
-    const ResolvedBag::Entry& entry = bag->entries[i];
-
-    // Resolve any references to their final value.
-    Res_value value = entry.value;
-    ResTable_config selected_config;
-    uint32_t flags;
-    uint32_t ref;
-    ApkAssetsCookie cookie =
-        assetmanager->ResolveReference(entry.cookie, &value, &selected_config, &flags, &ref);
-    if (cookie == kInvalidCookie) {
-      return nullptr;
+    if (a == NULL) {
+        jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
+        return -1;
     }
 
-    if (value.dataType == Res_value::TYPE_STRING) {
-      const ApkAssets* apk_assets = assetmanager->GetApkAssets()[cookie];
-      const ResStringPool* pool = apk_assets->GetLoadedArsc()->GetStringPool();
+    //printf("Created Asset Stream: %p\n", a);
 
-      jstring java_string = nullptr;
-      size_t str_len;
-      const char* str_utf8 = pool->string8At(value.data, &str_len);
-      if (str_utf8 != nullptr) {
-        java_string = env->NewStringUTF(str_utf8);
-      } else {
-        const char16_t* str_utf16 = pool->stringAt(value.data, &str_len);
-        java_string = env->NewString(reinterpret_cast<const jchar*>(str_utf16), str_len);
-      }
-
-      // Check for errors creating the strings (if malformed or no memory).
-      if (env->ExceptionCheck()) {
-        return nullptr;
-      }
-
-      env->SetObjectArrayElement(array, i, java_string);
-
-      // If we have a large amount of string in our array, we might overflow the
-      // local reference table of the VM.
-      env->DeleteLocalRef(java_string);
-    }
-  }
-  return array;
+    return reinterpret_cast<jlong>(a);
 }
 
-static jintArray NativeGetResourceStringArrayInfo(JNIEnv* env, jclass /*clazz*/, jlong ptr,
-                                                  jint resid) {
-  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
-  const ResolvedBag* bag = assetmanager->GetBag(static_cast<uint32_t>(resid));
-  if (bag == nullptr) {
-    return nullptr;
-  }
+static jobject returnParcelFileDescriptor(JNIEnv* env, Asset* a, jlongArray outOffsets)
+{
+    off64_t startOffset, length;
+    int fd = a->openFileDescriptor(&startOffset, &length);
+    delete a;
 
-  jintArray array = env->NewIntArray(bag->entry_count * 2);
-  if (array == nullptr) {
-    return nullptr;
-  }
-
-  jint* buffer = reinterpret_cast<jint*>(env->GetPrimitiveArrayCritical(array, nullptr));
-  if (buffer == nullptr) {
-    return nullptr;
-  }
-
-  for (size_t i = 0; i < bag->entry_count; i++) {
-    const ResolvedBag::Entry& entry = bag->entries[i];
-    Res_value value = entry.value;
-    ResTable_config selected_config;
-    uint32_t flags;
-    uint32_t ref;
-    ApkAssetsCookie cookie =
-        assetmanager->ResolveReference(entry.cookie, &value, &selected_config, &flags, &ref);
-    if (cookie == kInvalidCookie) {
-      env->ReleasePrimitiveArrayCritical(array, buffer, JNI_ABORT);
-      return nullptr;
+    if (fd < 0) {
+        jniThrowException(env, "java/io/FileNotFoundException",
+                "This file can not be opened as a file descriptor; it is probably compressed");
+        return NULL;
     }
 
-    jint string_index = -1;
-    if (value.dataType == Res_value::TYPE_STRING) {
-      string_index = static_cast<jint>(value.data);
+    jlong* offsets = (jlong*)env->GetPrimitiveArrayCritical(outOffsets, 0);
+    if (offsets == NULL) {
+        close(fd);
+        return NULL;
     }
 
-    buffer[i * 2] = ApkAssetsCookieToJavaCookie(cookie);
-    buffer[(i * 2) + 1] = string_index;
-  }
-  env->ReleasePrimitiveArrayCritical(array, buffer, 0);
-  return array;
+    offsets[0] = startOffset;
+    offsets[1] = length;
+
+    env->ReleasePrimitiveArrayCritical(outOffsets, offsets, 0);
+
+    jobject fileDesc = jniCreateFileDescriptor(env, fd);
+    if (fileDesc == NULL) {
+        close(fd);
+        return NULL;
+    }
+
+    return newParcelFileDescriptor(env, fileDesc);
 }
 
-static jintArray NativeGetResourceIntArray(JNIEnv* env, jclass /*clazz*/, jlong ptr, jint resid) {
-  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
-  const ResolvedBag* bag = assetmanager->GetBag(static_cast<uint32_t>(resid));
-  if (bag == nullptr) {
-    return nullptr;
-  }
-
-  jintArray array = env->NewIntArray(bag->entry_count);
-  if (array == nullptr) {
-    return nullptr;
-  }
-
-  jint* buffer = reinterpret_cast<jint*>(env->GetPrimitiveArrayCritical(array, nullptr));
-  if (buffer == nullptr) {
-    return nullptr;
-  }
-
-  for (size_t i = 0; i < bag->entry_count; i++) {
-    const ResolvedBag::Entry& entry = bag->entries[i];
-    Res_value value = entry.value;
-    ResTable_config selected_config;
-    uint32_t flags;
-    uint32_t ref;
-    ApkAssetsCookie cookie =
-        assetmanager->ResolveReference(entry.cookie, &value, &selected_config, &flags, &ref);
-    if (cookie == kInvalidCookie) {
-      env->ReleasePrimitiveArrayCritical(array, buffer, JNI_ABORT);
-      return nullptr;
+static jobject android_content_AssetManager_openAssetFd(JNIEnv* env, jobject clazz,
+                                                jstring fileName, jlongArray outOffsets)
+{
+    AssetManager* am = assetManagerForJavaObject(env, clazz);
+    if (am == NULL) {
+        return NULL;
     }
 
-    if (value.dataType >= Res_value::TYPE_FIRST_INT && value.dataType <= Res_value::TYPE_LAST_INT) {
-      buffer[i] = static_cast<jint>(value.data);
-    }
-  }
-  env->ReleasePrimitiveArrayCritical(array, buffer, 0);
-  return array;
-}
+    ALOGV("openAssetFd in %p (Java object %p)\n", am, clazz);
 
-static jint NativeGetResourceArraySize(JNIEnv* /*env*/, jclass /*clazz*/, jlong ptr, jint resid) {
-  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
-  const ResolvedBag* bag = assetmanager->GetBag(static_cast<uint32_t>(resid));
-  if (bag == nullptr) {
-    return -1;
-  }
-  return static_cast<jint>(bag->entry_count);
-}
-
-static jint NativeGetResourceArray(JNIEnv* env, jclass /*clazz*/, jlong ptr, jint resid,
-                                   jintArray out_data) {
-  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
-  const ResolvedBag* bag = assetmanager->GetBag(static_cast<uint32_t>(resid));
-  if (bag == nullptr) {
-    return -1;
-  }
-
-  const jsize out_data_length = env->GetArrayLength(out_data);
-  if (env->ExceptionCheck()) {
-    return -1;
-  }
-
-  if (static_cast<jsize>(bag->entry_count) > out_data_length * STYLE_NUM_ENTRIES) {
-    jniThrowException(env, "java/lang/IllegalArgumentException", "Input array is not large enough");
-    return -1;
-  }
-
-  jint* buffer = reinterpret_cast<jint*>(env->GetPrimitiveArrayCritical(out_data, nullptr));
-  if (buffer == nullptr) {
-    return -1;
-  }
-
-  jint* cursor = buffer;
-  for (size_t i = 0; i < bag->entry_count; i++) {
-    const ResolvedBag::Entry& entry = bag->entries[i];
-    Res_value value = entry.value;
-    ResTable_config selected_config;
-    selected_config.density = 0;
-    uint32_t flags = bag->type_spec_flags;
-    uint32_t ref;
-    ApkAssetsCookie cookie =
-        assetmanager->ResolveReference(entry.cookie, &value, &selected_config, &flags, &ref);
-    if (cookie == kInvalidCookie) {
-      env->ReleasePrimitiveArrayCritical(out_data, buffer, JNI_ABORT);
-      return -1;
+    ScopedUtfChars fileName8(env, fileName);
+    if (fileName8.c_str() == NULL) {
+        return NULL;
     }
 
-    // Deal with the special @null value -- it turns back to TYPE_NULL.
-    if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
-      value.dataType = Res_value::TYPE_NULL;
-      value.data = Res_value::DATA_NULL_UNDEFINED;
+    Asset* a = am->open(fileName8.c_str(), Asset::ACCESS_RANDOM);
+
+    if (a == NULL) {
+        jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
+        return NULL;
     }
 
-    cursor[STYLE_TYPE] = static_cast<jint>(value.dataType);
-    cursor[STYLE_DATA] = static_cast<jint>(value.data);
-    cursor[STYLE_ASSET_COOKIE] = ApkAssetsCookieToJavaCookie(cookie);
-    cursor[STYLE_RESOURCE_ID] = static_cast<jint>(ref);
-    cursor[STYLE_CHANGING_CONFIGURATIONS] = static_cast<jint>(flags);
-    cursor[STYLE_DENSITY] = static_cast<jint>(selected_config.density);
-    cursor += STYLE_NUM_ENTRIES;
-  }
-  env->ReleasePrimitiveArrayCritical(out_data, buffer, 0);
-  return static_cast<jint>(bag->entry_count);
+    //printf("Created Asset Stream: %p\n", a);
+
+    return returnParcelFileDescriptor(env, a, outOffsets);
 }
 
-static jint NativeGetResourceIdentifier(JNIEnv* env, jclass /*clazz*/, jlong ptr, jstring name,
-                                        jstring def_type, jstring def_package) {
-  ScopedUtfChars name_utf8(env, name);
-  if (name_utf8.c_str() == nullptr) {
-    // This will throw NPE.
-    return 0;
-  }
-
-  std::string type;
-  if (def_type != nullptr) {
-    ScopedUtfChars type_utf8(env, def_type);
-    CHECK(type_utf8.c_str() != nullptr);
-    type = type_utf8.c_str();
-  }
-
-  std::string package;
-  if (def_package != nullptr) {
-    ScopedUtfChars package_utf8(env, def_package);
-    CHECK(package_utf8.c_str() != nullptr);
-    package = package_utf8.c_str();
-  }
-  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
-  return static_cast<jint>(assetmanager->GetResourceId(name_utf8.c_str(), type, package));
-}
-
-static jstring NativeGetResourceName(JNIEnv* env, jclass /*clazz*/, jlong ptr, jint resid) {
-  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
-  AssetManager2::ResourceName name;
-  if (!assetmanager->GetResourceName(static_cast<uint32_t>(resid), &name)) {
-    return nullptr;
-  }
-
-  std::string result;
-  if (name.package != nullptr) {
-    result.append(name.package, name.package_len);
-  }
-
-  if (name.type != nullptr || name.type16 != nullptr) {
-    if (!result.empty()) {
-      result += ":";
+static jlong android_content_AssetManager_openNonAssetNative(JNIEnv* env, jobject clazz,
+                                                         jint cookie,
+                                                         jstring fileName,
+                                                         jint mode)
+{
+    AssetManager* am = assetManagerForJavaObject(env, clazz);
+    if (am == NULL) {
+        return 0;
     }
 
-    if (name.type != nullptr) {
-      result.append(name.type, name.type_len);
-    } else {
-      result += util::Utf16ToUtf8(StringPiece16(name.type16, name.type_len));
-    }
-  }
+    ALOGV("openNonAssetNative in %p (Java object %p)\n", am, clazz);
 
-  if (name.entry != nullptr || name.entry16 != nullptr) {
-    if (!result.empty()) {
-      result += "/";
+    ScopedUtfChars fileName8(env, fileName);
+    if (fileName8.c_str() == NULL) {
+        return -1;
     }
 
-    if (name.entry != nullptr) {
-      result.append(name.entry, name.entry_len);
-    } else {
-      result += util::Utf16ToUtf8(StringPiece16(name.entry16, name.entry_len));
-    }
-  }
-  return env->NewStringUTF(result.c_str());
-}
-
-static jstring NativeGetResourcePackageName(JNIEnv* env, jclass /*clazz*/, jlong ptr, jint resid) {
-  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
-  AssetManager2::ResourceName name;
-  if (!assetmanager->GetResourceName(static_cast<uint32_t>(resid), &name)) {
-    return nullptr;
-  }
-
-  if (name.package != nullptr) {
-    return env->NewStringUTF(name.package);
-  }
-  return nullptr;
-}
-
-static jstring NativeGetResourceTypeName(JNIEnv* env, jclass /*clazz*/, jlong ptr, jint resid) {
-  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
-  AssetManager2::ResourceName name;
-  if (!assetmanager->GetResourceName(static_cast<uint32_t>(resid), &name)) {
-    return nullptr;
-  }
-
-  if (name.type != nullptr) {
-    return env->NewStringUTF(name.type);
-  } else if (name.type16 != nullptr) {
-    return env->NewString(reinterpret_cast<const jchar*>(name.type16), name.type_len);
-  }
-  return nullptr;
-}
-
-static jstring NativeGetResourceEntryName(JNIEnv* env, jclass /*clazz*/, jlong ptr, jint resid) {
-  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
-  AssetManager2::ResourceName name;
-  if (!assetmanager->GetResourceName(static_cast<uint32_t>(resid), &name)) {
-    return nullptr;
-  }
-
-  if (name.entry != nullptr) {
-    return env->NewStringUTF(name.entry);
-  } else if (name.entry16 != nullptr) {
-    return env->NewString(reinterpret_cast<const jchar*>(name.entry16), name.entry_len);
-  }
-  return nullptr;
-}
-
-static jobjectArray NativeGetLocales(JNIEnv* env, jclass /*class*/, jlong ptr,
-                                     jboolean exclude_system) {
-  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
-  std::set<std::string> locales =
-      assetmanager->GetResourceLocales(exclude_system, true /*merge_equivalent_languages*/);
-
-  jobjectArray array = env->NewObjectArray(locales.size(), g_stringClass, nullptr);
-  if (array == nullptr) {
-    return nullptr;
-  }
-
-  size_t idx = 0;
-  for (const std::string& locale : locales) {
-    jstring java_string = env->NewStringUTF(locale.c_str());
-    if (java_string == nullptr) {
-      return nullptr;
-    }
-    env->SetObjectArrayElement(array, idx++, java_string);
-    env->DeleteLocalRef(java_string);
-  }
-  return array;
-}
-
-static jobject ConstructConfigurationObject(JNIEnv* env, const ResTable_config& config) {
-  jobject result =
-      env->NewObject(gConfigurationOffsets.classObject, gConfigurationOffsets.constructor);
-  if (result == nullptr) {
-    return nullptr;
-  }
-
-  env->SetIntField(result, gConfigurationOffsets.mSmallestScreenWidthDpOffset,
-                   config.smallestScreenWidthDp);
-  env->SetIntField(result, gConfigurationOffsets.mScreenWidthDpOffset, config.screenWidthDp);
-  env->SetIntField(result, gConfigurationOffsets.mScreenHeightDpOffset, config.screenHeightDp);
-  return result;
-}
-
-static jobjectArray NativeGetSizeConfigurations(JNIEnv* env, jclass /*clazz*/, jlong ptr) {
-  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
-  std::set<ResTable_config> configurations =
-      assetmanager->GetResourceConfigurations(true /*exclude_system*/, false /*exclude_mipmap*/);
-
-  jobjectArray array =
-      env->NewObjectArray(configurations.size(), gConfigurationOffsets.classObject, nullptr);
-  if (array == nullptr) {
-    return nullptr;
-  }
-
-  size_t idx = 0;
-  for (const ResTable_config& configuration : configurations) {
-    jobject java_configuration = ConstructConfigurationObject(env, configuration);
-    if (java_configuration == nullptr) {
-      return nullptr;
+    if (mode != Asset::ACCESS_UNKNOWN && mode != Asset::ACCESS_RANDOM
+        && mode != Asset::ACCESS_STREAMING && mode != Asset::ACCESS_BUFFER) {
+        jniThrowException(env, "java/lang/IllegalArgumentException", "Bad access mode");
+        return -1;
     }
 
-    env->SetObjectArrayElement(array, idx++, java_configuration);
-    env->DeleteLocalRef(java_configuration);
-  }
-  return array;
+    Asset* a = cookie
+        ? am->openNonAsset(static_cast<int32_t>(cookie), fileName8.c_str(),
+                (Asset::AccessMode)mode)
+        : am->openNonAsset(fileName8.c_str(), (Asset::AccessMode)mode);
+
+    if (a == NULL) {
+        jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
+        return -1;
+    }
+
+    //printf("Created Asset Stream: %p\n", a);
+
+    return reinterpret_cast<jlong>(a);
 }
 
-static void NativeApplyStyle(JNIEnv* env, jclass /*clazz*/, jlong ptr, jlong theme_ptr,
-                             jint def_style_attr, jint def_style_resid, jlong xml_parser_ptr,
-                             jintArray java_attrs, jlong out_values_ptr, jlong out_indices_ptr) {
-  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
-  Theme* theme = reinterpret_cast<Theme*>(theme_ptr);
-  CHECK(theme->GetAssetManager() == &(*assetmanager));
-  (void) assetmanager;
+static jobject android_content_AssetManager_openNonAssetFdNative(JNIEnv* env, jobject clazz,
+                                                         jint cookie,
+                                                         jstring fileName,
+                                                         jlongArray outOffsets)
+{
+    AssetManager* am = assetManagerForJavaObject(env, clazz);
+    if (am == NULL) {
+        return NULL;
+    }
 
-  ResXMLParser* xml_parser = reinterpret_cast<ResXMLParser*>(xml_parser_ptr);
-  uint32_t* out_values = reinterpret_cast<uint32_t*>(out_values_ptr);
-  uint32_t* out_indices = reinterpret_cast<uint32_t*>(out_indices_ptr);
+    ALOGV("openNonAssetFd in %p (Java object %p)\n", am, clazz);
 
-  jsize attrs_len = env->GetArrayLength(java_attrs);
-  jint* attrs = reinterpret_cast<jint*>(env->GetPrimitiveArrayCritical(java_attrs, nullptr));
-  if (attrs == nullptr) {
-    return;
-  }
+    ScopedUtfChars fileName8(env, fileName);
+    if (fileName8.c_str() == NULL) {
+        return NULL;
+    }
 
-  ApplyStyle(theme, xml_parser, static_cast<uint32_t>(def_style_attr),
-             static_cast<uint32_t>(def_style_resid), reinterpret_cast<uint32_t*>(attrs), attrs_len,
-             out_values, out_indices);
-  env->ReleasePrimitiveArrayCritical(java_attrs, attrs, JNI_ABORT);
+    Asset* a = cookie
+        ? am->openNonAsset(static_cast<int32_t>(cookie), fileName8.c_str(), Asset::ACCESS_RANDOM)
+        : am->openNonAsset(fileName8.c_str(), Asset::ACCESS_RANDOM);
+
+    if (a == NULL) {
+        jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
+        return NULL;
+    }
+
+    //printf("Created Asset Stream: %p\n", a);
+
+    return returnParcelFileDescriptor(env, a, outOffsets);
 }
 
-static jboolean NativeResolveAttrs(JNIEnv* env, jclass /*clazz*/, jlong ptr, jlong theme_ptr,
-                                   jint def_style_attr, jint def_style_resid, jintArray java_values,
-                                   jintArray java_attrs, jintArray out_java_values,
-                                   jintArray out_java_indices) {
-  const jsize attrs_len = env->GetArrayLength(java_attrs);
-  const jsize out_values_len = env->GetArrayLength(out_java_values);
-  if (out_values_len < (attrs_len * STYLE_NUM_ENTRIES)) {
-    jniThrowException(env, "java/lang/IndexOutOfBoundsException", "outValues too small");
-    return JNI_FALSE;
-  }
-
-  jint* attrs = reinterpret_cast<jint*>(env->GetPrimitiveArrayCritical(java_attrs, nullptr));
-  if (attrs == nullptr) {
-    return JNI_FALSE;
-  }
-
-  jint* values = nullptr;
-  jsize values_len = 0;
-  if (java_values != nullptr) {
-    values_len = env->GetArrayLength(java_values);
-    values = reinterpret_cast<jint*>(env->GetPrimitiveArrayCritical(java_values, nullptr));
-    if (values == nullptr) {
-      env->ReleasePrimitiveArrayCritical(java_attrs, attrs, JNI_ABORT);
-      return JNI_FALSE;
+static jobjectArray android_content_AssetManager_list(JNIEnv* env, jobject clazz,
+                                                   jstring fileName)
+{
+    AssetManager* am = assetManagerForJavaObject(env, clazz);
+    if (am == NULL) {
+        return NULL;
     }
-  }
 
-  jint* out_values =
-      reinterpret_cast<jint*>(env->GetPrimitiveArrayCritical(out_java_values, nullptr));
-  if (out_values == nullptr) {
-    env->ReleasePrimitiveArrayCritical(java_attrs, attrs, JNI_ABORT);
-    if (values != nullptr) {
-      env->ReleasePrimitiveArrayCritical(java_values, values, JNI_ABORT);
+    ScopedUtfChars fileName8(env, fileName);
+    if (fileName8.c_str() == NULL) {
+        return NULL;
     }
-    return JNI_FALSE;
-  }
 
-  jint* out_indices = nullptr;
-  if (out_java_indices != nullptr) {
-    jsize out_indices_len = env->GetArrayLength(out_java_indices);
-    if (out_indices_len > attrs_len) {
-      out_indices =
-          reinterpret_cast<jint*>(env->GetPrimitiveArrayCritical(out_java_indices, nullptr));
-      if (out_indices == nullptr) {
-        env->ReleasePrimitiveArrayCritical(java_attrs, attrs, JNI_ABORT);
-        if (values != nullptr) {
-          env->ReleasePrimitiveArrayCritical(java_values, values, JNI_ABORT);
+    AssetDir* dir = am->openDir(fileName8.c_str());
+
+    if (dir == NULL) {
+        jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
+        return NULL;
+    }
+
+    size_t N = dir->getFileCount();
+
+    jobjectArray array = env->NewObjectArray(dir->getFileCount(),
+                                                g_stringClass, NULL);
+    if (array == NULL) {
+        delete dir;
+        return NULL;
+    }
+
+    for (size_t i=0; i<N; i++) {
+        const String8& name = dir->getFileName(i);
+        jstring str = env->NewStringUTF(name.string());
+        if (str == NULL) {
+            delete dir;
+            return NULL;
         }
-        env->ReleasePrimitiveArrayCritical(out_java_values, out_values, JNI_ABORT);
+        env->SetObjectArrayElement(array, i, str);
+        env->DeleteLocalRef(str);
+    }
+
+    delete dir;
+
+    return array;
+}
+
+static void android_content_AssetManager_destroyAsset(JNIEnv* env, jobject clazz,
+                                                      jlong assetHandle)
+{
+    Asset* a = reinterpret_cast<Asset*>(assetHandle);
+
+    //printf("Destroying Asset Stream: %p\n", a);
+
+    if (a == NULL) {
+        jniThrowNullPointerException(env, "asset");
+        return;
+    }
+
+    delete a;
+}
+
+static jint android_content_AssetManager_readAssetChar(JNIEnv* env, jobject clazz,
+                                                       jlong assetHandle)
+{
+    Asset* a = reinterpret_cast<Asset*>(assetHandle);
+
+    if (a == NULL) {
+        jniThrowNullPointerException(env, "asset");
+        return -1;
+    }
+
+    uint8_t b;
+    ssize_t res = a->read(&b, 1);
+    return res == 1 ? b : -1;
+}
+
+static jint android_content_AssetManager_readAsset(JNIEnv* env, jobject clazz,
+                                                jlong assetHandle, jbyteArray bArray,
+                                                jint off, jint len)
+{
+    Asset* a = reinterpret_cast<Asset*>(assetHandle);
+
+    if (a == NULL || bArray == NULL) {
+        jniThrowNullPointerException(env, "asset");
+        return -1;
+    }
+
+    if (len == 0) {
+        return 0;
+    }
+
+    jsize bLen = env->GetArrayLength(bArray);
+    if (off < 0 || off >= bLen || len < 0 || len > bLen || (off+len) > bLen) {
+        jniThrowException(env, "java/lang/IndexOutOfBoundsException", "");
+        return -1;
+    }
+
+    jbyte* b = env->GetByteArrayElements(bArray, NULL);
+    ssize_t res = a->read(b+off, len);
+    env->ReleaseByteArrayElements(bArray, b, 0);
+
+    if (res > 0) return static_cast<jint>(res);
+
+    if (res < 0) {
+        jniThrowException(env, "java/io/IOException", "");
+    }
+    return -1;
+}
+
+static jlong android_content_AssetManager_seekAsset(JNIEnv* env, jobject clazz,
+                                                 jlong assetHandle,
+                                                 jlong offset, jint whence)
+{
+    Asset* a = reinterpret_cast<Asset*>(assetHandle);
+
+    if (a == NULL) {
+        jniThrowNullPointerException(env, "asset");
+        return -1;
+    }
+
+    return a->seek(
+        offset, (whence > 0) ? SEEK_END : (whence < 0 ? SEEK_SET : SEEK_CUR));
+}
+
+static jlong android_content_AssetManager_getAssetLength(JNIEnv* env, jobject clazz,
+                                                      jlong assetHandle)
+{
+    Asset* a = reinterpret_cast<Asset*>(assetHandle);
+
+    if (a == NULL) {
+        jniThrowNullPointerException(env, "asset");
+        return -1;
+    }
+
+    return a->getLength();
+}
+
+static jlong android_content_AssetManager_getAssetRemainingLength(JNIEnv* env, jobject clazz,
+                                                               jlong assetHandle)
+{
+    Asset* a = reinterpret_cast<Asset*>(assetHandle);
+
+    if (a == NULL) {
+        jniThrowNullPointerException(env, "asset");
+        return -1;
+    }
+
+    return a->getRemainingLength();
+}
+
+static jint android_content_AssetManager_addAssetPath(JNIEnv* env, jobject clazz,
+                                                       jstring path, jboolean appAsLib)
+{
+    ScopedUtfChars path8(env, path);
+    if (path8.c_str() == NULL) {
+        return 0;
+    }
+
+    AssetManager* am = assetManagerForJavaObject(env, clazz);
+    if (am == NULL) {
+        return 0;
+    }
+
+    int32_t cookie;
+    bool res = am->addAssetPath(String8(path8.c_str()), &cookie, appAsLib);
+
+    return (res) ? static_cast<jint>(cookie) : 0;
+}
+
+static jint android_content_AssetManager_addOverlayPath(JNIEnv* env, jobject clazz,
+                                                     jstring idmapPath)
+{
+    ScopedUtfChars idmapPath8(env, idmapPath);
+    if (idmapPath8.c_str() == NULL) {
+        return 0;
+    }
+
+    AssetManager* am = assetManagerForJavaObject(env, clazz);
+    if (am == NULL) {
+        return 0;
+    }
+
+    int32_t cookie;
+    bool res = am->addOverlayPath(String8(idmapPath8.c_str()), &cookie);
+
+    return (res) ? (jint)cookie : 0;
+}
+
+static jint android_content_AssetManager_addAssetFd(JNIEnv* env, jobject clazz,
+                                                    jobject fileDescriptor, jstring debugPathName,
+                                                    jboolean appAsLib)
+{
+    ScopedUtfChars debugPathName8(env, debugPathName);
+
+    int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
+    if (fd < 0) {
+        jniThrowException(env, "java/lang/IllegalArgumentException", "Bad FileDescriptor");
+        return 0;
+    }
+
+    AssetManager* am = assetManagerForJavaObject(env, clazz);
+    if (am == NULL) {
+        return 0;
+    }
+
+    int dupfd = ::dup(fd);
+    if (dupfd < 0) {
+        jniThrowIOException(env, errno);
+        return 0;
+    }
+
+    int32_t cookie;
+    bool res = am->addAssetFd(dupfd, String8(debugPathName8.c_str()), &cookie, appAsLib);
+
+    return (res) ? static_cast<jint>(cookie) : 0;
+}
+
+static jboolean android_content_AssetManager_isUpToDate(JNIEnv* env, jobject clazz)
+{
+    AssetManager* am = assetManagerForJavaObject(env, clazz);
+    if (am == NULL) {
+        return JNI_TRUE;
+    }
+    return am->isUpToDate() ? JNI_TRUE : JNI_FALSE;
+}
+
+static jobjectArray getLocales(JNIEnv* env, jobject clazz, bool includeSystemLocales)
+{
+    Vector<String8> locales;
+
+    AssetManager* am = assetManagerForJavaObject(env, clazz);
+    if (am == NULL) {
+        return NULL;
+    }
+
+    am->getLocales(&locales, includeSystemLocales);
+
+    const int N = locales.size();
+
+    jobjectArray result = env->NewObjectArray(N, g_stringClass, NULL);
+    if (result == NULL) {
+        return NULL;
+    }
+
+    for (int i=0; i<N; i++) {
+        jstring str = env->NewStringUTF(locales[i].string());
+        if (str == NULL) {
+            return NULL;
+        }
+        env->SetObjectArrayElement(result, i, str);
+        env->DeleteLocalRef(str);
+    }
+
+    return result;
+}
+
+static jobjectArray android_content_AssetManager_getLocales(JNIEnv* env, jobject clazz)
+{
+    return getLocales(env, clazz, true /* include system locales */);
+}
+
+static jobjectArray android_content_AssetManager_getNonSystemLocales(JNIEnv* env, jobject clazz)
+{
+    return getLocales(env, clazz, false /* don't include system locales */);
+}
+
+static jobject constructConfigurationObject(JNIEnv* env, const ResTable_config& config) {
+    jobject result = env->NewObject(gConfigurationOffsets.classObject,
+            gConfigurationOffsets.constructor);
+    if (result == NULL) {
+        return NULL;
+    }
+
+    env->SetIntField(result, gConfigurationOffsets.mSmallestScreenWidthDpOffset,
+            config.smallestScreenWidthDp);
+    env->SetIntField(result, gConfigurationOffsets.mScreenWidthDpOffset, config.screenWidthDp);
+    env->SetIntField(result, gConfigurationOffsets.mScreenHeightDpOffset, config.screenHeightDp);
+
+    return result;
+}
+
+static jobjectArray getSizeConfigurationsInternal(JNIEnv* env,
+        const Vector<ResTable_config>& configs) {
+    const int N = configs.size();
+    jobjectArray result = env->NewObjectArray(N, gConfigurationOffsets.classObject, NULL);
+    if (result == NULL) {
+        return NULL;
+    }
+
+    for (int i=0; i<N; i++) {
+        jobject config = constructConfigurationObject(env, configs[i]);
+        if (config == NULL) {
+            env->DeleteLocalRef(result);
+            return NULL;
+        }
+
+        env->SetObjectArrayElement(result, i, config);
+        env->DeleteLocalRef(config);
+    }
+
+    return result;
+}
+
+static jobjectArray android_content_AssetManager_getSizeConfigurations(JNIEnv* env, jobject clazz) {
+    AssetManager* am = assetManagerForJavaObject(env, clazz);
+    if (am == NULL) {
+        return NULL;
+    }
+
+    const ResTable& res(am->getResources());
+    Vector<ResTable_config> configs;
+    res.getConfigurations(&configs, false /* ignoreMipmap */, true /* ignoreAndroidPackage */);
+
+    return getSizeConfigurationsInternal(env, configs);
+}
+
+static void android_content_AssetManager_setConfiguration(JNIEnv* env, jobject clazz,
+                                                          jint mcc, jint mnc,
+                                                          jstring locale, jint orientation,
+                                                          jint touchscreen, jint density,
+                                                          jint keyboard, jint keyboardHidden,
+                                                          jint navigation,
+                                                          jint screenWidth, jint screenHeight,
+                                                          jint smallestScreenWidthDp,
+                                                          jint screenWidthDp, jint screenHeightDp,
+                                                          jint screenLayout, jint uiMode,
+                                                          jint colorMode, jint sdkVersion)
+{
+    AssetManager* am = assetManagerForJavaObject(env, clazz);
+    if (am == NULL) {
+        return;
+    }
+
+    ResTable_config config;
+    memset(&config, 0, sizeof(config));
+
+    const char* locale8 = locale != NULL ? env->GetStringUTFChars(locale, NULL) : NULL;
+
+    // Constants duplicated from Java class android.content.res.Configuration.
+    static const jint kScreenLayoutRoundMask = 0x300;
+    static const jint kScreenLayoutRoundShift = 8;
+
+    config.mcc = (uint16_t)mcc;
+    config.mnc = (uint16_t)mnc;
+    config.orientation = (uint8_t)orientation;
+    config.touchscreen = (uint8_t)touchscreen;
+    config.density = (uint16_t)density;
+    config.keyboard = (uint8_t)keyboard;
+    config.inputFlags = (uint8_t)keyboardHidden;
+    config.navigation = (uint8_t)navigation;
+    config.screenWidth = (uint16_t)screenWidth;
+    config.screenHeight = (uint16_t)screenHeight;
+    config.smallestScreenWidthDp = (uint16_t)smallestScreenWidthDp;
+    config.screenWidthDp = (uint16_t)screenWidthDp;
+    config.screenHeightDp = (uint16_t)screenHeightDp;
+    config.screenLayout = (uint8_t)screenLayout;
+    config.uiMode = (uint8_t)uiMode;
+    config.colorMode = (uint8_t)colorMode;
+    config.sdkVersion = (uint16_t)sdkVersion;
+    config.minorVersion = 0;
+
+    // In Java, we use a 32bit integer for screenLayout, while we only use an 8bit integer
+    // in C++. We must extract the round qualifier out of the Java screenLayout and put it
+    // into screenLayout2.
+    config.screenLayout2 =
+            (uint8_t)((screenLayout & kScreenLayoutRoundMask) >> kScreenLayoutRoundShift);
+
+    am->setConfiguration(config, locale8);
+
+    if (locale != NULL) env->ReleaseStringUTFChars(locale, locale8);
+}
+
+static jint android_content_AssetManager_getResourceIdentifier(JNIEnv* env, jobject clazz,
+                                                            jstring name,
+                                                            jstring defType,
+                                                            jstring defPackage)
+{
+    ScopedStringChars name16(env, name);
+    if (name16.get() == NULL) {
+        return 0;
+    }
+
+    AssetManager* am = assetManagerForJavaObject(env, clazz);
+    if (am == NULL) {
+        return 0;
+    }
+
+    const char16_t* defType16 = reinterpret_cast<const char16_t*>(defType)
+        ? reinterpret_cast<const char16_t*>(env->GetStringChars(defType, NULL))
+        : NULL;
+    jsize defTypeLen = defType
+        ? env->GetStringLength(defType) : 0;
+    const char16_t* defPackage16 = reinterpret_cast<const char16_t*>(defPackage)
+        ? reinterpret_cast<const char16_t*>(env->GetStringChars(defPackage,
+                                                                NULL))
+        : NULL;
+    jsize defPackageLen = defPackage
+        ? env->GetStringLength(defPackage) : 0;
+
+    jint ident = am->getResources().identifierForName(
+        reinterpret_cast<const char16_t*>(name16.get()), name16.size(),
+        defType16, defTypeLen, defPackage16, defPackageLen);
+
+    if (defPackage16) {
+        env->ReleaseStringChars(defPackage,
+                                reinterpret_cast<const jchar*>(defPackage16));
+    }
+    if (defType16) {
+        env->ReleaseStringChars(defType,
+                                reinterpret_cast<const jchar*>(defType16));
+    }
+
+    return ident;
+}
+
+static jstring android_content_AssetManager_getResourceName(JNIEnv* env, jobject clazz,
+                                                            jint resid)
+{
+    AssetManager* am = assetManagerForJavaObject(env, clazz);
+    if (am == NULL) {
+        return NULL;
+    }
+
+    ResTable::resource_name name;
+    if (!am->getResources().getResourceName(resid, true, &name)) {
+        return NULL;
+    }
+
+    String16 str;
+    if (name.package != NULL) {
+        str.setTo(name.package, name.packageLen);
+    }
+    if (name.type8 != NULL || name.type != NULL) {
+        if (str.size() > 0) {
+            char16_t div = ':';
+            str.append(&div, 1);
+        }
+        if (name.type8 != NULL) {
+            str.append(String16(name.type8, name.typeLen));
+        } else {
+            str.append(name.type, name.typeLen);
+        }
+    }
+    if (name.name8 != NULL || name.name != NULL) {
+        if (str.size() > 0) {
+            char16_t div = '/';
+            str.append(&div, 1);
+        }
+        if (name.name8 != NULL) {
+            str.append(String16(name.name8, name.nameLen));
+        } else {
+            str.append(name.name, name.nameLen);
+        }
+    }
+
+    return env->NewString((const jchar*)str.string(), str.size());
+}
+
+static jstring android_content_AssetManager_getResourcePackageName(JNIEnv* env, jobject clazz,
+                                                                   jint resid)
+{
+    AssetManager* am = assetManagerForJavaObject(env, clazz);
+    if (am == NULL) {
+        return NULL;
+    }
+
+    ResTable::resource_name name;
+    if (!am->getResources().getResourceName(resid, true, &name)) {
+        return NULL;
+    }
+
+    if (name.package != NULL) {
+        return env->NewString((const jchar*)name.package, name.packageLen);
+    }
+
+    return NULL;
+}
+
+static jstring android_content_AssetManager_getResourceTypeName(JNIEnv* env, jobject clazz,
+                                                                jint resid)
+{
+    AssetManager* am = assetManagerForJavaObject(env, clazz);
+    if (am == NULL) {
+        return NULL;
+    }
+
+    ResTable::resource_name name;
+    if (!am->getResources().getResourceName(resid, true, &name)) {
+        return NULL;
+    }
+
+    if (name.type8 != NULL) {
+        return env->NewStringUTF(name.type8);
+    }
+
+    if (name.type != NULL) {
+        return env->NewString((const jchar*)name.type, name.typeLen);
+    }
+
+    return NULL;
+}
+
+static jstring android_content_AssetManager_getResourceEntryName(JNIEnv* env, jobject clazz,
+                                                                 jint resid)
+{
+    AssetManager* am = assetManagerForJavaObject(env, clazz);
+    if (am == NULL) {
+        return NULL;
+    }
+
+    ResTable::resource_name name;
+    if (!am->getResources().getResourceName(resid, true, &name)) {
+        return NULL;
+    }
+
+    if (name.name8 != NULL) {
+        return env->NewStringUTF(name.name8);
+    }
+
+    if (name.name != NULL) {
+        return env->NewString((const jchar*)name.name, name.nameLen);
+    }
+
+    return NULL;
+}
+
+static jint android_content_AssetManager_loadResourceValue(JNIEnv* env, jobject clazz,
+                                                           jint ident,
+                                                           jshort density,
+                                                           jobject outValue,
+                                                           jboolean resolve)
+{
+    if (outValue == NULL) {
+         jniThrowNullPointerException(env, "outValue");
+         return 0;
+    }
+    AssetManager* am = assetManagerForJavaObject(env, clazz);
+    if (am == NULL) {
+        return 0;
+    }
+    const ResTable& res(am->getResources());
+
+    Res_value value;
+    ResTable_config config;
+    uint32_t typeSpecFlags;
+    ssize_t block = res.getResource(ident, &value, false, density, &typeSpecFlags, &config);
+    if (kThrowOnBadId) {
+        if (block == BAD_INDEX) {
+            jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
+            return 0;
+        }
+    }
+    uint32_t ref = ident;
+    if (resolve) {
+        block = res.resolveReference(&value, block, &ref, &typeSpecFlags, &config);
+        if (kThrowOnBadId) {
+            if (block == BAD_INDEX) {
+                jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
+                return 0;
+            }
+        }
+    }
+    if (block >= 0) {
+        return copyValue(env, outValue, &res, value, ref, block, typeSpecFlags, &config);
+    }
+
+    return static_cast<jint>(block);
+}
+
+static jint android_content_AssetManager_loadResourceBagValue(JNIEnv* env, jobject clazz,
+                                                           jint ident, jint bagEntryId,
+                                                           jobject outValue, jboolean resolve)
+{
+    AssetManager* am = assetManagerForJavaObject(env, clazz);
+    if (am == NULL) {
+        return 0;
+    }
+    const ResTable& res(am->getResources());
+
+    // Now lock down the resource object and start pulling stuff from it.
+    res.lock();
+
+    ssize_t block = -1;
+    Res_value value;
+
+    const ResTable::bag_entry* entry = NULL;
+    uint32_t typeSpecFlags;
+    ssize_t entryCount = res.getBagLocked(ident, &entry, &typeSpecFlags);
+
+    for (ssize_t i=0; i<entryCount; i++) {
+        if (((uint32_t)bagEntryId) == entry->map.name.ident) {
+            block = entry->stringBlock;
+            value = entry->map.value;
+        }
+        entry++;
+    }
+
+    res.unlock();
+
+    if (block < 0) {
+        return static_cast<jint>(block);
+    }
+
+    uint32_t ref = ident;
+    if (resolve) {
+        block = res.resolveReference(&value, block, &ref, &typeSpecFlags);
+        if (kThrowOnBadId) {
+            if (block == BAD_INDEX) {
+                jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
+                return 0;
+            }
+        }
+    }
+    if (block >= 0) {
+        return copyValue(env, outValue, &res, value, ref, block, typeSpecFlags);
+    }
+
+    return static_cast<jint>(block);
+}
+
+static jint android_content_AssetManager_getStringBlockCount(JNIEnv* env, jobject clazz)
+{
+    AssetManager* am = assetManagerForJavaObject(env, clazz);
+    if (am == NULL) {
+        return 0;
+    }
+    return am->getResources().getTableCount();
+}
+
+static jlong android_content_AssetManager_getNativeStringBlock(JNIEnv* env, jobject clazz,
+                                                           jint block)
+{
+    AssetManager* am = assetManagerForJavaObject(env, clazz);
+    if (am == NULL) {
+        return 0;
+    }
+    return reinterpret_cast<jlong>(am->getResources().getTableStringBlock(block));
+}
+
+static jstring android_content_AssetManager_getCookieName(JNIEnv* env, jobject clazz,
+                                                       jint cookie)
+{
+    AssetManager* am = assetManagerForJavaObject(env, clazz);
+    if (am == NULL) {
+        return NULL;
+    }
+    String8 name(am->getAssetPath(static_cast<int32_t>(cookie)));
+    if (name.length() == 0) {
+        jniThrowException(env, "java/lang/IndexOutOfBoundsException", "Empty cookie name");
+        return NULL;
+    }
+    jstring str = env->NewStringUTF(name.string());
+    return str;
+}
+
+static jobject android_content_AssetManager_getAssignedPackageIdentifiers(JNIEnv* env, jobject clazz)
+{
+    AssetManager* am = assetManagerForJavaObject(env, clazz);
+    if (am == NULL) {
+        return 0;
+    }
+
+    const ResTable& res = am->getResources();
+
+    jobject sparseArray = env->NewObject(gSparseArrayOffsets.classObject,
+            gSparseArrayOffsets.constructor);
+    const size_t N = res.getBasePackageCount();
+    for (size_t i = 0; i < N; i++) {
+        const String16 name = res.getBasePackageName(i);
+        env->CallVoidMethod(
+            sparseArray, gSparseArrayOffsets.put,
+            static_cast<jint>(res.getBasePackageId(i)),
+            env->NewString(reinterpret_cast<const jchar*>(name.string()),
+                           name.size()));
+    }
+    return sparseArray;
+}
+
+static jlong android_content_AssetManager_newTheme(JNIEnv* env, jobject clazz)
+{
+    AssetManager* am = assetManagerForJavaObject(env, clazz);
+    if (am == NULL) {
+        return 0;
+    }
+    return reinterpret_cast<jlong>(new ResTable::Theme(am->getResources()));
+}
+
+static void android_content_AssetManager_deleteTheme(JNIEnv* env, jobject clazz,
+                                                     jlong themeHandle)
+{
+    ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
+    delete theme;
+}
+
+static void android_content_AssetManager_applyThemeStyle(JNIEnv* env, jobject clazz,
+                                                         jlong themeHandle,
+                                                         jint styleRes,
+                                                         jboolean force)
+{
+    ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
+    theme->applyStyle(styleRes, force ? true : false);
+}
+
+static void android_content_AssetManager_copyTheme(JNIEnv* env, jobject clazz,
+                                                   jlong destHandle, jlong srcHandle)
+{
+    ResTable::Theme* dest = reinterpret_cast<ResTable::Theme*>(destHandle);
+    ResTable::Theme* src = reinterpret_cast<ResTable::Theme*>(srcHandle);
+    dest->setTo(*src);
+}
+
+static void android_content_AssetManager_clearTheme(JNIEnv* env, jobject clazz, jlong themeHandle)
+{
+    ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
+    theme->clear();
+}
+
+static jint android_content_AssetManager_loadThemeAttributeValue(
+    JNIEnv* env, jobject clazz, jlong themeHandle, jint ident, jobject outValue, jboolean resolve)
+{
+    ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
+    const ResTable& res(theme->getResTable());
+
+    Res_value value;
+    // XXX value could be different in different configs!
+    uint32_t typeSpecFlags = 0;
+    ssize_t block = theme->getAttribute(ident, &value, &typeSpecFlags);
+    uint32_t ref = 0;
+    if (resolve) {
+        block = res.resolveReference(&value, block, &ref, &typeSpecFlags);
+        if (kThrowOnBadId) {
+            if (block == BAD_INDEX) {
+                jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
+                return 0;
+            }
+        }
+    }
+    return block >= 0 ? copyValue(env, outValue, &res, value, ref, block, typeSpecFlags) : block;
+}
+
+static jint android_content_AssetManager_getThemeChangingConfigurations(JNIEnv* env, jobject clazz,
+                                                                        jlong themeHandle)
+{
+    ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
+    return theme->getChangingConfigurations();
+}
+
+static void android_content_AssetManager_dumpTheme(JNIEnv* env, jobject clazz,
+                                                   jlong themeHandle, jint pri,
+                                                   jstring tag, jstring prefix)
+{
+    ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
+    const ResTable& res(theme->getResTable());
+    (void)res;
+
+    // XXX Need to use params.
+    theme->dumpToLog();
+}
+
+static jboolean android_content_AssetManager_resolveAttrs(JNIEnv* env, jobject clazz,
+                                                          jlong themeToken,
+                                                          jint defStyleAttr,
+                                                          jint defStyleRes,
+                                                          jintArray inValues,
+                                                          jintArray attrs,
+                                                          jintArray outValues,
+                                                          jintArray outIndices)
+{
+    if (themeToken == 0) {
+        jniThrowNullPointerException(env, "theme token");
         return JNI_FALSE;
-      }
     }
-  }
-
-  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
-  Theme* theme = reinterpret_cast<Theme*>(theme_ptr);
-  CHECK(theme->GetAssetManager() == &(*assetmanager));
-  (void) assetmanager;
-
-  bool result = ResolveAttrs(
-      theme, static_cast<uint32_t>(def_style_attr), static_cast<uint32_t>(def_style_resid),
-      reinterpret_cast<uint32_t*>(values), values_len, reinterpret_cast<uint32_t*>(attrs),
-      attrs_len, reinterpret_cast<uint32_t*>(out_values), reinterpret_cast<uint32_t*>(out_indices));
-  if (out_indices != nullptr) {
-    env->ReleasePrimitiveArrayCritical(out_java_indices, out_indices, 0);
-  }
-
-  env->ReleasePrimitiveArrayCritical(out_java_values, out_values, 0);
-  if (values != nullptr) {
-    env->ReleasePrimitiveArrayCritical(java_values, values, JNI_ABORT);
-  }
-  env->ReleasePrimitiveArrayCritical(java_attrs, attrs, JNI_ABORT);
-  return result ? JNI_TRUE : JNI_FALSE;
-}
-
-static jboolean NativeRetrieveAttributes(JNIEnv* env, jclass /*clazz*/, jlong ptr,
-                                         jlong xml_parser_ptr, jintArray java_attrs,
-                                         jintArray out_java_values, jintArray out_java_indices) {
-  const jsize attrs_len = env->GetArrayLength(java_attrs);
-  const jsize out_values_len = env->GetArrayLength(out_java_values);
-  if (out_values_len < (attrs_len * STYLE_NUM_ENTRIES)) {
-    jniThrowException(env, "java/lang/IndexOutOfBoundsException", "outValues too small");
-    return JNI_FALSE;
-  }
-
-  jint* attrs = reinterpret_cast<jint*>(env->GetPrimitiveArrayCritical(java_attrs, nullptr));
-  if (attrs == nullptr) {
-    return JNI_FALSE;
-  }
-
-  jint* out_values =
-      reinterpret_cast<jint*>(env->GetPrimitiveArrayCritical(out_java_values, nullptr));
-  if (out_values == nullptr) {
-    env->ReleasePrimitiveArrayCritical(java_attrs, attrs, JNI_ABORT);
-    return JNI_FALSE;
-  }
-
-  jint* out_indices = nullptr;
-  if (out_java_indices != nullptr) {
-    jsize out_indices_len = env->GetArrayLength(out_java_indices);
-    if (out_indices_len > attrs_len) {
-      out_indices =
-          reinterpret_cast<jint*>(env->GetPrimitiveArrayCritical(out_java_indices, nullptr));
-      if (out_indices == nullptr) {
-        env->ReleasePrimitiveArrayCritical(java_attrs, attrs, JNI_ABORT);
-        env->ReleasePrimitiveArrayCritical(out_java_values, out_values, JNI_ABORT);
+    if (attrs == NULL) {
+        jniThrowNullPointerException(env, "attrs");
         return JNI_FALSE;
-      }
     }
-  }
-
-  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
-  ResXMLParser* xml_parser = reinterpret_cast<ResXMLParser*>(xml_parser_ptr);
-
-  bool result = RetrieveAttributes(assetmanager.get(), xml_parser,
-                                   reinterpret_cast<uint32_t*>(attrs), attrs_len,
-                                   reinterpret_cast<uint32_t*>(out_values),
-                                   reinterpret_cast<uint32_t*>(out_indices));
-
-  if (out_indices != nullptr) {
-    env->ReleasePrimitiveArrayCritical(out_java_indices, out_indices, 0);
-  }
-  env->ReleasePrimitiveArrayCritical(out_java_values, out_values, 0);
-  env->ReleasePrimitiveArrayCritical(java_attrs, attrs, JNI_ABORT);
-  return result ? JNI_TRUE : JNI_FALSE;
-}
-
-static jlong NativeThemeCreate(JNIEnv* /*env*/, jclass /*clazz*/, jlong ptr) {
-  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
-  return reinterpret_cast<jlong>(assetmanager->NewTheme().release());
-}
-
-static void NativeThemeDestroy(JNIEnv* /*env*/, jclass /*clazz*/, jlong theme_ptr) {
-  delete reinterpret_cast<Theme*>(theme_ptr);
-}
-
-static void NativeThemeApplyStyle(JNIEnv* env, jclass /*clazz*/, jlong ptr, jlong theme_ptr,
-                                  jint resid, jboolean force) {
-  // AssetManager is accessed via the theme, so grab an explicit lock here.
-  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
-  Theme* theme = reinterpret_cast<Theme*>(theme_ptr);
-  CHECK(theme->GetAssetManager() == &(*assetmanager));
-  (void) assetmanager;
-  theme->ApplyStyle(static_cast<uint32_t>(resid), force);
-
-  // TODO(adamlesinski): Consider surfacing exception when result is failure.
-  // CTS currently expects no exceptions from this method.
-  // std::string error_msg = StringPrintf("Failed to apply style 0x%08x to theme", resid);
-  // jniThrowException(env, "java/lang/IllegalArgumentException", error_msg.c_str());
-}
-
-static void NativeThemeCopy(JNIEnv* env, jclass /*clazz*/, jlong dst_theme_ptr,
-                            jlong src_theme_ptr) {
-  Theme* dst_theme = reinterpret_cast<Theme*>(dst_theme_ptr);
-  Theme* src_theme = reinterpret_cast<Theme*>(src_theme_ptr);
-  if (!dst_theme->SetTo(*src_theme)) {
-    jniThrowException(env, "java/lang/IllegalArgumentException",
-                      "Themes are from different AssetManagers");
-  }
-}
-
-static void NativeThemeClear(JNIEnv* /*env*/, jclass /*clazz*/, jlong theme_ptr) {
-  reinterpret_cast<Theme*>(theme_ptr)->Clear();
-}
-
-static jint NativeThemeGetAttributeValue(JNIEnv* env, jclass /*clazz*/, jlong ptr, jlong theme_ptr,
-                                         jint resid, jobject typed_value,
-                                         jboolean resolve_references) {
-  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
-  Theme* theme = reinterpret_cast<Theme*>(theme_ptr);
-  CHECK(theme->GetAssetManager() == &(*assetmanager));
-  (void) assetmanager;
-
-  Res_value value;
-  uint32_t flags;
-  ApkAssetsCookie cookie = theme->GetAttribute(static_cast<uint32_t>(resid), &value, &flags);
-  if (cookie == kInvalidCookie) {
-    return ApkAssetsCookieToJavaCookie(kInvalidCookie);
-  }
-
-  uint32_t ref = 0u;
-  if (resolve_references) {
-    ResTable_config selected_config;
-    cookie =
-        theme->GetAssetManager()->ResolveReference(cookie, &value, &selected_config, &flags, &ref);
-    if (cookie == kInvalidCookie) {
-      return ApkAssetsCookieToJavaCookie(kInvalidCookie);
+    if (outValues == NULL) {
+        jniThrowNullPointerException(env, "out values");
+        return JNI_FALSE;
     }
-  }
-  return CopyValue(env, cookie, value, ref, flags, nullptr, typed_value);
+
+    const jsize NI = env->GetArrayLength(attrs);
+    const jsize NV = env->GetArrayLength(outValues);
+    if (NV < (NI*STYLE_NUM_ENTRIES)) {
+        jniThrowException(env, "java/lang/IndexOutOfBoundsException", "out values too small");
+        return JNI_FALSE;
+    }
+
+    jint* src = (jint*)env->GetPrimitiveArrayCritical(attrs, 0);
+    if (src == NULL) {
+        return JNI_FALSE;
+    }
+
+    jint* srcValues = (jint*)env->GetPrimitiveArrayCritical(inValues, 0);
+    const jsize NSV = srcValues == NULL ? 0 : env->GetArrayLength(inValues);
+
+    jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
+    if (baseDest == NULL) {
+        env->ReleasePrimitiveArrayCritical(attrs, src, 0);
+        return JNI_FALSE;
+    }
+
+    jint* indices = NULL;
+    if (outIndices != NULL) {
+        if (env->GetArrayLength(outIndices) > NI) {
+            indices = (jint*)env->GetPrimitiveArrayCritical(outIndices, 0);
+        }
+    }
+
+    ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeToken);
+    bool result = ResolveAttrs(theme, defStyleAttr, defStyleRes,
+                               (uint32_t*) srcValues, NSV,
+                               (uint32_t*) src, NI,
+                               (uint32_t*) baseDest,
+                               (uint32_t*) indices);
+
+    if (indices != NULL) {
+        env->ReleasePrimitiveArrayCritical(outIndices, indices, 0);
+    }
+    env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
+    env->ReleasePrimitiveArrayCritical(inValues, srcValues, 0);
+    env->ReleasePrimitiveArrayCritical(attrs, src, 0);
+    return result ? JNI_TRUE : JNI_FALSE;
 }
 
-static void NativeThemeDump(JNIEnv* /*env*/, jclass /*clazz*/, jlong ptr, jlong theme_ptr,
-                            jint priority, jstring tag, jstring prefix) {
-  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
-  Theme* theme = reinterpret_cast<Theme*>(theme_ptr);
-  CHECK(theme->GetAssetManager() == &(*assetmanager));
-  (void) assetmanager;
-  (void) theme;
-  (void) priority;
-  (void) tag;
-  (void) prefix;
+static void android_content_AssetManager_applyStyle(JNIEnv* env, jobject, jlong themeToken,
+        jint defStyleAttr, jint defStyleRes, jlong xmlParserToken, jintArray attrsObj, jint length,
+        jlong outValuesAddress, jlong outIndicesAddress) {
+    jint* attrs = env->GetIntArrayElements(attrsObj, 0);
+    ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeToken);
+    ResXMLParser* xmlParser = reinterpret_cast<ResXMLParser*>(xmlParserToken);
+    uint32_t* outValues = reinterpret_cast<uint32_t*>(static_cast<uintptr_t>(outValuesAddress));
+    uint32_t* outIndices = reinterpret_cast<uint32_t*>(static_cast<uintptr_t>(outIndicesAddress));
+    ApplyStyle(theme, xmlParser, defStyleAttr, defStyleRes,
+            reinterpret_cast<const uint32_t*>(attrs), length, outValues, outIndices);
+    env->ReleaseIntArrayElements(attrsObj, attrs, JNI_ABORT);
 }
 
-static jint NativeThemeGetChangingConfigurations(JNIEnv* /*env*/, jclass /*clazz*/,
-                                                 jlong theme_ptr) {
-  Theme* theme = reinterpret_cast<Theme*>(theme_ptr);
-  return static_cast<jint>(theme->GetChangingConfigurations());
+static jboolean android_content_AssetManager_retrieveAttributes(JNIEnv* env, jobject clazz,
+                                                        jlong xmlParserToken,
+                                                        jintArray attrs,
+                                                        jintArray outValues,
+                                                        jintArray outIndices)
+{
+    if (xmlParserToken == 0) {
+        jniThrowNullPointerException(env, "xmlParserToken");
+        return JNI_FALSE;
+    }
+    if (attrs == NULL) {
+        jniThrowNullPointerException(env, "attrs");
+        return JNI_FALSE;
+    }
+    if (outValues == NULL) {
+        jniThrowNullPointerException(env, "out values");
+        return JNI_FALSE;
+    }
+
+    AssetManager* am = assetManagerForJavaObject(env, clazz);
+    if (am == NULL) {
+        return JNI_FALSE;
+    }
+    const ResTable& res(am->getResources());
+    ResXMLParser* xmlParser = (ResXMLParser*)xmlParserToken;
+
+    const jsize NI = env->GetArrayLength(attrs);
+    const jsize NV = env->GetArrayLength(outValues);
+    if (NV < (NI*STYLE_NUM_ENTRIES)) {
+        jniThrowException(env, "java/lang/IndexOutOfBoundsException", "out values too small");
+        return JNI_FALSE;
+    }
+
+    jint* src = (jint*)env->GetPrimitiveArrayCritical(attrs, 0);
+    if (src == NULL) {
+        return JNI_FALSE;
+    }
+
+    jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
+    if (baseDest == NULL) {
+        env->ReleasePrimitiveArrayCritical(attrs, src, 0);
+        return JNI_FALSE;
+    }
+
+    jint* indices = NULL;
+    if (outIndices != NULL) {
+        if (env->GetArrayLength(outIndices) > NI) {
+            indices = (jint*)env->GetPrimitiveArrayCritical(outIndices, 0);
+        }
+    }
+
+    bool result = RetrieveAttributes(&res, xmlParser,
+                                     (uint32_t*) src, NI,
+                                     (uint32_t*) baseDest,
+                                     (uint32_t*) indices);
+
+    if (indices != NULL) {
+        env->ReleasePrimitiveArrayCritical(outIndices, indices, 0);
+    }
+    env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
+    env->ReleasePrimitiveArrayCritical(attrs, src, 0);
+    return result ? JNI_TRUE : JNI_FALSE;
 }
 
-static void NativeAssetDestroy(JNIEnv* /*env*/, jclass /*clazz*/, jlong asset_ptr) {
-  delete reinterpret_cast<Asset*>(asset_ptr);
+static jint android_content_AssetManager_getArraySize(JNIEnv* env, jobject clazz,
+                                                       jint id)
+{
+    AssetManager* am = assetManagerForJavaObject(env, clazz);
+    if (am == NULL) {
+        return 0;
+    }
+    const ResTable& res(am->getResources());
+
+    res.lock();
+    const ResTable::bag_entry* defStyleEnt = NULL;
+    ssize_t bagOff = res.getBagLocked(id, &defStyleEnt);
+    res.unlock();
+
+    return static_cast<jint>(bagOff);
 }
 
-static jint NativeAssetReadChar(JNIEnv* /*env*/, jclass /*clazz*/, jlong asset_ptr) {
-  Asset* asset = reinterpret_cast<Asset*>(asset_ptr);
-  uint8_t b;
-  ssize_t res = asset->read(&b, sizeof(b));
-  return res == sizeof(b) ? static_cast<jint>(b) : -1;
+static jint android_content_AssetManager_retrieveArray(JNIEnv* env, jobject clazz,
+                                                        jint id,
+                                                        jintArray outValues)
+{
+    if (outValues == NULL) {
+        jniThrowNullPointerException(env, "out values");
+        return JNI_FALSE;
+    }
+
+    AssetManager* am = assetManagerForJavaObject(env, clazz);
+    if (am == NULL) {
+        return JNI_FALSE;
+    }
+    const ResTable& res(am->getResources());
+    ResTable_config config;
+    Res_value value;
+    ssize_t block;
+
+    const jsize NV = env->GetArrayLength(outValues);
+
+    jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
+    jint* dest = baseDest;
+    if (dest == NULL) {
+        jniThrowException(env, "java/lang/OutOfMemoryError", "");
+        return JNI_FALSE;
+    }
+
+    // Now lock down the resource object and start pulling stuff from it.
+    res.lock();
+
+    const ResTable::bag_entry* arrayEnt = NULL;
+    uint32_t arrayTypeSetFlags = 0;
+    ssize_t bagOff = res.getBagLocked(id, &arrayEnt, &arrayTypeSetFlags);
+    const ResTable::bag_entry* endArrayEnt = arrayEnt +
+        (bagOff >= 0 ? bagOff : 0);
+
+    int i = 0;
+    uint32_t typeSetFlags;
+    while (i < NV && arrayEnt < endArrayEnt) {
+        block = arrayEnt->stringBlock;
+        typeSetFlags = arrayTypeSetFlags;
+        config.density = 0;
+        value = arrayEnt->map.value;
+
+        uint32_t resid = 0;
+        if (value.dataType != Res_value::TYPE_NULL) {
+            // Take care of resolving the found resource to its final value.
+            //printf("Resolving attribute reference\n");
+            ssize_t newBlock = res.resolveReference(&value, block, &resid,
+                    &typeSetFlags, &config);
+            if (kThrowOnBadId) {
+                if (newBlock == BAD_INDEX) {
+                    jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
+                    return JNI_FALSE;
+                }
+            }
+            if (newBlock >= 0) block = newBlock;
+        }
+
+        // Deal with the special @null value -- it turns back to TYPE_NULL.
+        if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
+            value.dataType = Res_value::TYPE_NULL;
+            value.data = Res_value::DATA_NULL_UNDEFINED;
+        }
+
+        //printf("Attribute 0x%08x: final type=0x%x, data=0x%08x\n", curIdent, value.dataType, value.data);
+
+        // Write the final value back to Java.
+        dest[STYLE_TYPE] = value.dataType;
+        dest[STYLE_DATA] = value.data;
+        dest[STYLE_ASSET_COOKIE] = reinterpret_cast<jint>(res.getTableCookie(block));
+        dest[STYLE_RESOURCE_ID] = resid;
+        dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
+        dest[STYLE_DENSITY] = config.density;
+        dest += STYLE_NUM_ENTRIES;
+        i+= STYLE_NUM_ENTRIES;
+        arrayEnt++;
+    }
+
+    i /= STYLE_NUM_ENTRIES;
+
+    res.unlock();
+
+    env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
+
+    return i;
 }
 
-static jint NativeAssetRead(JNIEnv* env, jclass /*clazz*/, jlong asset_ptr, jbyteArray java_buffer,
-                            jint offset, jint len) {
-  if (len == 0) {
-    return 0;
-  }
+static jlong android_content_AssetManager_openXmlAssetNative(JNIEnv* env, jobject clazz,
+                                                         jint cookie,
+                                                         jstring fileName)
+{
+    AssetManager* am = assetManagerForJavaObject(env, clazz);
+    if (am == NULL) {
+        return 0;
+    }
 
-  jsize buffer_len = env->GetArrayLength(java_buffer);
-  if (offset < 0 || offset >= buffer_len || len < 0 || len > buffer_len ||
-      offset > buffer_len - len) {
-    jniThrowException(env, "java/lang/IndexOutOfBoundsException", "");
-    return -1;
-  }
+    ALOGV("openXmlAsset in %p (Java object %p)\n", am, clazz);
 
-  ScopedByteArrayRW byte_array(env, java_buffer);
-  if (byte_array.get() == nullptr) {
-    return -1;
-  }
+    ScopedUtfChars fileName8(env, fileName);
+    if (fileName8.c_str() == NULL) {
+        return 0;
+    }
 
-  Asset* asset = reinterpret_cast<Asset*>(asset_ptr);
-  ssize_t res = asset->read(byte_array.get() + offset, len);
-  if (res < 0) {
-    jniThrowException(env, "java/io/IOException", "");
-    return -1;
-  }
-  return res > 0 ? static_cast<jint>(res) : -1;
+    int32_t assetCookie = static_cast<int32_t>(cookie);
+    Asset* a = assetCookie
+        ? am->openNonAsset(assetCookie, fileName8.c_str(), Asset::ACCESS_BUFFER)
+        : am->openNonAsset(fileName8.c_str(), Asset::ACCESS_BUFFER, &assetCookie);
+
+    if (a == NULL) {
+        jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
+        return 0;
+    }
+
+    const DynamicRefTable* dynamicRefTable =
+            am->getResources().getDynamicRefTableForCookie(assetCookie);
+    ResXMLTree* block = new ResXMLTree(dynamicRefTable);
+    status_t err = block->setTo(a->getBuffer(true), a->getLength(), true);
+    a->close();
+    delete a;
+
+    if (err != NO_ERROR) {
+        jniThrowException(env, "java/io/FileNotFoundException", "Corrupt XML binary file");
+        return 0;
+    }
+
+    return reinterpret_cast<jlong>(block);
 }
 
-static jlong NativeAssetSeek(JNIEnv* env, jclass /*clazz*/, jlong asset_ptr, jlong offset,
-                             jint whence) {
-  Asset* asset = reinterpret_cast<Asset*>(asset_ptr);
-  return static_cast<jlong>(asset->seek(
-      static_cast<off64_t>(offset), (whence > 0 ? SEEK_END : (whence < 0 ? SEEK_SET : SEEK_CUR))));
+static jintArray android_content_AssetManager_getArrayStringInfo(JNIEnv* env, jobject clazz,
+                                                                 jint arrayResId)
+{
+    AssetManager* am = assetManagerForJavaObject(env, clazz);
+    if (am == NULL) {
+        return NULL;
+    }
+    const ResTable& res(am->getResources());
+
+    const ResTable::bag_entry* startOfBag;
+    const ssize_t N = res.lockBag(arrayResId, &startOfBag);
+    if (N < 0) {
+        return NULL;
+    }
+
+    jintArray array = env->NewIntArray(N * 2);
+    if (array == NULL) {
+        res.unlockBag(startOfBag);
+        return NULL;
+    }
+
+    Res_value value;
+    const ResTable::bag_entry* bag = startOfBag;
+    for (size_t i = 0, j = 0; ((ssize_t)i)<N; i++, bag++) {
+        jint stringIndex = -1;
+        jint stringBlock = 0;
+        value = bag->map.value;
+
+        // Take care of resolving the found resource to its final value.
+        stringBlock = res.resolveReference(&value, bag->stringBlock, NULL);
+        if (value.dataType == Res_value::TYPE_STRING) {
+            stringIndex = value.data;
+        }
+
+        if (kThrowOnBadId) {
+            if (stringBlock == BAD_INDEX) {
+                jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
+                return array;
+            }
+        }
+
+        //todo: It might be faster to allocate a C array to contain
+        //      the blocknums and indices, put them in there and then
+        //      do just one SetIntArrayRegion()
+        env->SetIntArrayRegion(array, j, 1, &stringBlock);
+        env->SetIntArrayRegion(array, j + 1, 1, &stringIndex);
+        j = j + 2;
+    }
+    res.unlockBag(startOfBag);
+    return array;
 }
 
-static jlong NativeAssetGetLength(JNIEnv* /*env*/, jclass /*clazz*/, jlong asset_ptr) {
-  Asset* asset = reinterpret_cast<Asset*>(asset_ptr);
-  return static_cast<jlong>(asset->getLength());
+static jobjectArray android_content_AssetManager_getArrayStringResource(JNIEnv* env, jobject clazz,
+                                                                        jint arrayResId)
+{
+    AssetManager* am = assetManagerForJavaObject(env, clazz);
+    if (am == NULL) {
+        return NULL;
+    }
+    const ResTable& res(am->getResources());
+
+    const ResTable::bag_entry* startOfBag;
+    const ssize_t N = res.lockBag(arrayResId, &startOfBag);
+    if (N < 0) {
+        return NULL;
+    }
+
+    jobjectArray array = env->NewObjectArray(N, g_stringClass, NULL);
+    if (env->ExceptionCheck()) {
+        res.unlockBag(startOfBag);
+        return NULL;
+    }
+
+    Res_value value;
+    const ResTable::bag_entry* bag = startOfBag;
+    size_t strLen = 0;
+    for (size_t i=0; ((ssize_t)i)<N; i++, bag++) {
+        value = bag->map.value;
+        jstring str = NULL;
+
+        // Take care of resolving the found resource to its final value.
+        ssize_t block = res.resolveReference(&value, bag->stringBlock, NULL);
+        if (kThrowOnBadId) {
+            if (block == BAD_INDEX) {
+                jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
+                return array;
+            }
+        }
+        if (value.dataType == Res_value::TYPE_STRING) {
+            const ResStringPool* pool = res.getTableStringBlock(block);
+            const char* str8 = pool->string8At(value.data, &strLen);
+            if (str8 != NULL) {
+                str = env->NewStringUTF(str8);
+            } else {
+                const char16_t* str16 = pool->stringAt(value.data, &strLen);
+                str = env->NewString(reinterpret_cast<const jchar*>(str16),
+                                     strLen);
+            }
+
+            // If one of our NewString{UTF} calls failed due to memory, an
+            // exception will be pending.
+            if (env->ExceptionCheck()) {
+                res.unlockBag(startOfBag);
+                return NULL;
+            }
+
+            env->SetObjectArrayElement(array, i, str);
+
+            // str is not NULL at that point, otherwise ExceptionCheck would have been true.
+            // If we have a large amount of strings in our array, we might
+            // overflow the local reference table of the VM.
+            env->DeleteLocalRef(str);
+        }
+    }
+    res.unlockBag(startOfBag);
+    return array;
 }
 
-static jlong NativeAssetGetRemainingLength(JNIEnv* /*env*/, jclass /*clazz*/, jlong asset_ptr) {
-  Asset* asset = reinterpret_cast<Asset*>(asset_ptr);
-  return static_cast<jlong>(asset->getRemainingLength());
+static jintArray android_content_AssetManager_getArrayIntResource(JNIEnv* env, jobject clazz,
+                                                                        jint arrayResId)
+{
+    AssetManager* am = assetManagerForJavaObject(env, clazz);
+    if (am == NULL) {
+        return NULL;
+    }
+    const ResTable& res(am->getResources());
+
+    const ResTable::bag_entry* startOfBag;
+    const ssize_t N = res.lockBag(arrayResId, &startOfBag);
+    if (N < 0) {
+        return NULL;
+    }
+
+    jintArray array = env->NewIntArray(N);
+    if (array == NULL) {
+        res.unlockBag(startOfBag);
+        return NULL;
+    }
+
+    Res_value value;
+    const ResTable::bag_entry* bag = startOfBag;
+    for (size_t i=0; ((ssize_t)i)<N; i++, bag++) {
+        value = bag->map.value;
+
+        // Take care of resolving the found resource to its final value.
+        ssize_t block = res.resolveReference(&value, bag->stringBlock, NULL);
+        if (kThrowOnBadId) {
+            if (block == BAD_INDEX) {
+                jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
+                return array;
+            }
+        }
+        if (value.dataType >= Res_value::TYPE_FIRST_INT
+                && value.dataType <= Res_value::TYPE_LAST_INT) {
+            int intVal = value.data;
+            env->SetIntArrayRegion(array, i, 1, &intVal);
+        }
+    }
+    res.unlockBag(startOfBag);
+    return array;
+}
+
+static jintArray android_content_AssetManager_getStyleAttributes(JNIEnv* env, jobject clazz,
+                                                                 jint styleId)
+{
+    AssetManager* am = assetManagerForJavaObject(env, clazz);
+    if (am == NULL) {
+        return NULL;
+    }
+    const ResTable& res(am->getResources());
+
+    const ResTable::bag_entry* startOfBag;
+    const ssize_t N = res.lockBag(styleId, &startOfBag);
+    if (N < 0) {
+        return NULL;
+    }
+
+    jintArray array = env->NewIntArray(N);
+    if (array == NULL) {
+        res.unlockBag(startOfBag);
+        return NULL;
+    }
+
+    const ResTable::bag_entry* bag = startOfBag;
+    for (size_t i=0; ((ssize_t)i)<N; i++, bag++) {
+        int resourceId = bag->map.name.ident;
+        env->SetIntArrayRegion(array, i, 1, &resourceId);
+    }
+    res.unlockBag(startOfBag);
+    return array;
+}
+
+static void android_content_AssetManager_init(JNIEnv* env, jobject clazz, jboolean isSystem)
+{
+    if (isSystem) {
+        verifySystemIdmaps();
+    }
+    AssetManager* am = new AssetManager();
+    if (am == NULL) {
+        jniThrowException(env, "java/lang/OutOfMemoryError", "");
+        return;
+    }
+
+    am->addDefaultAssets();
+
+    ALOGV("Created AssetManager %p for Java object %p\n", am, clazz);
+    env->SetLongField(clazz, gAssetManagerOffsets.mObject, reinterpret_cast<jlong>(am));
+}
+
+static void android_content_AssetManager_destroy(JNIEnv* env, jobject clazz)
+{
+    AssetManager* am = (AssetManager*)
+        (env->GetLongField(clazz, gAssetManagerOffsets.mObject));
+    ALOGV("Destroying AssetManager %p for Java object %p\n", am, clazz);
+    if (am != NULL) {
+        delete am;
+        env->SetLongField(clazz, gAssetManagerOffsets.mObject, 0);
+    }
+}
+
+static jint android_content_AssetManager_getGlobalAssetCount(JNIEnv* env, jobject clazz)
+{
+    return Asset::getGlobalCount();
+}
+
+static jobject android_content_AssetManager_getAssetAllocations(JNIEnv* env, jobject clazz)
+{
+    String8 alloc = Asset::getAssetAllocations();
+    if (alloc.length() <= 0) {
+        return NULL;
+    }
+
+    jstring str = env->NewStringUTF(alloc.string());
+    return str;
+}
+
+static jint android_content_AssetManager_getGlobalAssetManagerCount(JNIEnv* env, jobject clazz)
+{
+    return AssetManager::getGlobalCount();
 }
 
 // ----------------------------------------------------------------------------
 
-// JNI registration.
+/*
+ * JNI registration.
+ */
 static const JNINativeMethod gAssetManagerMethods[] = {
-    // AssetManager setup methods.
-    {"nativeCreate", "()J", (void*)NativeCreate},
-    {"nativeDestroy", "(J)V", (void*)NativeDestroy},
-    {"nativeSetApkAssets", "(J[Landroid/content/res/ApkAssets;Z)V", (void*)NativeSetApkAssets},
-    {"nativeSetConfiguration", "(JIILjava/lang/String;IIIIIIIIIIIIIII)V",
-     (void*)NativeSetConfiguration},
-    {"nativeGetAssignedPackageIdentifiers", "(J)Landroid/util/SparseArray;",
-     (void*)NativeGetAssignedPackageIdentifiers},
+    /* name, signature, funcPtr */
 
-    // AssetManager file methods.
-    {"nativeList", "(JLjava/lang/String;)[Ljava/lang/String;", (void*)NativeList},
-    {"nativeOpenAsset", "(JLjava/lang/String;I)J", (void*)NativeOpenAsset},
-    {"nativeOpenAssetFd", "(JLjava/lang/String;[J)Landroid/os/ParcelFileDescriptor;",
-     (void*)NativeOpenAssetFd},
-    {"nativeOpenNonAsset", "(JILjava/lang/String;I)J", (void*)NativeOpenNonAsset},
-    {"nativeOpenNonAssetFd", "(JILjava/lang/String;[J)Landroid/os/ParcelFileDescriptor;",
-     (void*)NativeOpenNonAssetFd},
-    {"nativeOpenXmlAsset", "(JILjava/lang/String;)J", (void*)NativeOpenXmlAsset},
+    // Basic asset stuff.
+    { "openAsset",      "(Ljava/lang/String;I)J",
+        (void*) android_content_AssetManager_openAsset },
+    { "openAssetFd",      "(Ljava/lang/String;[J)Landroid/os/ParcelFileDescriptor;",
+        (void*) android_content_AssetManager_openAssetFd },
+    { "openNonAssetNative", "(ILjava/lang/String;I)J",
+        (void*) android_content_AssetManager_openNonAssetNative },
+    { "openNonAssetFdNative", "(ILjava/lang/String;[J)Landroid/os/ParcelFileDescriptor;",
+        (void*) android_content_AssetManager_openNonAssetFdNative },
+    { "list",           "(Ljava/lang/String;)[Ljava/lang/String;",
+        (void*) android_content_AssetManager_list },
+    { "destroyAsset",   "(J)V",
+        (void*) android_content_AssetManager_destroyAsset },
+    { "readAssetChar",  "(J)I",
+        (void*) android_content_AssetManager_readAssetChar },
+    { "readAsset",      "(J[BII)I",
+        (void*) android_content_AssetManager_readAsset },
+    { "seekAsset",      "(JJI)J",
+        (void*) android_content_AssetManager_seekAsset },
+    { "getAssetLength", "(J)J",
+        (void*) android_content_AssetManager_getAssetLength },
+    { "getAssetRemainingLength", "(J)J",
+        (void*) android_content_AssetManager_getAssetRemainingLength },
+    { "addAssetPathNative", "(Ljava/lang/String;Z)I",
+        (void*) android_content_AssetManager_addAssetPath },
+    { "addAssetFdNative", "(Ljava/io/FileDescriptor;Ljava/lang/String;Z)I",
+        (void*) android_content_AssetManager_addAssetFd },
+    { "addOverlayPathNative",   "(Ljava/lang/String;)I",
+        (void*) android_content_AssetManager_addOverlayPath },
+    { "isUpToDate",     "()Z",
+        (void*) android_content_AssetManager_isUpToDate },
 
-    // AssetManager resource methods.
-    {"nativeGetResourceValue", "(JISLandroid/util/TypedValue;Z)I", (void*)NativeGetResourceValue},
-    {"nativeGetResourceBagValue", "(JIILandroid/util/TypedValue;)I",
-     (void*)NativeGetResourceBagValue},
-    {"nativeGetStyleAttributes", "(JI)[I", (void*)NativeGetStyleAttributes},
-    {"nativeGetResourceStringArray", "(JI)[Ljava/lang/String;",
-     (void*)NativeGetResourceStringArray},
-    {"nativeGetResourceStringArrayInfo", "(JI)[I", (void*)NativeGetResourceStringArrayInfo},
-    {"nativeGetResourceIntArray", "(JI)[I", (void*)NativeGetResourceIntArray},
-    {"nativeGetResourceArraySize", "(JI)I", (void*)NativeGetResourceArraySize},
-    {"nativeGetResourceArray", "(JI[I)I", (void*)NativeGetResourceArray},
+    // Resources.
+    { "getLocales",      "()[Ljava/lang/String;",
+        (void*) android_content_AssetManager_getLocales },
+    { "getNonSystemLocales", "()[Ljava/lang/String;",
+        (void*) android_content_AssetManager_getNonSystemLocales },
+    { "getSizeConfigurations", "()[Landroid/content/res/Configuration;",
+        (void*) android_content_AssetManager_getSizeConfigurations },
+    { "setConfiguration", "(IILjava/lang/String;IIIIIIIIIIIIIII)V",
+        (void*) android_content_AssetManager_setConfiguration },
+    { "getResourceIdentifier","(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I",
+        (void*) android_content_AssetManager_getResourceIdentifier },
+    { "getResourceName","(I)Ljava/lang/String;",
+        (void*) android_content_AssetManager_getResourceName },
+    { "getResourcePackageName","(I)Ljava/lang/String;",
+        (void*) android_content_AssetManager_getResourcePackageName },
+    { "getResourceTypeName","(I)Ljava/lang/String;",
+        (void*) android_content_AssetManager_getResourceTypeName },
+    { "getResourceEntryName","(I)Ljava/lang/String;",
+        (void*) android_content_AssetManager_getResourceEntryName },
+    { "loadResourceValue","(ISLandroid/util/TypedValue;Z)I",
+        (void*) android_content_AssetManager_loadResourceValue },
+    { "loadResourceBagValue","(IILandroid/util/TypedValue;Z)I",
+        (void*) android_content_AssetManager_loadResourceBagValue },
+    { "getStringBlockCount","()I",
+        (void*) android_content_AssetManager_getStringBlockCount },
+    { "getNativeStringBlock","(I)J",
+        (void*) android_content_AssetManager_getNativeStringBlock },
+    { "getCookieName","(I)Ljava/lang/String;",
+        (void*) android_content_AssetManager_getCookieName },
+    { "getAssignedPackageIdentifiers","()Landroid/util/SparseArray;",
+        (void*) android_content_AssetManager_getAssignedPackageIdentifiers },
 
-    // AssetManager resource name/ID methods.
-    {"nativeGetResourceIdentifier", "(JLjava/lang/String;Ljava/lang/String;Ljava/lang/String;)I",
-     (void*)NativeGetResourceIdentifier},
-    {"nativeGetResourceName", "(JI)Ljava/lang/String;", (void*)NativeGetResourceName},
-    {"nativeGetResourcePackageName", "(JI)Ljava/lang/String;", (void*)NativeGetResourcePackageName},
-    {"nativeGetResourceTypeName", "(JI)Ljava/lang/String;", (void*)NativeGetResourceTypeName},
-    {"nativeGetResourceEntryName", "(JI)Ljava/lang/String;", (void*)NativeGetResourceEntryName},
-    {"nativeGetLocales", "(JZ)[Ljava/lang/String;", (void*)NativeGetLocales},
-    {"nativeGetSizeConfigurations", "(J)[Landroid/content/res/Configuration;",
-     (void*)NativeGetSizeConfigurations},
+    // Themes.
+    { "newTheme", "()J",
+        (void*) android_content_AssetManager_newTheme },
+    { "deleteTheme", "(J)V",
+        (void*) android_content_AssetManager_deleteTheme },
+    { "applyThemeStyle", "(JIZ)V",
+        (void*) android_content_AssetManager_applyThemeStyle },
+    { "copyTheme", "(JJ)V",
+        (void*) android_content_AssetManager_copyTheme },
+    { "clearTheme", "(J)V",
+        (void*) android_content_AssetManager_clearTheme },
+    { "loadThemeAttributeValue", "(JILandroid/util/TypedValue;Z)I",
+        (void*) android_content_AssetManager_loadThemeAttributeValue },
+    { "getThemeChangingConfigurations", "(J)I",
+        (void*) android_content_AssetManager_getThemeChangingConfigurations },
+    { "dumpTheme", "(JILjava/lang/String;Ljava/lang/String;)V",
+        (void*) android_content_AssetManager_dumpTheme },
+    { "applyStyle","(JIIJ[IIJJ)V",
+        (void*) android_content_AssetManager_applyStyle },
+    { "resolveAttrs","(JII[I[I[I[I)Z",
+        (void*) android_content_AssetManager_resolveAttrs },
+    { "retrieveAttributes","(J[I[I[I)Z",
+        (void*) android_content_AssetManager_retrieveAttributes },
+    { "getArraySize","(I)I",
+        (void*) android_content_AssetManager_getArraySize },
+    { "retrieveArray","(I[I)I",
+        (void*) android_content_AssetManager_retrieveArray },
 
-    // Style attribute related methods.
-    {"nativeApplyStyle", "(JJIIJ[IJJ)V", (void*)NativeApplyStyle},
-    {"nativeResolveAttrs", "(JJII[I[I[I[I)Z", (void*)NativeResolveAttrs},
-    {"nativeRetrieveAttributes", "(JJ[I[I[I)Z", (void*)NativeRetrieveAttributes},
+    // XML files.
+    { "openXmlAssetNative", "(ILjava/lang/String;)J",
+        (void*) android_content_AssetManager_openXmlAssetNative },
 
-    // Theme related methods.
-    {"nativeThemeCreate", "(J)J", (void*)NativeThemeCreate},
-    {"nativeThemeDestroy", "(J)V", (void*)NativeThemeDestroy},
-    {"nativeThemeApplyStyle", "(JJIZ)V", (void*)NativeThemeApplyStyle},
-    {"nativeThemeCopy", "(JJ)V", (void*)NativeThemeCopy},
-    {"nativeThemeClear", "(J)V", (void*)NativeThemeClear},
-    {"nativeThemeGetAttributeValue", "(JJILandroid/util/TypedValue;Z)I",
-     (void*)NativeThemeGetAttributeValue},
-    {"nativeThemeDump", "(JJILjava/lang/String;Ljava/lang/String;)V", (void*)NativeThemeDump},
-    {"nativeThemeGetChangingConfigurations", "(J)I", (void*)NativeThemeGetChangingConfigurations},
+    // Arrays.
+    { "getArrayStringResource","(I)[Ljava/lang/String;",
+        (void*) android_content_AssetManager_getArrayStringResource },
+    { "getArrayStringInfo","(I)[I",
+        (void*) android_content_AssetManager_getArrayStringInfo },
+    { "getArrayIntResource","(I)[I",
+        (void*) android_content_AssetManager_getArrayIntResource },
+    { "getStyleAttributes","(I)[I",
+        (void*) android_content_AssetManager_getStyleAttributes },
 
-    // AssetInputStream methods.
-    {"nativeAssetDestroy", "(J)V", (void*)NativeAssetDestroy},
-    {"nativeAssetReadChar", "(J)I", (void*)NativeAssetReadChar},
-    {"nativeAssetRead", "(J[BII)I", (void*)NativeAssetRead},
-    {"nativeAssetSeek", "(JJI)J", (void*)NativeAssetSeek},
-    {"nativeAssetGetLength", "(J)J", (void*)NativeAssetGetLength},
-    {"nativeAssetGetRemainingLength", "(J)J", (void*)NativeAssetGetRemainingLength},
-
-    // System/idmap related methods.
-    {"nativeVerifySystemIdmaps", "()V", (void*)NativeVerifySystemIdmaps},
-
-    // Global management/debug methods.
-    {"getGlobalAssetCount", "()I", (void*)NativeGetGlobalAssetCount},
-    {"getAssetAllocations", "()Ljava/lang/String;", (void*)NativeGetAssetAllocations},
-    {"getGlobalAssetManagerCount", "()I", (void*)NativeGetGlobalAssetManagerCount},
+    // Bookkeeping.
+    { "init",           "(Z)V",
+        (void*) android_content_AssetManager_init },
+    { "destroy",        "()V",
+        (void*) android_content_AssetManager_destroy },
+    { "getGlobalAssetCount", "()I",
+        (void*) android_content_AssetManager_getGlobalAssetCount },
+    { "getAssetAllocations", "()Ljava/lang/String;",
+        (void*) android_content_AssetManager_getAssetAllocations },
+    { "getGlobalAssetManagerCount", "()I",
+        (void*) android_content_AssetManager_getGlobalAssetManagerCount },
 };
 
-int register_android_content_AssetManager(JNIEnv* env) {
-  jclass apk_assets_class = FindClassOrDie(env, "android/content/res/ApkAssets");
-  gApkAssetsFields.native_ptr = GetFieldIDOrDie(env, apk_assets_class, "mNativePtr", "J");
+int register_android_content_AssetManager(JNIEnv* env)
+{
+    jclass typedValue = FindClassOrDie(env, "android/util/TypedValue");
+    gTypedValueOffsets.mType = GetFieldIDOrDie(env, typedValue, "type", "I");
+    gTypedValueOffsets.mData = GetFieldIDOrDie(env, typedValue, "data", "I");
+    gTypedValueOffsets.mString = GetFieldIDOrDie(env, typedValue, "string",
+                                                 "Ljava/lang/CharSequence;");
+    gTypedValueOffsets.mAssetCookie = GetFieldIDOrDie(env, typedValue, "assetCookie", "I");
+    gTypedValueOffsets.mResourceId = GetFieldIDOrDie(env, typedValue, "resourceId", "I");
+    gTypedValueOffsets.mChangingConfigurations = GetFieldIDOrDie(env, typedValue,
+                                                                 "changingConfigurations", "I");
+    gTypedValueOffsets.mDensity = GetFieldIDOrDie(env, typedValue, "density", "I");
 
-  jclass typedValue = FindClassOrDie(env, "android/util/TypedValue");
-  gTypedValueOffsets.mType = GetFieldIDOrDie(env, typedValue, "type", "I");
-  gTypedValueOffsets.mData = GetFieldIDOrDie(env, typedValue, "data", "I");
-  gTypedValueOffsets.mString =
-      GetFieldIDOrDie(env, typedValue, "string", "Ljava/lang/CharSequence;");
-  gTypedValueOffsets.mAssetCookie = GetFieldIDOrDie(env, typedValue, "assetCookie", "I");
-  gTypedValueOffsets.mResourceId = GetFieldIDOrDie(env, typedValue, "resourceId", "I");
-  gTypedValueOffsets.mChangingConfigurations =
-      GetFieldIDOrDie(env, typedValue, "changingConfigurations", "I");
-  gTypedValueOffsets.mDensity = GetFieldIDOrDie(env, typedValue, "density", "I");
+    jclass assetFd = FindClassOrDie(env, "android/content/res/AssetFileDescriptor");
+    gAssetFileDescriptorOffsets.mFd = GetFieldIDOrDie(env, assetFd, "mFd",
+                                                      "Landroid/os/ParcelFileDescriptor;");
+    gAssetFileDescriptorOffsets.mStartOffset = GetFieldIDOrDie(env, assetFd, "mStartOffset", "J");
+    gAssetFileDescriptorOffsets.mLength = GetFieldIDOrDie(env, assetFd, "mLength", "J");
 
-  jclass assetFd = FindClassOrDie(env, "android/content/res/AssetFileDescriptor");
-  gAssetFileDescriptorOffsets.mFd =
-      GetFieldIDOrDie(env, assetFd, "mFd", "Landroid/os/ParcelFileDescriptor;");
-  gAssetFileDescriptorOffsets.mStartOffset = GetFieldIDOrDie(env, assetFd, "mStartOffset", "J");
-  gAssetFileDescriptorOffsets.mLength = GetFieldIDOrDie(env, assetFd, "mLength", "J");
+    jclass assetManager = FindClassOrDie(env, "android/content/res/AssetManager");
+    gAssetManagerOffsets.mObject = GetFieldIDOrDie(env, assetManager, "mObject", "J");
 
-  jclass assetManager = FindClassOrDie(env, "android/content/res/AssetManager");
-  gAssetManagerOffsets.mObject = GetFieldIDOrDie(env, assetManager, "mObject", "J");
+    jclass stringClass = FindClassOrDie(env, "java/lang/String");
+    g_stringClass = MakeGlobalRefOrDie(env, stringClass);
 
-  jclass stringClass = FindClassOrDie(env, "java/lang/String");
-  g_stringClass = MakeGlobalRefOrDie(env, stringClass);
+    jclass sparseArrayClass = FindClassOrDie(env, "android/util/SparseArray");
+    gSparseArrayOffsets.classObject = MakeGlobalRefOrDie(env, sparseArrayClass);
+    gSparseArrayOffsets.constructor = GetMethodIDOrDie(env, gSparseArrayOffsets.classObject,
+                                                       "<init>", "()V");
+    gSparseArrayOffsets.put = GetMethodIDOrDie(env, gSparseArrayOffsets.classObject, "put",
+                                               "(ILjava/lang/Object;)V");
 
-  jclass sparseArrayClass = FindClassOrDie(env, "android/util/SparseArray");
-  gSparseArrayOffsets.classObject = MakeGlobalRefOrDie(env, sparseArrayClass);
-  gSparseArrayOffsets.constructor =
-      GetMethodIDOrDie(env, gSparseArrayOffsets.classObject, "<init>", "()V");
-  gSparseArrayOffsets.put =
-      GetMethodIDOrDie(env, gSparseArrayOffsets.classObject, "put", "(ILjava/lang/Object;)V");
+    jclass configurationClass = FindClassOrDie(env, "android/content/res/Configuration");
+    gConfigurationOffsets.classObject = MakeGlobalRefOrDie(env, configurationClass);
+    gConfigurationOffsets.constructor = GetMethodIDOrDie(env, configurationClass,
+            "<init>", "()V");
+    gConfigurationOffsets.mSmallestScreenWidthDpOffset = GetFieldIDOrDie(env, configurationClass,
+            "smallestScreenWidthDp", "I");
+    gConfigurationOffsets.mScreenWidthDpOffset = GetFieldIDOrDie(env, configurationClass,
+            "screenWidthDp", "I");
+    gConfigurationOffsets.mScreenHeightDpOffset = GetFieldIDOrDie(env, configurationClass,
+            "screenHeightDp", "I");
 
-  jclass configurationClass = FindClassOrDie(env, "android/content/res/Configuration");
-  gConfigurationOffsets.classObject = MakeGlobalRefOrDie(env, configurationClass);
-  gConfigurationOffsets.constructor = GetMethodIDOrDie(env, configurationClass, "<init>", "()V");
-  gConfigurationOffsets.mSmallestScreenWidthDpOffset =
-      GetFieldIDOrDie(env, configurationClass, "smallestScreenWidthDp", "I");
-  gConfigurationOffsets.mScreenWidthDpOffset =
-      GetFieldIDOrDie(env, configurationClass, "screenWidthDp", "I");
-  gConfigurationOffsets.mScreenHeightDpOffset =
-      GetFieldIDOrDie(env, configurationClass, "screenHeightDp", "I");
-
-  return RegisterMethodsOrDie(env, "android/content/res/AssetManager", gAssetManagerMethods,
-                              NELEM(gAssetManagerMethods));
+    return RegisterMethodsOrDie(env, "android/content/res/AssetManager", gAssetManagerMethods,
+                                NELEM(gAssetManagerMethods));
 }
 
 }; // namespace android
diff --git a/core/jni/include/android_runtime/android_util_AssetManager.h b/core/jni/include/android_runtime/android_util_AssetManager.h
index 2c1e357..8dd9337 100644
--- a/core/jni/include/android_runtime/android_util_AssetManager.h
+++ b/core/jni/include/android_runtime/android_util_AssetManager.h
@@ -14,20 +14,17 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_RUNTIME_ASSETMANAGER_H
-#define ANDROID_RUNTIME_ASSETMANAGER_H
+#ifndef android_util_AssetManager_H
+#define android_util_AssetManager_H
 
-#include "androidfw/AssetManager2.h"
-#include "androidfw/MutexGuard.h"
+#include <androidfw/AssetManager.h>
 
 #include "jni.h"
 
 namespace android {
 
-extern AAssetManager* NdkAssetManagerForJavaObject(JNIEnv* env, jobject jassetmanager);
-extern Guarded<AssetManager2>* AssetManagerForJavaObject(JNIEnv* env, jobject jassetmanager);
-extern Guarded<AssetManager2>* AssetManagerForNdkAssetManager(AAssetManager* assetmanager);
+extern AssetManager* assetManagerForJavaObject(JNIEnv* env, jobject assetMgr);
 
-}  // namespace android
+}
 
-#endif  // ANDROID_RUNTIME_ASSETMANAGER_H
+#endif
diff --git a/core/proto/android/providers/settings.proto b/core/proto/android/providers/settings.proto
index ff0f4fd..f2b7ab2 100644
--- a/core/proto/android/providers/settings.proto
+++ b/core/proto/android/providers/settings.proto
@@ -422,7 +422,7 @@
     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 zram_enabled = 347 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto enable_smart_replies_in_notifications = 348 [ (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 ];
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index f6f1d81..6f3c25f 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -573,6 +573,10 @@
     <protected-broadcast android:name="android.media.tv.action.CHANNEL_BROWSABLE_REQUESTED" />
     <protected-broadcast android:name="com.android.server.InputMethodManagerService.SHOW_INPUT_METHOD_PICKER" />
 
+    <!-- Time zone rules update intents fired by the system server -->
+    <protected-broadcast android:name="com.android.intent.action.timezone.RULES_UPDATE_OPERATION" />
+    <protected-broadcast android:name="com.android.intent.action.timezone.TRIGGER_RULES_UPDATE_CHECK" />
+
     <!-- Made protected in P (was introduced in JB-MR2) -->
     <protected-broadcast android:name="android.intent.action.GET_RESTRICTION_ENTRIES" />
     <protected-broadcast android:name="android.telephony.euicc.action.OTA_STATUS_CHANGED" />
@@ -1412,6 +1416,12 @@
     <permission android:name="android.permission.MANAGE_LOWPAN_INTERFACES"
         android:protectionLevel="signature|privileged" />
 
+    <!-- @hide Allows internal management of Wi-Fi connectivity state when on
+         permission review mode.
+         <p>Not for use by third-party applications. -->
+    <permission android:name="android.permission.MANAGE_WIFI_WHEN_PERMISSION_REVIEW_REQUIRED"
+        android:protectionLevel="signature" />
+
     <!-- ======================================= -->
     <!-- Permissions for short range, peripheral networks -->
     <!-- ======================================= -->
@@ -1495,6 +1505,11 @@
     <permission android:name="android.permission.NFC_HANDOVER_STATUS"
         android:protectionLevel="signature|privileged" />
 
+    <!-- @hide Allows internal management of Bluetooth state when on permission review mode.
+         <p>Not for use by third-party applications. -->
+    <permission android:name="android.permission.MANAGE_BLUETOOTH_WHEN_PERMISSION_REVIEW_REQUIRED"
+        android:protectionLevel="signature" />
+
     <!-- ================================== -->
     <!-- Permissions for accessing accounts -->
     <!-- ================================== -->
@@ -1812,19 +1827,20 @@
     <permission android:name="android.permission.BIND_TELEPHONY_NETWORK_SERVICE"
                 android:protectionLevel="signature" />
 
-    <!-- Allows an application to manage embedded subscriptions (those on a eUICC) through
-         EuiccManager APIs.
+    <!-- @SystemApi Allows an application to manage embedded subscriptions (those on a eUICC)
+         through EuiccManager APIs.
          <p>Protection level: signature|privileged|development
-         TODO(b/35851809): Mark this as a SystemApi and remove com. prefix.
-         @hide -->
-    <permission android:name="com.android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS"
+         @hide
+    -->
+    <permission android:name="android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS"
                 android:protectionLevel="signature|privileged|development" />
 
-    <!-- Must be required by an EuiccService to ensure that only the system can bind to it.
+    <!-- @SystemApi Must be required by an EuiccService to ensure that only the system can bind to
+         it.
          <p>Protection level: signature
-         TODO(b/35851809): Mark this as a SystemApi and remove com. prefix.
-         @hide -->
-    <permission android:name="com.android.permission.BIND_EUICC_SERVICE"
+         @hide
+    -->
+    <permission android:name="android.permission.BIND_EUICC_SERVICE"
                 android:protectionLevel="signature" />
 
     <!-- ================================== -->
@@ -2955,11 +2971,16 @@
     <permission android:name="android.permission.MANAGE_SCOPED_ACCESS_DIRECTORY_PERMISSIONS"
         android:protectionLevel="signature" />
 
-    <!-- @SystemApi Allows an application to delete cache files.
-    <p>Not for use by third-party applications. -->
+    <!-- @SystemApi Old permission for deleting an app's cache files, no longer used,
+         but signals for us to quietly ignore calls instead of throwing an exception. -->
     <permission android:name="android.permission.DELETE_CACHE_FILES"
         android:protectionLevel="signature|privileged" />
 
+    <!-- Allows an application to delete cache files.
+         @hide -->
+    <permission android:name="android.permission.INTERNAL_DELETE_CACHE_FILES"
+        android:protectionLevel="signature" />
+
     <!-- @SystemApi Allows an application to delete packages.
          <p>Not for use by third-party applications.
          <p>Starting in {@link android.os.Build.VERSION_CODES#N}, user confirmation is requested
@@ -3785,15 +3806,6 @@
     <permission android:name="android.permission.INSTANT_APP_FOREGROUND_SERVICE"
         android:protectionLevel="signature|development|instant|appop" />
 
-    <!-- Allows a regular application to use {@link android.app.Service#startForeground
-         Service.startForeground}.
-         <p>Protection level: normal
-    -->
-    <permission android:name="android.permission.FOREGROUND_SERVICE"
-        android:description="@string/permdesc_foregroundService"
-        android:label="@string/permlab_foregroundService"
-        android:protectionLevel="normal|instant" />
-
     <!-- @hide Allows system components to access all app shortcuts. -->
     <permission android:name="android.permission.ACCESS_SHORTCUTS"
         android:protectionLevel="signature" />
diff --git a/core/res/res/color/watch_switch_track_color_material.xml b/core/res/res/color-watch/btn_watch_default_dark.xml
similarity index 82%
copy from core/res/res/color/watch_switch_track_color_material.xml
copy to core/res/res/color-watch/btn_watch_default_dark.xml
index c7dc5d3..68b0eb6 100644
--- a/core/res/res/color/watch_switch_track_color_material.xml
+++ b/core/res/res/color-watch/btn_watch_default_dark.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2016 The Android Open Source Project
+<!-- 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.
@@ -17,6 +17,6 @@
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
     <item android:state_enabled="false"
           android:alpha="?attr/disabledAlpha"
-          android:color="?android:colorPrimary" />
-    <item android:color="?android:colorPrimary" />
-</selector>
\ No newline at end of file
+          android:color="?attr/colorPrimaryDark"/>
+    <item android:color="?attr/colorPrimaryDark"/>
+</selector>
diff --git a/core/res/res/color/watch_switch_thumb_color_material.xml b/core/res/res/color-watch/switch_thumb_watch_default_dark.xml
similarity index 85%
rename from core/res/res/color/watch_switch_thumb_color_material.xml
rename to core/res/res/color-watch/switch_thumb_watch_default_dark.xml
index f78d9b62..a553fa9 100644
--- a/core/res/res/color/watch_switch_thumb_color_material.xml
+++ b/core/res/res/color-watch/switch_thumb_watch_default_dark.xml
@@ -11,8 +11,8 @@
      limitations under the License.
 -->
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:color="?attr/colorButtonNormal" android:alpha="?attr/disabledAlpha"
+    <item android:color="?attr/colorPrimary" android:alpha="?attr/disabledAlpha"
             android:state_enabled="false" />
     <item android:color="?attr/colorControlActivated" android:state_checked="true" />
-    <item android:color="?attr/colorButtonNormal" />
+    <item android:color="?attr/colorPrimary" />
 </selector>
diff --git a/core/res/res/color/watch_switch_track_color_material.xml b/core/res/res/color-watch/switch_track_watch_default_dark.xml
similarity index 87%
rename from core/res/res/color/watch_switch_track_color_material.xml
rename to core/res/res/color-watch/switch_track_watch_default_dark.xml
index c7dc5d3..15bbeda 100644
--- a/core/res/res/color/watch_switch_track_color_material.xml
+++ b/core/res/res/color-watch/switch_track_watch_default_dark.xml
@@ -17,6 +17,6 @@
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
     <item android:state_enabled="false"
           android:alpha="?attr/disabledAlpha"
-          android:color="?android:colorPrimary" />
-    <item android:color="?android:colorPrimary" />
-</selector>
\ No newline at end of file
+          android:color="?android:colorPrimaryDark" />
+    <item android:color="?android:colorPrimaryDark" />
+</selector>
diff --git a/core/res/res/drawable/watch_switch_thumb_material_anim.xml b/core/res/res/drawable-watch/switch_thumb_watch_default_dark_anim.xml
similarity index 100%
rename from core/res/res/drawable/watch_switch_thumb_material_anim.xml
rename to core/res/res/drawable-watch/switch_thumb_watch_default_dark_anim.xml
diff --git a/core/res/res/layout-watch/preference_widget_switch.xml b/core/res/res/layout-watch/preference_widget_switch.xml
index a1a845a..1f9d678 100644
--- a/core/res/res/layout-watch/preference_widget_switch.xml
+++ b/core/res/res/layout-watch/preference_widget_switch.xml
@@ -21,11 +21,11 @@
     android:layout_height="40dp"
     android:switchMinWidth="40dp"
     android:layout_gravity="center"
-    android:thumb="@drawable/watch_switch_thumb_material_anim"
-    android:thumbTint="@color/watch_switch_thumb_color_material"
+    android:thumb="@drawable/switch_thumb_watch_default_dark_anim"
+    android:thumbTint="@color/switch_thumb_watch_default_dark"
     android:thumbTintMode="multiply"
     android:track="@drawable/watch_switch_track_mtrl"
-    android:trackTint="@color/watch_switch_track_color_material"
+    android:trackTint="@color/switch_track_watch_default_dark"
     android:focusable="false"
     android:clickable="false"
     android:background="@null" />
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index df0f578..ba64d0f 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -264,10 +264,8 @@
     <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string>
     <string name="safeMode" msgid="2788228061547930246">"Sikker tilstand"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android-system"</string>
-    <!-- no translation found for user_owner_label (8836124313744349203) -->
-    <skip />
-    <!-- no translation found for managed_profile_label (8947929265267690522) -->
-    <skip />
+    <string name="user_owner_label" msgid="8836124313744349203">"Skift til personlig profil"</string>
+    <string name="managed_profile_label" msgid="8947929265267690522">"Skift til arbejdsprofil"</string>
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"Kontaktpersoner"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"have adgang til dine kontaktpersoner"</string>
     <string name="permgrouprequest_contacts" msgid="1601591667800538208">"Giv &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; adgang til dine kontaktpersoner"</string>
@@ -357,6 +355,8 @@
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"Tillader, at appen gør dele af sig selv vedholdende i hukommelsen. Dette kan begrænse den tilgængelige hukommelse for andre apps, hvilket gør tabletten langsommere."</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"Giver appen lov til at gøre dele af sig selv vedholdende i hukommelsen. Dette kan begrænse den tilgængelige hukommelse for andre apps og derved gøre fjernsynet langsommere."</string>
     <string name="permdesc_persistentActivity" product="default" msgid="4384760047508278272">"Tillader, at appen gør dele af sig selv vedholdende i hukommelsen. Dette kan begrænse den tilgængelige hukommelse for andre apps, hvilket gør telefonen langsommere."</string>
+    <string name="permlab_foregroundService" msgid="3310786367649133115">"kør tjeneste i forgrunden"</string>
+    <string name="permdesc_foregroundService" msgid="6471634326171344622">"Tillad, at appen anvender tjenester i forgrunden."</string>
     <string name="permlab_getPackageSize" msgid="7472921768357981986">"måle appens lagerplads"</string>
     <string name="permdesc_getPackageSize" msgid="3921068154420738296">"Tillader, at en app kan hente sin kode, data og cachestørrelser"</string>
     <string name="permlab_writeSettings" msgid="2226195290955224730">"ændre systemindstillinger"</string>
@@ -419,10 +419,8 @@
     <string name="permdesc_readPhoneState" msgid="1639212771826125528">"Tillader, at appen kan få adgang til telefonfunktionerne på enheden. Med denne tilladelse kan appen fastslå telefonnummeret og enheds-id\'erne, hvorvidt et opkald er aktivt samt det eksterne nummer, der oprettes forbindelse til via et opkald."</string>
     <string name="permlab_manageOwnCalls" msgid="1503034913274622244">"dirigere opkald gennem systemet"</string>
     <string name="permdesc_manageOwnCalls" msgid="6552974537554717418">"Tillader appen at dirigere sine opkald gennem systemet for at forbedre opkaldsoplevelsen."</string>
-    <!-- no translation found for permlab_acceptHandover (2661534649736022409) -->
-    <skip />
-    <!-- no translation found for permdesc_acceptHandovers (4570660484220539698) -->
-    <skip />
+    <string name="permlab_acceptHandover" msgid="2661534649736022409">"fortsætte et opkald fra en anden app"</string>
+    <string name="permdesc_acceptHandovers" msgid="4570660484220539698">"Tillader, at appen fortsætter et opkald, der blev startet i en anden app."</string>
     <string name="permlab_readPhoneNumbers" msgid="6108163940932852440">"læse telefonnumre"</string>
     <string name="permdesc_readPhoneNumbers" msgid="8559488833662272354">"Tillader, at appen får adgang til telefonnumrene på denne enhed."</string>
     <string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"afholde tabletcomputeren fra at gå i dvale"</string>
@@ -497,11 +495,12 @@
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Fingeraftrykket kan ikke gemmes. Fjern et eksisterende fingeraftryk."</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Registrering af fingeraftryk fik timeout. Prøv igen."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Fingeraftrykshandlingen blev annulleret."</string>
-    <!-- no translation found for fingerprint_error_user_canceled (7999639584615291494) -->
-    <skip />
+    <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"Fingeraftrykshandlingen blev annulleret af brugeren."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Du har prøvet for mange gange. Prøv igen senere."</string>
     <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Du har brugt for mange forsøg. Fingeraftrykslæseren er deaktiveret."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Prøv igen."</string>
+    <string name="fingerprint_error_no_fingerprints" msgid="7654382120628334248">"Der er ikke registreret nogen fingeraftryk."</string>
+    <string name="fingerprint_error_hw_not_present" msgid="5729436878065119329">"Denne enhed har ingen fingeraftrykslæser"</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Fingeraftryk <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
@@ -1000,12 +999,9 @@
     <string name="browse" msgid="1245903488306147205">"Åbn"</string>
     <string name="sms" msgid="4560537514610063430">"Besked"</string>
     <string name="add_contact" msgid="7867066569670597203">"Tilføj"</string>
-    <!-- no translation found for view_calendar (979609872939597838) -->
-    <skip />
-    <!-- no translation found for add_calendar_event (1953664627192056206) -->
-    <skip />
-    <!-- no translation found for view_flight (7691640491425680214) -->
-    <skip />
+    <string name="view_calendar" msgid="979609872939597838">"Se"</string>
+    <string name="add_calendar_event" msgid="1953664627192056206">"Planlæg"</string>
+    <string name="view_flight" msgid="7691640491425680214">"Spor"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Der er snart ikke mere lagerplads"</string>
     <string name="low_internal_storage_view_text" msgid="6640505817617414371">"Nogle systemfunktioner virker måske ikke"</string>
     <string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"Der er ikke nok ledig lagerplads til systemet. Sørg for, at du har 250 MB ledig plads, og genstart."</string>
@@ -1131,8 +1127,7 @@
       <item quantity="other">Åbne Wi-Fi-netværk er tilgængelige</item>
     </plurals>
     <string name="wifi_available_title" msgid="3817100557900599505">"Opret forbindelse til et åbent Wi-Fi-netværk"</string>
-    <!-- no translation found for wifi_available_carrier_network_title (4527932626916527897) -->
-    <skip />
+    <string name="wifi_available_carrier_network_title" msgid="4527932626916527897">"Opret forbindelse til dit mobilselskabs Wi‑Fi-netværk"</string>
     <string name="wifi_available_title_connecting" msgid="1557292688310330032">"Opretter forbindelse til et åbent Wi‑Fi-netværk"</string>
     <string name="wifi_available_title_connected" msgid="7542672851522241548">"Forbundet til Wi-Fi-netværket"</string>
     <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Der kan ikke oprettes forbindelse til Wi-Fi-netværket"</string>
@@ -1216,13 +1211,15 @@
     <string name="no_permissions" msgid="7283357728219338112">"Der kræves ingen tilladelser"</string>
     <string name="perm_costs_money" msgid="4902470324142151116">"dette kan koste dig penge"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
-    <string name="usb_charging_notification_title" msgid="6895185153353640787">"USB oplader denne enhed"</string>
-    <string name="usb_supplying_notification_title" msgid="5310642257296510271">"USB, der leverer strøm til den tilsluttede enhed"</string>
-    <string name="usb_mtp_notification_title" msgid="8396264943589760855">"USB til filoverførsel"</string>
-    <string name="usb_ptp_notification_title" msgid="1347328437083192112">"USB til billedoverførsel"</string>
-    <string name="usb_midi_notification_title" msgid="4850904915889144654">"USB til MIDI"</string>
-    <string name="usb_accessory_notification_title" msgid="7848236974087653666">"Tilsluttet et USB-ekstraudstyr"</string>
+    <string name="usb_charging_notification_title" msgid="1595122345358177163">"Enheden oplades via USB"</string>
+    <string name="usb_supplying_notification_title" msgid="4631045789893086181">"Den tilsluttede enhed oplades via USB"</string>
+    <string name="usb_mtp_notification_title" msgid="4238227258391151029">"Filoverførsel via USB er slået til"</string>
+    <string name="usb_ptp_notification_title" msgid="5425857879922006878">"PTP via USB er slået til"</string>
+    <string name="usb_tether_notification_title" msgid="3716143122035802501">"Netdeling via USB er slået til"</string>
+    <string name="usb_midi_notification_title" msgid="5356040379749154805">"MIDI via USB er slået til"</string>
+    <string name="usb_accessory_notification_title" msgid="1899977434994900306">"Tilstanden USB-tilbehør er slået til"</string>
     <string name="usb_notification_message" msgid="3370903770828407960">"Tryk for at se flere muligheder."</string>
+    <string name="usb_power_notification_message" msgid="4647527153291917218">"Den tilsluttede enhed oplades. Tryk for at få flere valgmuligheder."</string>
     <string name="usb_unsupported_audio_accessory_title" msgid="3529881374464628084">"Der blev registreret et analogt lydtilbehør"</string>
     <string name="usb_unsupported_audio_accessory_message" msgid="6309553946441565215">"Den tilsluttede enhed er ikke kompatibel med denne telefon. Tryk for at få flere oplysninger."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB-fejlretning er tilsluttet"</string>
@@ -1524,7 +1521,7 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Du har tegnet dit oplåsningsmønster forkert <xliff:g id="NUMBER_0">%1$d</xliff:g> gange. Efter <xliff:g id="NUMBER_1">%2$d</xliff:g> yderligere mislykkede forsøg til vil du blive bedt om at låse din telefon op ved hjælp af en e-mailkonto.\n\n Prøv igen om <xliff:g id="NUMBER_2">%3$d</xliff:g> sekunder."</string>
     <string name="kg_text_message_separator" product="default" msgid="4160700433287233771">" – "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="7899202978204438708">"Fjern"</string>
-    <string name="safe_media_volume_warning" product="default" msgid="2276318909314492312">"Vil du skrue højere op end det anbefalede lydstyrkeniveau?\n\nDu kan skade hørelsen ved at lytte til meget højt musik over længere tid."</string>
+    <string name="safe_media_volume_warning" product="default" msgid="2276318909314492312">"Vil du skrue højere op end det anbefalede lydstyrkeniveau?\n\nDu kan skade hørelsen ved at lytte til meget høj musik over længere tid."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="8404780875025725199">"Vil du bruge genvejen til Hjælpefunktioner?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="7256507885737444807">"Når genvejen er slået til, kan du starte en hjælpefunktion ved at trykke på begge lydstyrkeknapper i tre sekunder.\n\n Nuværende hjælpefunktion:\n<xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Du kan skifte funktion i Indstillinger &gt; Hjælpefunktioner."</string>
     <string name="disable_accessibility_shortcut" msgid="627625354248453445">"Deaktiver genvej"</string>
@@ -1661,9 +1658,6 @@
     <string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> – arbejde"</string>
     <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2. <xliff:g id="LABEL">%1$s</xliff:g> til arbejde"</string>
     <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3. <xliff:g id="LABEL">%1$s</xliff:g> til arbejde"</string>
-    <string name="lock_to_app_toast" msgid="6820571533009838261">"Hvis du vil frigøre dette skærmbillede, skal du trykke på knapperne Tilbage og Oversigt og holde fingrene nede"</string>
-    <string name="lock_to_app_start" msgid="6643342070839862795">"Skærmen blev fastgjort"</string>
-    <string name="lock_to_app_exit" msgid="8598219838213787430">"Skærmen blev frigjort"</string>
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Bed om pinkode inden frigørelse"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Bed om oplåsningsmønster ved deaktivering"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Bed om adgangskode inden frigørelse"</string>
@@ -1757,15 +1751,11 @@
     <string name="language_picker_section_all" msgid="3097279199511617537">"Alle sprog"</string>
     <string name="region_picker_section_all" msgid="8966316787153001779">"Alle områder"</string>
     <string name="locale_search_menu" msgid="2560710726687249178">"Søg"</string>
-    <!-- no translation found for work_mode_off_title (1118691887588435530) -->
-    <skip />
-    <!-- no translation found for work_mode_off_message (5130856710614337649) -->
-    <skip />
+    <string name="work_mode_off_title" msgid="1118691887588435530">"Skal arbejdsprofilen slås til?"</string>
+    <string name="work_mode_off_message" msgid="5130856710614337649">"Dine arbejdsapps, underretninger, data og andre funktioner til din arbejdsprofil deaktiveres"</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"Slå til"</string>
-    <!-- no translation found for deprecated_target_sdk_message (1449696506742572767) -->
-    <skip />
-    <!-- no translation found for deprecated_target_sdk_app_store (5032340500368495077) -->
-    <skip />
+    <string name="deprecated_target_sdk_message" msgid="1449696506742572767">"Denne app er lavet til en ældre version af Android og fungerer muligvis ikke korrekt. Prøv at søge efter opdateringer, eller kontakt udvikleren."</string>
+    <string name="deprecated_target_sdk_app_store" msgid="5032340500368495077">"Søg efter opdatering"</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"Du har nye beskeder"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"Åbn sms-appen for at se beskeden"</string>
     <string name="user_encrypted_title" msgid="9054897468831672082">"Nogle funktioner er begrænsede"</string>
@@ -1832,17 +1822,14 @@
     <string name="mmcc_illegal_me" msgid="1950705155760872972">"Telefon er ikke tilladt for tale"</string>
     <string name="popup_window_default_title" msgid="4874318849712115433">"Pop op-vindue"</string>
     <string name="slice_more_content" msgid="8504342889413274608">"<xliff:g id="NUMBER">%1$d</xliff:g> mere"</string>
-    <string name="shortcut_restored_on_lower_version" msgid="5270675146351613828">"Denne genvej kræver den nyeste app"</string>
+    <string name="shortcut_restored_on_lower_version" msgid="4860853725206702336">"Appversionen er nedgraderet, eller også er den ikke kompatibel med denne genvej"</string>
     <string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Genvejen kunne ikke gendannes, da appen ikke understøtter backup og gendannelse"</string>
     <string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Genvejen kunne ikke gendannes på grund af uoverensstemmelse i appsignatur"</string>
     <string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Genvejen kunne ikke gendannes"</string>
     <string name="shortcut_disabled_reason_unknown" msgid="5276016910284687075">"Genvejen er deaktiveret"</string>
-    <!-- no translation found for harmful_app_warning_uninstall (4837672735619532931) -->
-    <skip />
-    <!-- no translation found for harmful_app_warning_open_anyway (596432803680914321) -->
-    <skip />
-    <!-- no translation found for harmful_app_warning_title (8982527462829423432) -->
-    <skip />
+    <string name="harmful_app_warning_uninstall" msgid="4837672735619532931">"AFINSTALLER"</string>
+    <string name="harmful_app_warning_open_anyway" msgid="596432803680914321">"ÅBN ALLIGEVEL"</string>
+    <string name="harmful_app_warning_title" msgid="8982527462829423432">"Der er registreret en skadelig app"</string>
     <string name="slices_permission_request" msgid="8484943441501672932">"<xliff:g id="APP_0">%1$s</xliff:g> anmoder om tilladelse til at vise eksempler fra <xliff:g id="APP_2">%2$s</xliff:g>"</string>
     <string name="screenshot_edit" msgid="7867478911006447565">"Rediger"</string>
 </resources>
diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml
index 2436326..1b3e131 100644
--- a/core/res/res/values-eu/strings.xml
+++ b/core/res/res/values-eu/strings.xml
@@ -264,10 +264,8 @@
     <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string>
     <string name="safeMode" msgid="2788228061547930246">"Modu segurua"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android sistema"</string>
-    <!-- no translation found for user_owner_label (8836124313744349203) -->
-    <skip />
-    <!-- no translation found for managed_profile_label (8947929265267690522) -->
-    <skip />
+    <string name="user_owner_label" msgid="8836124313744349203">"Aldatu profil pertsonalera"</string>
+    <string name="managed_profile_label" msgid="8947929265267690522">"Aldatu laneko profilera"</string>
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"Kontaktuak"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"atzitu kontaktuak"</string>
     <string name="permgrouprequest_contacts" msgid="1601591667800538208">"Baimendu kontaktuak atzitzea &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aplikazioari"</string>
@@ -357,6 +355,8 @@
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"Beren zati batzuk memoria modu iraunkorrean ezartzeko baimena ematen die aplikazioei. Horrela, beste aplikazioek erabilgarri duten memoria murritz daiteke eta tableta motel daiteke."</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"Beren zati batzuk memorian modu iraunkorrean aktibo uztea baimentzen die aplikazioei. Horrela, beste aplikazioek memoria gutxiago izan lezakete erabilgarri eta telebistak motelago funtziona lezake."</string>
     <string name="permdesc_persistentActivity" product="default" msgid="4384760047508278272">"Beren zati batzuk memoria modu iraunkorrean ezartzeko baimena ematen die aplikazioei. Horrela, beste aplikazioek erabilgarri duten memoria murritz daiteke eta telefonoa motel daiteke."</string>
+    <string name="permlab_foregroundService" msgid="3310786367649133115">"Exekutatu zerbitzuak aurreko planoan"</string>
+    <string name="permdesc_foregroundService" msgid="6471634326171344622">"Aurreko planoko zerbitzuak erabiltzea baimentzen dio aplikazioari."</string>
     <string name="permlab_getPackageSize" msgid="7472921768357981986">"neurtu aplikazioen biltegiratze-tokia"</string>
     <string name="permdesc_getPackageSize" msgid="3921068154420738296">"Bere kodea, datuak eta cache-tamainak eskuratzea baimentzen die aplikazioei."</string>
     <string name="permlab_writeSettings" msgid="2226195290955224730">"aldatu sistemaren ezarpenak"</string>
@@ -419,10 +419,8 @@
     <string name="permdesc_readPhoneState" msgid="1639212771826125528">"Gailuaren telefono-eginbideak atzitzeko baimena ematen die aplikazioei. Baimen horrek aplikazioari telefono-zenbakia eta gailu IDak zein diren, deirik aktibo dagoen eta deia zer zenbakirekin konektatuta dagoen zehazteko baimena ematen die aplikazioei."</string>
     <string name="permlab_manageOwnCalls" msgid="1503034913274622244">"bideratu deiak sistemaren bidez"</string>
     <string name="permdesc_manageOwnCalls" msgid="6552974537554717418">"Deiak sistemaren bidez bideratzea baimentzen die aplikazioei, deien zerbitzua ahal bezain ona izan dadin."</string>
-    <!-- no translation found for permlab_acceptHandover (2661534649736022409) -->
-    <skip />
-    <!-- no translation found for permdesc_acceptHandovers (4570660484220539698) -->
-    <skip />
+    <string name="permlab_acceptHandover" msgid="2661534649736022409">"Jarraitu beste aplikazio batean hasitako deia"</string>
+    <string name="permdesc_acceptHandovers" msgid="4570660484220539698">"Beste aplikazio batean hasitako dei bat jarraitzea baimentzen dio aplikazioari."</string>
     <string name="permlab_readPhoneNumbers" msgid="6108163940932852440">"irakurri telefono-zenbakiak"</string>
     <string name="permdesc_readPhoneNumbers" msgid="8559488833662272354">"Gailuaren telefono-zenbakiak atzitzea baimentzen die aplikazioei."</string>
     <string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"eragotzi tableta inaktibo ezartzea"</string>
@@ -497,11 +495,12 @@
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Ezin da gorde hatz-marka digitala. Kendu lehendik gordeta duzunetako bat."</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Hatz-marka digitalak prozesatzeko denbora-muga gainditu da. Saiatu berriro."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Hatz-markaren eragiketa bertan behera utzi da."</string>
-    <!-- no translation found for fingerprint_error_user_canceled (7999639584615291494) -->
-    <skip />
+    <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"Erabiltzaileak bertan behera utzi du hatz-marka bidezko eragiketa."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Saiakera gehiegi egin dituzu. Saiatu berriro geroago."</string>
     <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Saiakera gehiegi egin dituzu. Desgaitu egin da hatz-marken sentsorea."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Saiatu berriro."</string>
+    <string name="fingerprint_error_no_fingerprints" msgid="7654382120628334248">"Ez da erregistratu hatz-markarik."</string>
+    <string name="fingerprint_error_hw_not_present" msgid="5729436878065119329">"Gailu honek ez du hatz-marken sentsorerik"</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"<xliff:g id="FINGERID">%d</xliff:g> hatza"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
@@ -1000,12 +999,9 @@
     <string name="browse" msgid="1245903488306147205">"Ireki"</string>
     <string name="sms" msgid="4560537514610063430">"Bidali mezua"</string>
     <string name="add_contact" msgid="7867066569670597203">"Gehitu"</string>
-    <!-- no translation found for view_calendar (979609872939597838) -->
-    <skip />
-    <!-- no translation found for add_calendar_event (1953664627192056206) -->
-    <skip />
-    <!-- no translation found for view_flight (7691640491425680214) -->
-    <skip />
+    <string name="view_calendar" msgid="979609872939597838">"Ikusi"</string>
+    <string name="add_calendar_event" msgid="1953664627192056206">"Antolatu"</string>
+    <string name="view_flight" msgid="7691640491425680214">"Egin jarraipena"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Memoria betetzen ari da"</string>
     <string name="low_internal_storage_view_text" msgid="6640505817617414371">"Sistemaren funtzio batzuek ez dute agian funtzionatuko"</string>
     <string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"Sisteman ez dago behar adina memoria. Ziurtatu gutxienez 250 MB erabilgarri dituzula eta, ondoren, berrabiarazi gailua."</string>
@@ -1131,8 +1127,7 @@
       <item quantity="one">Wi-Fi sare irekia erabilgarri</item>
     </plurals>
     <string name="wifi_available_title" msgid="3817100557900599505">"Konektatu Wi‑Fi sare irekira"</string>
-    <!-- no translation found for wifi_available_carrier_network_title (4527932626916527897) -->
-    <skip />
+    <string name="wifi_available_carrier_network_title" msgid="4527932626916527897">"Konektatu operadorearen Wi‑Fi sarera"</string>
     <string name="wifi_available_title_connecting" msgid="1557292688310330032">"Wi‑Fi sare irekira konektatzen"</string>
     <string name="wifi_available_title_connected" msgid="7542672851522241548">"Wi‑Fi sare irekira konektatuta"</string>
     <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Ezin izan da konektatu Wi‑Fi sare irekira"</string>
@@ -1217,13 +1212,15 @@
     <string name="no_permissions" msgid="7283357728219338112">"Ez da baimenik behar"</string>
     <string name="perm_costs_money" msgid="4902470324142151116">"dirua kosta dakizuke"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"Ados"</string>
-    <string name="usb_charging_notification_title" msgid="6895185153353640787">"Gailua USB bidez ari da kargatzen"</string>
-    <string name="usb_supplying_notification_title" msgid="5310642257296510271">"Konektatutako gailua USB bidez jasotzen ari da energia"</string>
-    <string name="usb_mtp_notification_title" msgid="8396264943589760855">"Fitxategiak transferitzeko USBa"</string>
-    <string name="usb_ptp_notification_title" msgid="1347328437083192112">"Argazkiak transferitzeko USBa"</string>
-    <string name="usb_midi_notification_title" msgid="4850904915889144654">"MIDI modurako USBa"</string>
-    <string name="usb_accessory_notification_title" msgid="7848236974087653666">"USB osagarri batera konektatuta"</string>
+    <string name="usb_charging_notification_title" msgid="1595122345358177163">"Gailua USB bidez kargatzen"</string>
+    <string name="usb_supplying_notification_title" msgid="4631045789893086181">"Konektatutako gailua USB bidez kargatzen ari da"</string>
+    <string name="usb_mtp_notification_title" msgid="4238227258391151029">"Aktibatuta dago USB bidezko fitxategi-transferentzia"</string>
+    <string name="usb_ptp_notification_title" msgid="5425857879922006878">"Aktibatuta dago USB bidezko PTP modua"</string>
+    <string name="usb_tether_notification_title" msgid="3716143122035802501">"Aktibatuta dago USB bidez konexioa partekatzeko aukera"</string>
+    <string name="usb_midi_notification_title" msgid="5356040379749154805">"Aktibatuta dago USB bidezko MIDI modua"</string>
+    <string name="usb_accessory_notification_title" msgid="1899977434994900306">"Aktibatuta dago USB osagarriaren modua"</string>
     <string name="usb_notification_message" msgid="3370903770828407960">"Sakatu aukera gehiago ikusteko."</string>
+    <string name="usb_power_notification_message" msgid="4647527153291917218">"Konektatutako gailua kargatzen ari da. Sakatu aukera gehiago ikusteko."</string>
     <string name="usb_unsupported_audio_accessory_title" msgid="3529881374464628084">"Audio-osagarri analogiko bat hauteman da"</string>
     <string name="usb_unsupported_audio_accessory_message" msgid="6309553946441565215">"Erantsitako gailua ez da telefono honekin bateragarria. Sakatu informazio gehiago lortzeko."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB arazketa konektatuta"</string>
@@ -1662,9 +1659,6 @@
     <string name="managed_profile_label_badge" msgid="2355652472854327647">"Laneko <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"Laneko 2. <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"Laneko 3. <xliff:g id="LABEL">%1$s</xliff:g>"</string>
-    <string name="lock_to_app_toast" msgid="6820571533009838261">"Pantailari aingura kentzeko, eduki sakatuta Atzera eta Ikuspegi orokorra botoiak"</string>
-    <string name="lock_to_app_start" msgid="6643342070839862795">"Pantaila ainguratu da"</string>
-    <string name="lock_to_app_exit" msgid="8598219838213787430">"Aingura kendu zaio pantailari"</string>
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Eskatu PIN kodea aingura kendu aurretik"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Eskatu desblokeatzeko eredua aingura kendu aurretik"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Eskatu pasahitza aingura kendu aurretik"</string>
@@ -1758,15 +1752,11 @@
     <string name="language_picker_section_all" msgid="3097279199511617537">"Hizkuntza guztiak"</string>
     <string name="region_picker_section_all" msgid="8966316787153001779">"Lurralde guztiak"</string>
     <string name="locale_search_menu" msgid="2560710726687249178">"Bilaketa"</string>
-    <!-- no translation found for work_mode_off_title (1118691887588435530) -->
-    <skip />
-    <!-- no translation found for work_mode_off_message (5130856710614337649) -->
-    <skip />
+    <string name="work_mode_off_title" msgid="1118691887588435530">"Laneko profila aktibatu?"</string>
+    <string name="work_mode_off_message" msgid="5130856710614337649">"Laneko aplikazioak, jakinarazpenak, datuak eta laneko profileko bestelako eginbideak aktibatuko dira"</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"Aktibatu"</string>
-    <!-- no translation found for deprecated_target_sdk_message (1449696506742572767) -->
-    <skip />
-    <!-- no translation found for deprecated_target_sdk_app_store (5032340500368495077) -->
-    <skip />
+    <string name="deprecated_target_sdk_message" msgid="1449696506742572767">"Aplikazioa Android-en bertsio zaharrago baterako sortu zenez, baliteke behar bezala ez funtzionatzea. Bilatu eguneratzerik baden, edo jarri garatzailearekin harremanetan."</string>
+    <string name="deprecated_target_sdk_app_store" msgid="5032340500368495077">"Bilatu eguneratzeak"</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"Mezu berriak dituzu"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"Mezuak ikusteko, ireki SMS mezuen aplikazioa"</string>
     <string name="user_encrypted_title" msgid="9054897468831672082">"Funtzioak mugatuta egon litezke"</string>
@@ -1833,17 +1823,14 @@
     <string name="mmcc_illegal_me" msgid="1950705155760872972">"Telefonoa ezin da erabili ahotsa erabiltzeko"</string>
     <string name="popup_window_default_title" msgid="4874318849712115433">"Leiho gainerakorra"</string>
     <string name="slice_more_content" msgid="8504342889413274608">"Beste <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
-    <string name="shortcut_restored_on_lower_version" msgid="5270675146351613828">"Aplikazioaren bertsio berriena behar da lasterbideak funtziona dezan"</string>
+    <string name="shortcut_restored_on_lower_version" msgid="4860853725206702336">"Aplikazioaren bertsio zaharrago batera aldatu da, edo aplikazioa ez da lasterbide honekin bateragarria"</string>
     <string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Ezin izan da leheneratu lasterbidea aplikazioak ez duelako onartzen babeskopiak egiteko eta leheneratzeko aukera"</string>
     <string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Ezin izan da leheneratu lasterbidea aplikazioaren sinadurak ez datozelako bat"</string>
     <string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Ezin izan da leheneratu lasterbidea"</string>
     <string name="shortcut_disabled_reason_unknown" msgid="5276016910284687075">"Desgaituta dago lasterbidea"</string>
-    <!-- no translation found for harmful_app_warning_uninstall (4837672735619532931) -->
-    <skip />
-    <!-- no translation found for harmful_app_warning_open_anyway (596432803680914321) -->
-    <skip />
-    <!-- no translation found for harmful_app_warning_title (8982527462829423432) -->
-    <skip />
+    <string name="harmful_app_warning_uninstall" msgid="4837672735619532931">"DESINSTALATU"</string>
+    <string name="harmful_app_warning_open_anyway" msgid="596432803680914321">"IREKI, HALA ERE"</string>
+    <string name="harmful_app_warning_title" msgid="8982527462829423432">"Aplikazio kaltegarri bat hauteman da"</string>
     <string name="slices_permission_request" msgid="8484943441501672932">"<xliff:g id="APP_0">%1$s</xliff:g> aplikazioak <xliff:g id="APP_2">%2$s</xliff:g> aplikazioaren zatiak erakutsi nahi ditu"</string>
     <string name="screenshot_edit" msgid="7867478911006447565">"Editatu"</string>
 </resources>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 2891b8c..ade233c 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -355,6 +355,8 @@
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"Permet à l\'application de rendre certains de ces composants persistants dans la mémoire. Cette autorisation peut limiter la mémoire disponible pour d\'autres applications et ralentir la tablette."</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"Permet à l\'application de placer certaines de ses parties en permanence dans la mémoire. Cela peut limiter la mémoire disponible pour les autres applications et ralentir le téléviseur."</string>
     <string name="permdesc_persistentActivity" product="default" msgid="4384760047508278272">"Permet à l\'application de rendre certains de ces composants persistants dans la mémoire. Cette autorisation peut limiter la mémoire disponible pour d\'autres applications et ralentir le téléphone."</string>
+    <string name="permlab_foregroundService" msgid="3310786367649133115">"exécuter le service en premier plan"</string>
+    <string name="permdesc_foregroundService" msgid="6471634326171344622">"Permet à l\'application d\'utiliser les services en premier plan."</string>
     <string name="permlab_getPackageSize" msgid="7472921768357981986">"évaluer l\'espace de stockage de l\'application"</string>
     <string name="permdesc_getPackageSize" msgid="3921068154420738296">"Permet à l\'application de récupérer la taille de son code, de ses données et de sa mémoire cache."</string>
     <string name="permlab_writeSettings" msgid="2226195290955224730">"modifier les paramètres du système"</string>
@@ -497,10 +499,8 @@
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Trop de tentatives. Veuillez réessayer plus tard."</string>
     <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Trop de tentatives. Capteur d\'empreintes digitales désactivé."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Réessayer."</string>
-    <!-- no translation found for fingerprint_error_no_fingerprints (7654382120628334248) -->
-    <skip />
-    <!-- no translation found for fingerprint_error_hw_not_present (5729436878065119329) -->
-    <skip />
+    <string name="fingerprint_error_no_fingerprints" msgid="7654382120628334248">"Aucune empreinte digitale enregistrée."</string>
+    <string name="fingerprint_error_hw_not_present" msgid="5729436878065119329">"Cet appareil ne possède pas de capteur d\'empreintes digitales"</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Doigt <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
@@ -1211,23 +1211,15 @@
     <string name="no_permissions" msgid="7283357728219338112">"Aucune autorisation requise"</string>
     <string name="perm_costs_money" msgid="4902470324142151116">"cela peut engendrer des frais"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
-    <!-- no translation found for usb_charging_notification_title (1595122345358177163) -->
-    <skip />
-    <!-- no translation found for usb_supplying_notification_title (4631045789893086181) -->
-    <skip />
-    <!-- no translation found for usb_mtp_notification_title (4238227258391151029) -->
-    <skip />
-    <!-- no translation found for usb_ptp_notification_title (5425857879922006878) -->
-    <skip />
-    <!-- no translation found for usb_tether_notification_title (3716143122035802501) -->
-    <skip />
-    <!-- no translation found for usb_midi_notification_title (5356040379749154805) -->
-    <skip />
-    <!-- no translation found for usb_accessory_notification_title (1899977434994900306) -->
-    <skip />
+    <string name="usb_charging_notification_title" msgid="1595122345358177163">"Chargement de cet appareil par USB"</string>
+    <string name="usb_supplying_notification_title" msgid="4631045789893086181">"Chargement de l\'appareil connecté par USB"</string>
+    <string name="usb_mtp_notification_title" msgid="4238227258391151029">"Transfert de fichiers USB activé"</string>
+    <string name="usb_ptp_notification_title" msgid="5425857879922006878">"Mode PTP par USB activé"</string>
+    <string name="usb_tether_notification_title" msgid="3716143122035802501">"Partage de connexion USB activé"</string>
+    <string name="usb_midi_notification_title" msgid="5356040379749154805">"Mode MIDI par USB activé"</string>
+    <string name="usb_accessory_notification_title" msgid="1899977434994900306">"Mode accessoire USB activé"</string>
     <string name="usb_notification_message" msgid="3370903770828407960">"Touchez pour afficher plus d\'options."</string>
-    <!-- no translation found for usb_power_notification_message (4647527153291917218) -->
-    <skip />
+    <string name="usb_power_notification_message" msgid="4647527153291917218">"Chargement de l\'appareil connecté. Touchez l\'écran pour afficher plus d\'options."</string>
     <string name="usb_unsupported_audio_accessory_title" msgid="3529881374464628084">"Un accessoire audio analogique a été détecté"</string>
     <string name="usb_unsupported_audio_accessory_message" msgid="6309553946441565215">"L\'appareil connecté n\'est pas compatible avec ce téléphone. Touchez ici en savoir plus."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Débogage USB activé"</string>
@@ -1830,8 +1822,7 @@
     <string name="mmcc_illegal_me" msgid="1950705155760872972">"Ce téléphone n\'est pas autorisé pour la voix"</string>
     <string name="popup_window_default_title" msgid="4874318849712115433">"Fenêtre contextuelle"</string>
     <string name="slice_more_content" msgid="8504342889413274608">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
-    <!-- no translation found for shortcut_restored_on_lower_version (4860853725206702336) -->
-    <skip />
+    <string name="shortcut_restored_on_lower_version" msgid="4860853725206702336">"La version de l\'application a été rétrogradée ou n\'est pas compatible avec ce raccourci"</string>
     <string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Impossible de restaurer le raccourci, car l\'application ne prend pas en charge la sauvegarde et la restauration"</string>
     <string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Impossible de restaurer le raccourci en raison d\'une erreur de correspondance des signature d\'applications"</string>
     <string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Impossible de restaurer le raccourci"</string>
diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml
index 0b7b7d09..efee736 100644
--- a/core/res/res/values-hy/strings.xml
+++ b/core/res/res/values-hy/strings.xml
@@ -264,10 +264,8 @@
     <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string>
     <string name="safeMode" msgid="2788228061547930246">"Անվտանգ ռեժիմ"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android համակարգ"</string>
-    <!-- no translation found for user_owner_label (8836124313744349203) -->
-    <skip />
-    <!-- no translation found for managed_profile_label (8947929265267690522) -->
-    <skip />
+    <string name="user_owner_label" msgid="8836124313744349203">"Բացել անձնական պրոֆիլը"</string>
+    <string name="managed_profile_label" msgid="8947929265267690522">"Բացել աշխատանքային պրոֆիլը"</string>
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"Կոնտակտներ"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"օգտագործել ձեր կոնտակտները"</string>
     <string name="permgrouprequest_contacts" msgid="1601591667800538208">"Թույլ տալ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; հավելվածին օգտագործել ձեր կոնտակտները"</string>
@@ -357,6 +355,8 @@
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"Թույլ է տալիս հավելվածին մնայուն դարձնել իր մասերը հիշողության մեջ: Սա կարող է սահմանափակել այլ հավելվածներին հասանելի հիշողությունը` դանդաղեցնելով պլանշետի աշխատանքը:"</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"Թույլ է տալիս հավելվածին պահել իր տարրերը հիշողության մեջ: Սա կարող է սահմանափակել այլ հավելվածների համար հատկացված հիշողությունը և դանդաղեցնել հեռուստացույցի աշխատանքը:"</string>
     <string name="permdesc_persistentActivity" product="default" msgid="4384760047508278272">"Թույլ է տալիս հավելվածին մնայուն դարձնել իր մասերը հիշողության մեջ: Սա կարող է սահմանափակել այլ հավելվածներին հասանելի հիշողությունը` դանդաղեցնելով հեռախոսի աշխատանքը:"</string>
+    <string name="permlab_foregroundService" msgid="3310786367649133115">"աշխատեցնել ակտիվ ծառայությունները"</string>
+    <string name="permdesc_foregroundService" msgid="6471634326171344622">"Թույլ է տալիս հավելվածին օգտագործել ակտիվ ծառայությունները:"</string>
     <string name="permlab_getPackageSize" msgid="7472921768357981986">"չափել հավելվածի պահոցի տարածքը"</string>
     <string name="permdesc_getPackageSize" msgid="3921068154420738296">"Թույլ է տալիս հավելվածին առբերել իր կոդը, տվյալները և քեշի չափերը"</string>
     <string name="permlab_writeSettings" msgid="2226195290955224730">"փոփոխել համակարգի կարգավորումները"</string>
@@ -419,10 +419,8 @@
     <string name="permdesc_readPhoneState" msgid="1639212771826125528">"Թույլ է տալիս հավելվածին օգտագործել սարքի հեռախոսային գործիքները: Այս թույլտվությունը հավելվածին հնարավորություն է տալիս որոշել հեռախոսահամարը և սարքի ID-ները, արդյոք զանգը ակտիվ է և միացված զանգի հեռակա հեռախոսահամարը:"</string>
     <string name="permlab_manageOwnCalls" msgid="1503034913274622244">"զանգերն ուղարկել համակարգի միջոցով"</string>
     <string name="permdesc_manageOwnCalls" msgid="6552974537554717418">"Հավելվածին թույլ է տալիս իր զանգերն ուղարկել համակարգի միջոցով՝ կապի որակը բարձրացնելու նպատակով։"</string>
-    <!-- no translation found for permlab_acceptHandover (2661534649736022409) -->
-    <skip />
-    <!-- no translation found for permdesc_acceptHandovers (4570660484220539698) -->
-    <skip />
+    <string name="permlab_acceptHandover" msgid="2661534649736022409">"շարունակել զանգը այլ հավելվածի միջոցով"</string>
+    <string name="permdesc_acceptHandovers" msgid="4570660484220539698">"Թույլ է տալիս հավելվածին շարունակել մեկ այլ հավելվածի միջոցով սկսած զանգը:"</string>
     <string name="permlab_readPhoneNumbers" msgid="6108163940932852440">"օգտագործել հեռախոսահամարները"</string>
     <string name="permdesc_readPhoneNumbers" msgid="8559488833662272354">"Հավելվածին թույլ է տալիս օգտագործել սարքի հեռախոսահամարները:"</string>
     <string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"զերծ պահել պլանշետը քնելուց"</string>
@@ -497,11 +495,12 @@
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Հնարավոր չէ պահել մատնահետքը: Հեռացրեք առկա մատնահետքը:"</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Մատնահետքի գրանցման ժամանակը սպառվել է: Փորձեք նորից:"</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Իսկորոշումը մատնահետքի միջոցով չեղարկվեց:"</string>
-    <!-- no translation found for fingerprint_error_user_canceled (7999639584615291494) -->
-    <skip />
+    <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"Մատնահետքով նույնականացման գործողությունը չեղարկվել է օգտատիրոջ կողմից:"</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Չափից շատ փորձ եք կատարել: Փորձեք նորից քիչ հետո:"</string>
     <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Չափից շատ փորձ եք կատարել: Մատնահետքերի սկաներն անջատվել է:"</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Փորձեք նորից:"</string>
+    <string name="fingerprint_error_no_fingerprints" msgid="7654382120628334248">"Գրանցված մատնահետք չկա:"</string>
+    <string name="fingerprint_error_hw_not_present" msgid="5729436878065119329">"Սարքը չունի մատնահետքի սկաներ"</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Մատնահետք <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
@@ -1000,12 +999,9 @@
     <string name="browse" msgid="1245903488306147205">"Բացել"</string>
     <string name="sms" msgid="4560537514610063430">"SMS գրել"</string>
     <string name="add_contact" msgid="7867066569670597203">"Ավելացնել"</string>
-    <!-- no translation found for view_calendar (979609872939597838) -->
-    <skip />
-    <!-- no translation found for add_calendar_event (1953664627192056206) -->
-    <skip />
-    <!-- no translation found for view_flight (7691640491425680214) -->
-    <skip />
+    <string name="view_calendar" msgid="979609872939597838">"Դիտել"</string>
+    <string name="add_calendar_event" msgid="1953664627192056206">"Ժամանակացույց"</string>
+    <string name="view_flight" msgid="7691640491425680214">"Հետագծել"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Հիշողությունը սպառվում է"</string>
     <string name="low_internal_storage_view_text" msgid="6640505817617414371">"Որոշ գործառույթներ կարող են չաշխատել"</string>
     <string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"Համակարգի համար բավարար հիշողություն չկա: Համոզվեք, որ ունեք 250ՄԲ ազատ տարածություն և վերագործարկեք:"</string>
@@ -1131,8 +1127,7 @@
       <item quantity="other">Հասանելի են չպաշտպանված Wi-Fi ցանցեր</item>
     </plurals>
     <string name="wifi_available_title" msgid="3817100557900599505">"Միացեք բաց Wi‑Fi ցանցին"</string>
-    <!-- no translation found for wifi_available_carrier_network_title (4527932626916527897) -->
-    <skip />
+    <string name="wifi_available_carrier_network_title" msgid="4527932626916527897">"Միացեք օպերատորի Wi‑Fi ցանցին"</string>
     <string name="wifi_available_title_connecting" msgid="1557292688310330032">"Միացում բաց Wi‑Fi ցանցին"</string>
     <string name="wifi_available_title_connected" msgid="7542672851522241548">"Միացել է Wi‑Fi ցանցին"</string>
     <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Չհաջողվեց միանալ Wi‑Fi ցանցին"</string>
@@ -1216,13 +1211,15 @@
     <string name="no_permissions" msgid="7283357728219338112">"Թույլտվություններ չեն պահանջվում"</string>
     <string name="perm_costs_money" msgid="4902470324142151116">"Սա կարող է գումար պահանջել"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"Հաստատել"</string>
-    <string name="usb_charging_notification_title" msgid="6895185153353640787">"Սարքի լիցքավորում USB լարի միջոցով"</string>
-    <string name="usb_supplying_notification_title" msgid="5310642257296510271">"Հոսանքի մատակարարում կցված սարքերին USB լարի միջոցով"</string>
-    <string name="usb_mtp_notification_title" msgid="8396264943589760855">"Ֆայլերի փոխանցման USB"</string>
-    <string name="usb_ptp_notification_title" msgid="1347328437083192112">"Լուսանկարների փոխանցման USB"</string>
-    <string name="usb_midi_notification_title" msgid="4850904915889144654">"MIDI-ի USB"</string>
-    <string name="usb_accessory_notification_title" msgid="7848236974087653666">"Կապակցված է USB լրասարքի"</string>
+    <string name="usb_charging_notification_title" msgid="1595122345358177163">"Սարքի լիցքավորում USB-ի միջոցով"</string>
+    <string name="usb_supplying_notification_title" msgid="4631045789893086181">"Միացված սարքի լիցքավորում USB-ի միջոցով"</string>
+    <string name="usb_mtp_notification_title" msgid="4238227258391151029">"Ֆայլերի փոխանցումը USB-ի միջոցով միացավ"</string>
+    <string name="usb_ptp_notification_title" msgid="5425857879922006878">"PTP ռեժիմը USB-ի միջոցով միացավ"</string>
+    <string name="usb_tether_notification_title" msgid="3716143122035802501">"USB մոդեմի ռեժիմը միացավ"</string>
+    <string name="usb_midi_notification_title" msgid="5356040379749154805">"MIDI ռեժիմը USB-ի միջոցով միացավ"</string>
+    <string name="usb_accessory_notification_title" msgid="1899977434994900306">"USB լրասարքի ռեժիմը միացավ"</string>
     <string name="usb_notification_message" msgid="3370903770828407960">"Հպեք՝ լրացուցիչ ընտրանքների համար:"</string>
+    <string name="usb_power_notification_message" msgid="4647527153291917218">"Միացված սարքի լիցքավորում: Հպեք՝ ավելի շատ ընտրանքների համար:"</string>
     <string name="usb_unsupported_audio_accessory_title" msgid="3529881374464628084">"Հայտնաբերված է անալոգային աուդիո լրասարք"</string>
     <string name="usb_unsupported_audio_accessory_message" msgid="6309553946441565215">"Միացված սարքը համատեղելի չէ այս հեռախոսի հետ: Հպեք` ավելին իմանալու համար:"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB վրիպազերծումը միացված է"</string>
@@ -1458,7 +1455,7 @@
     <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"Գրասալիկ"</string>
     <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"Հեռուստացույց"</string>
     <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Հեռախոս"</string>
-    <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Համակցված բարձրախոսներ"</string>
+    <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Դոկ-կայանի բարձրախոսներ"</string>
     <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string>
     <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Ականջակալներ"</string>
     <string name="default_audio_route_name_usb" msgid="1234984851352637769">"USB"</string>
@@ -1661,9 +1658,6 @@
     <string name="managed_profile_label_badge" msgid="2355652472854327647">"Աշխատանքային <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2-րդ աշխատանք <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3-րդ աշխատանք <xliff:g id="LABEL">%1$s</xliff:g>"</string>
-    <string name="lock_to_app_toast" msgid="6820571533009838261">"Այս էկրանն ապամրացնելու համար հպեք և պահեք Հետ և Համատեսք կոճակները"</string>
-    <string name="lock_to_app_start" msgid="6643342070839862795">"Էկրանն ամրացված է"</string>
-    <string name="lock_to_app_exit" msgid="8598219838213787430">"Էկրանն ապամրացված է"</string>
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Ապաամրացնելուց առաջ հարցնել PIN-կոդը"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Ապաամրացնելուց առաջ հարցնել ապակողպող նախշը"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Ապաամրացնելուց առաջ հարցնել գաղտնաբառը"</string>
@@ -1757,15 +1751,11 @@
     <string name="language_picker_section_all" msgid="3097279199511617537">"Բոլոր լեզուները"</string>
     <string name="region_picker_section_all" msgid="8966316787153001779">"Բոլոր տարածաշրջանները"</string>
     <string name="locale_search_menu" msgid="2560710726687249178">"Որոնում"</string>
-    <!-- no translation found for work_mode_off_title (1118691887588435530) -->
-    <skip />
-    <!-- no translation found for work_mode_off_message (5130856710614337649) -->
-    <skip />
+    <string name="work_mode_off_title" msgid="1118691887588435530">"Միացնե՞լ աշխատանքային պրոֆիլը"</string>
+    <string name="work_mode_off_message" msgid="5130856710614337649">"Ձեր աշխատանքային հավելվածները, ծանուցումները, տվյալները և աշխատանքային պրոֆիլի մյուս գործառույթները կմիանան"</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"Միացնել"</string>
-    <!-- no translation found for deprecated_target_sdk_message (1449696506742572767) -->
-    <skip />
-    <!-- no translation found for deprecated_target_sdk_app_store (5032340500368495077) -->
-    <skip />
+    <string name="deprecated_target_sdk_message" msgid="1449696506742572767">"Այս հավելվածը ստեղծվել է Android-ի ավելի հին տարբերակի համար և կարող է պատշաճ չաշխատել: Ստուգեք թարմացումների առկայությունը կամ դիմեք մշակողին:"</string>
+    <string name="deprecated_target_sdk_app_store" msgid="5032340500368495077">"Ստուգել նոր տարբերակի առկայությունը"</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"Դուք ունեք նոր հաղորդագրություններ"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"Դիտելու համար բացել SMS հավելվածը"</string>
     <string name="user_encrypted_title" msgid="9054897468831672082">"Որոշ գործառույթներ կարող են սահմանափակված լինել"</string>
@@ -1832,17 +1822,14 @@
     <string name="mmcc_illegal_me" msgid="1950705155760872972">"Այս հեռախոսով չեք կարող զանգել"</string>
     <string name="popup_window_default_title" msgid="4874318849712115433">"Հայտնվող պատուհան"</string>
     <string name="slice_more_content" msgid="8504342889413274608">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
-    <string name="shortcut_restored_on_lower_version" msgid="5270675146351613828">"Այս դյուրանցման համար անհրաժեշտ է հավելվածի վերջին տարբերակը"</string>
+    <string name="shortcut_restored_on_lower_version" msgid="4860853725206702336">"Սա հավելվածի ավելի հին տարբերակն է կամ համատեղելի չէ այս դյուրանցման հետ"</string>
     <string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Չհաջողվեց վերականգնել դյուրանցումը, քանի որ հավելվածում չի աջակցվում պահուստավորման և վերականգնման գործառույթը"</string>
     <string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Չհաջողվեց վերականգնել դյուրանցումը, քանի որ հավելվածների ստորագրությունները տարբեր են"</string>
     <string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Չհաջողվեց վերականգնել դյուրանցումը"</string>
     <string name="shortcut_disabled_reason_unknown" msgid="5276016910284687075">"Դյուրանցումն անջատված է"</string>
-    <!-- no translation found for harmful_app_warning_uninstall (4837672735619532931) -->
-    <skip />
-    <!-- no translation found for harmful_app_warning_open_anyway (596432803680914321) -->
-    <skip />
-    <!-- no translation found for harmful_app_warning_title (8982527462829423432) -->
-    <skip />
+    <string name="harmful_app_warning_uninstall" msgid="4837672735619532931">"ՀԵՌԱՑՆԵԼ"</string>
+    <string name="harmful_app_warning_open_anyway" msgid="596432803680914321">"ԲԱՑԵԼ"</string>
+    <string name="harmful_app_warning_title" msgid="8982527462829423432">"Հայտնաբերվել է վնասաբեր հավելված"</string>
     <string name="slices_permission_request" msgid="8484943441501672932">"<xliff:g id="APP_0">%1$s</xliff:g> հավելվածն ուզում է ցուցադրել հատվածներ <xliff:g id="APP_2">%2$s</xliff:g> հավելվածից"</string>
     <string name="screenshot_edit" msgid="7867478911006447565">"Փոփոխել"</string>
 </resources>
diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml
index c9076ca..5ac81d5 100644
--- a/core/res/res/values-uz/strings.xml
+++ b/core/res/res/values-uz/strings.xml
@@ -355,6 +355,8 @@
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"Ilovaga o‘zining komponentlarini xotirada doimiy saqlashga ruxsat beradi. Bu mavjud xotirani cheklashi va planshetni sekin ishlashiga sabab bo‘lishi mumkin."</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"Ilovaga o‘zining muayyan qismlarining xotiraning turg‘un qismiga aylantirish huquqini beradi. Bunda, boshqa ilovalar uchun xotiradan ajratilgan joy cheklanib, televizorning ishlashi sekinlashishi mumkin."</string>
     <string name="permdesc_persistentActivity" product="default" msgid="4384760047508278272">"Ilovaga o‘zining komponentlarini xotirada doimiy saqlashga ruxsat beradi. Bu mavjud xotirani cheklashi va telefonni sekin ishlashiga sabab bo‘lishi mumkin."</string>
+    <string name="permlab_foregroundService" msgid="3310786367649133115">"faol xizmatlarni ishga tushirish"</string>
+    <string name="permdesc_foregroundService" msgid="6471634326171344622">"Ilovaga faol xizmatlardan foydalanishga ruxsat beradi."</string>
     <string name="permlab_getPackageSize" msgid="7472921768357981986">"ilovalar egallagan xotira joyini hisoblash"</string>
     <string name="permdesc_getPackageSize" msgid="3921068154420738296">"Ilova o‘zining kodi, ma’lumotlari va kesh o‘lchami to‘g‘risidagi ma’lumotlarni olishi mumkin"</string>
     <string name="permlab_writeSettings" msgid="2226195290955224730">"tizim sozlamalarini o‘zgartirish"</string>
@@ -497,10 +499,8 @@
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Urinishlar soni ko‘payib ketdi. Keyinroq qayta urinib ko‘ring."</string>
     <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Urinishlar soni ko‘payib ketdi. Barmoq izi skaneri bloklandi."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Qayta urinib ko‘ring."</string>
-    <!-- no translation found for fingerprint_error_no_fingerprints (7654382120628334248) -->
-    <skip />
-    <!-- no translation found for fingerprint_error_hw_not_present (5729436878065119329) -->
-    <skip />
+    <string name="fingerprint_error_no_fingerprints" msgid="7654382120628334248">"Hech qanday barmoq izi qayd qilinmagan."</string>
+    <string name="fingerprint_error_hw_not_present" msgid="5729436878065119329">"Bu qurilmada barmoq izi skaneri yo‘q"</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Barmoq izi <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
@@ -1212,23 +1212,15 @@
     <string name="no_permissions" msgid="7283357728219338112">"Hech qanday ruxsat talab qilinmaydi"</string>
     <string name="perm_costs_money" msgid="4902470324142151116">"buning uchun sizdan haq olinishi mumkin"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
-    <!-- no translation found for usb_charging_notification_title (1595122345358177163) -->
-    <skip />
-    <!-- no translation found for usb_supplying_notification_title (4631045789893086181) -->
-    <skip />
-    <!-- no translation found for usb_mtp_notification_title (4238227258391151029) -->
-    <skip />
-    <!-- no translation found for usb_ptp_notification_title (5425857879922006878) -->
-    <skip />
-    <!-- no translation found for usb_tether_notification_title (3716143122035802501) -->
-    <skip />
-    <!-- no translation found for usb_midi_notification_title (5356040379749154805) -->
-    <skip />
-    <!-- no translation found for usb_accessory_notification_title (1899977434994900306) -->
-    <skip />
+    <string name="usb_charging_notification_title" msgid="1595122345358177163">"Bu qurilma USB orqali quvvatlanmoqda"</string>
+    <string name="usb_supplying_notification_title" msgid="4631045789893086181">"USB orqali ulangan qurilma quvvatlanmoqda"</string>
+    <string name="usb_mtp_notification_title" msgid="4238227258391151029">"USB orqali fayl uzatish yoqildi"</string>
+    <string name="usb_ptp_notification_title" msgid="5425857879922006878">"USB orqali PTP rejimi yoqildi"</string>
+    <string name="usb_tether_notification_title" msgid="3716143122035802501">"USB modem rejimi yoqildi"</string>
+    <string name="usb_midi_notification_title" msgid="5356040379749154805">"USB orqali MIDI rejimi yoqildi"</string>
+    <string name="usb_accessory_notification_title" msgid="1899977434994900306">"USB qurilma ulandi"</string>
     <string name="usb_notification_message" msgid="3370903770828407960">"Boshqa parametrlarini ko‘rish uchun bosing."</string>
-    <!-- no translation found for usb_power_notification_message (4647527153291917218) -->
-    <skip />
+    <string name="usb_power_notification_message" msgid="4647527153291917218">"Ulangan qurilma quvvatlanmoqda. Boshqa parametrlar uchun bosing."</string>
     <string name="usb_unsupported_audio_accessory_title" msgid="3529881374464628084">"Analogli audio uskuna aniqlandi"</string>
     <string name="usb_unsupported_audio_accessory_message" msgid="6309553946441565215">"Biriktirilgan qurilma mazkur telefon bilan mos emas. Batafsil axborot olish uchun bu yerga bosing."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB orqali nosozliklarni tuzatish"</string>
@@ -1831,8 +1823,7 @@
     <string name="mmcc_illegal_me" msgid="1950705155760872972">"Ovoz uchun telefon taqiqlangan"</string>
     <string name="popup_window_default_title" msgid="4874318849712115433">"Qalqib chiquvchi oyna"</string>
     <string name="slice_more_content" msgid="8504342889413274608">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
-    <!-- no translation found for shortcut_restored_on_lower_version (4860853725206702336) -->
-    <skip />
+    <string name="shortcut_restored_on_lower_version" msgid="4860853725206702336">"Ilova versiyasi eski yoki bu yorliq bilan mos emas"</string>
     <string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Ilovada zaxiralash va tiklash ishlamagani uchun yorliq tiklanmadi"</string>
     <string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Ilova imzosi mos kelmagani uchun yorliq tiklanmadi"</string>
     <string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Yorliq tiklanmadi"</string>
diff --git a/core/res/res/values-watch/colors_device_defaults.xml b/core/res/res/values-watch/colors_device_defaults.xml
index 654e92c..6ffd6e6 100644
--- a/core/res/res/values-watch/colors_device_defaults.xml
+++ b/core/res/res/values-watch/colors_device_defaults.xml
@@ -14,48 +14,88 @@
      limitations under the License.
 -->
 
-<!-- Colors specific to DeviceDefault themes. These are mostly pass-throughs to enable
-     overlaying new theme colors. -->
+<!-- Colors specific to Theme.DeviceDefault on watches, as specified via themes_device_default.xml
+     Note: These colors specifically proide a darker, high-contrast UI that is suitable for
+     wearables with respect to 'glanceability'. OEM customization is supported within this set. -->
 <resources>
-
-    <!--
-       primary_device_default_dark
-         > from values/colors_material/primary_material_dark
-         > from values/colors_material/material_grey_900
-         = #ff212121
-         ! replaced with custom color #33ffffff
-    -->
-    <color name="primary_device_default_dark">#33ffffff</color>
-    <!--
-       primary_dark_device_default_dark
-         > from values/colors_material/primary_dark_material_dark
-         = @color/black
-    -->
-    <color name="primary_dark_device_default_dark">@color/black</color>
     <!--
        accent_device_default_dark
          > from values/colors_material/accent_material_dark
          > from values/colors_material/material_deep_teal_200
          = #ff80cbc4
          ! replaced with custom color #5E97F6
+         ! OEMS can customize as per specification
     -->
     <color name="accent_device_default_dark">#5E97F6</color>
+
+    <!--
+       foreground_device_default_dark
+         - introduced to avoid coupling to foreground_material_dark
+         - colorForeground typically falls through Theme.DeviceDefault to Theme.Material
+         ! fixed as white for optimal glanceability/contrast
+         ! OEMs should not customize
+    -->
+    <color name="foreground_device_default_dark">@color/white</color>
+
     <!--
        background_device_default_dark
          > from values/colors_material/background_material_dark
          > from values/colors_material/material_grey_850
          = #ff303030
-         ! replaced with custom color #232E33
+         ! replaced with custom color #000000
+         ! OEMs can customized as per specification
+           (derived from accent color, constrained by brightness)
     -->
-    <color name="background_device_default_dark">#232E33</color>
+    <color name="background_device_default_dark">#000000</color>
+
     <!--
        background_floating_device_default_dark
          > from values/colors_material/background_floating_material_dark
          > from values/colors_material/material_grey_800
          = #ff424242
-         ! replaced with custom color #3E5059
+         ! replaced with custom color #1D2E4D
+           (derived from accent color, constrained by brightness)
     -->
-    <color name="background_floating_device_default_dark">#3E5059</color>
+    <color name="background_floating_device_default_dark">#1D2E4D</color>
+
+    <!--
+       primary_device_default_dark
+         > from values/colors_material/primary_material_dark
+         > from values/colors_material/material_grey_900
+         = #ff212121
+         ! replaced with custom color #808080
+         ! OEMs can customize as per specification
+           (derived from background color + foreground @ 50% opacity)
+    -->
+    <color name="primary_device_default_dark">#808080</color>
+
+    <!--
+       primary_dark_device_default_dark
+         > from values/colors_material/primary_dark_material_dark
+         = @color/black
+         ! replaced with custom color #333333
+         ! OEMS can customize as per specification
+           (derived from background color + foreground @ 20% opacity)
+    -->
+    <color name="primary_dark_device_default_dark">#333333</color>
+
+    <!--
+       button_normal_device_default_dark
+         - uses ?attr/disabledAlpha and ?attr/colorPrimaryDark to draw state list
+           (used as colorButtonNormal attribute in theme)
+         - see color-watch/btn_watch_default_dark.xml
+    -->
+    <color name="button_normal_device_default_dark">@color/btn_watch_default_dark</color>
+
+    <!--
+       error_color_device_default_dark
+         - introduced to avoid coupling to error_color_mtterial (also #F4511E)
+         - colorError typically falls through Theme.DeviceDefault to Theme.Material
+         ! OEMs can customize as per specification
+    -->
+    <color name="error_color_device_default_dark">#F4511E</color>
+
+    <!-- no customization required/suggested below this point -->
 
     <!--
        background_cache_hint_selector_device_default
@@ -65,38 +105,12 @@
          - no color customization required here
     -->
 
-    <!--
-       button_normal_device_default_dark
-         - uses ?attr/disabledAlpha and button_material_dark to draw
-         - cloned to watch_btn_default.xml drawable
-           (btn_default_material_dark & button_material_dark - see
-           values-watch/colors_material.xml)
-    -->
-    <color name="button_normal_device_default_dark">@color/btn_default_material_dark</color>
-
-    <!-- Use the same value as for accent_device_default_dark but start with #99,
-         i.e. 60% opacity -->
-    <color name="accent_device_default_dark_60_percent_opacity">#995E97f6</color>
-
-    <!--
-       foreground_device_default_dark
-         - introduced to avoid coupling to foreground_material_dark
-         - colorForeground typically falls through Theme.DeviceDefault to Theme.Material
-    -->
-    <color name="foreground_device_default_dark">@color/white</color>
-
-    <!--
-       error_color_device_default_dark
-         - introduced to avoid coupling to error_color_material (also #F4511E)
-         - colorError typically falls through Theme.DeviceDefault to Theme.Material
-    -->
-    <color name="error_color_device_default_dark">#F4511E</color>
-
     <!-- deprecated for Wear
          these overrides exist only for compatibility with existing
          WTS theme test heuristics, based on the previous modifications
          to the material theme, they should not be used for customization
          as they are not exposed via publicly accessible attributes -->
+    <color name="accent_device_default_dark_60_percent_opacity">#995E97f6</color>
     <color name="accent_device_default_700">#5385DB</color>
     <color name="accent_device_default_light">#75A4F5</color>
     <color name="accent_device_default_50">#93B7F5</color>
diff --git a/core/res/res/values-watch/colors_material.xml b/core/res/res/values-watch/colors_material.xml
deleted file mode 100644
index b19820c..0000000
--- a/core/res/res/values-watch/colors_material.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
--->
-<resources>
-
-  <!-- referenced in colors/watch_btn_default.xml selector -->
-  <color name="button_material_dark">#ff919699</color>
-
-</resources>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index d2194ba..cf7925b 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -3311,4 +3311,9 @@
     <!-- IWLAN network service package name to bind to by default. If none is specified in an overlay, an
          empty string is passed in -->
     <string name="config_wlan_network_service_package" translatable="false"></string>
+
+    <!-- Wear devices: Controls the radios affected by Activity Mode. -->
+    <string-array name="config_wearActivityModeRadios">
+        <item>"wifi"</item>
+    </string-array>
 </resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 2b7b056..ec81df7 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -916,11 +916,6 @@
     <string name="permdesc_persistentActivity" product="default">Allows the app to make parts of itself persistent in memory.  This can limit memory available to other apps slowing down the phone.</string>
 
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
-    <string name="permlab_foregroundService">run foreground service</string>
-    <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
-    <string name="permdesc_foregroundService">Allows the app to make use of foreground services.</string>
-
-    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permlab_getPackageSize">measure app storage space</string>
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permdesc_getPackageSize">Allows the app to retrieve its code, data, and cache sizes</string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index ca698ef..a86f58a 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1716,6 +1716,7 @@
   <java-symbol type="string" name="bugreport_status" />
   <java-symbol type="string" name="bugreport_title" />
   <java-symbol type="string" name="faceunlock_multiple_failures" />
+  <java-symbol type="string" name="global_actions" />
   <java-symbol type="string" name="global_action_power_off" />
   <java-symbol type="string" name="global_action_restart" />
   <java-symbol type="string" name="global_actions_airplane_mode_off_status" />
@@ -3254,4 +3255,7 @@
   <java-symbol type="bool" name="config_keepRestrictedProfilesInBackground" />
 
   <java-symbol type="array" name="config_ringtoneEffectUris" />
+
+  <!-- For Wear devices -->
+  <java-symbol type="array" name="config_wearActivityModeRadios" />
 </resources>
diff --git a/core/tests/coretests/AndroidManifest.xml b/core/tests/coretests/AndroidManifest.xml
index 53c22f6..7d5c60a 100644
--- a/core/tests/coretests/AndroidManifest.xml
+++ b/core/tests/coretests/AndroidManifest.xml
@@ -51,7 +51,6 @@
     <uses-permission android:name="android.permission.CLEAR_APP_USER_DATA" />
     <uses-permission android:name="android.permission.DELETE_CACHE_FILES" />
     <uses-permission android:name="android.permission.DOWNLOAD_CACHE_NON_PURGEABLE" />
-    <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
     <uses-permission android:name="android.permission.GET_PACKAGE_SIZE" />
     <uses-permission android:name="android.permission.INTERNET" />
     <uses-permission android:name="android.permission.INJECT_EVENTS" />
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index 853a36d..a0b6297 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -220,7 +220,7 @@
                     Settings.Global.ENABLE_DELETION_HELPER_NO_THRESHOLD_TOGGLE,
                     Settings.Global.ENABLE_DISKSTATS_LOGGING,
                     Settings.Global.ENABLE_EPHEMERAL_FEATURE,
-                    Settings.Global.ENABLE_SMART_REPLIES_IN_NOTIFICATIONS,
+                    Settings.Global.SMART_REPLIES_IN_NOTIFICATIONS_FLAGS,
                     Settings.Global.ENHANCED_4G_MODE_ENABLED,
                     Settings.Global.EPHEMERAL_COOKIE_MAX_SIZE_BYTES,
                     Settings.Global.ERROR_LOGCAT_PREFIX,
@@ -366,6 +366,7 @@
                     Settings.Global.SQLITE_COMPATIBILITY_WAL_FLAGS,
                     Settings.Global.STORAGE_BENCHMARK_INTERVAL,
                     Settings.Global.STORAGE_SETTINGS_CLOBBER_THRESHOLD,
+                    Settings.Global.SYNC_MANAGER_CONSTANTS,
                     Settings.Global.SYNC_MAX_RETRY_DELAY_IN_SECONDS,
                     Settings.Global.SYS_FREE_STORAGE_LOG_INTERVAL,
                     Settings.Global.SYS_STORAGE_CACHE_MAX_BYTES,
diff --git a/core/tests/coretests/src/android/service/euicc/EuiccProfileInfoTest.java b/core/tests/coretests/src/android/service/euicc/EuiccProfileInfoTest.java
index 1e3ddf3..e69d1e7 100644
--- a/core/tests/coretests/src/android/service/euicc/EuiccProfileInfoTest.java
+++ b/core/tests/coretests/src/android/service/euicc/EuiccProfileInfoTest.java
@@ -30,14 +30,15 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.util.Arrays;
+
 @SmallTest
 @RunWith(AndroidJUnit4.class)
 public class EuiccProfileInfoTest {
     @Test
     public void testWriteToParcel() {
         EuiccProfileInfo p =
-                new EuiccProfileInfo.Builder()
-                        .setIccid("21430000000000006587")
+                new EuiccProfileInfo.Builder("21430000000000006587")
                         .setNickname("profile nickname")
                         .setServiceProviderName("service provider")
                         .setProfileName("profile name")
@@ -50,9 +51,7 @@
                                         "45"))
                         .setPolicyRules(EuiccProfileInfo.POLICY_RULE_DO_NOT_DELETE)
                         .setUiccAccessRule(
-                                new UiccAccessRule[] {
-                                        new UiccAccessRule(new byte[] {}, "package", 12345L)
-                                })
+                                Arrays.asList(new UiccAccessRule(new byte[] {}, "package", 12345L)))
                         .build();
 
         Parcel parcel = Parcel.obtain();
@@ -68,8 +67,7 @@
     @Test
     public void testWriteToParcelNullCarrierId() {
         EuiccProfileInfo p =
-                new EuiccProfileInfo.Builder()
-                        .setIccid("21430000000000006587")
+                new EuiccProfileInfo.Builder("21430000000000006587")
                         .setNickname("profile nickname")
                         .setServiceProviderName("service provider")
                         .setProfileName("profile name")
@@ -77,9 +75,8 @@
                         .setState(EuiccProfileInfo.PROFILE_STATE_ENABLED)
                         .setPolicyRules(EuiccProfileInfo.POLICY_RULE_DO_NOT_DELETE)
                         .setUiccAccessRule(
-                                new UiccAccessRule[] {
-                                        new UiccAccessRule(new byte[] {}, "package", 12345L)
-                                })
+                                Arrays.asList(new UiccAccessRule(new byte[] {}, "package", 12345L))
+                        )
                         .build();
 
         Parcel parcel = Parcel.obtain();
@@ -95,8 +92,7 @@
     @Test
     public void testBuilderAndGetters() {
         EuiccProfileInfo p =
-                new EuiccProfileInfo.Builder()
-                        .setIccid("21430000000000006587")
+                new EuiccProfileInfo.Builder("21430000000000006587")
                         .setNickname("profile nickname")
                         .setProfileName("profile name")
                         .setServiceProviderName("service provider")
@@ -108,10 +104,7 @@
                         .setState(EuiccProfileInfo.PROFILE_STATE_ENABLED)
                         .setProfileClass(EuiccProfileInfo.PROFILE_CLASS_OPERATIONAL)
                         .setPolicyRules(EuiccProfileInfo.POLICY_RULE_DO_NOT_DELETE)
-                        .setUiccAccessRule(
-                                new UiccAccessRule[] {
-                                        new UiccAccessRule(new byte[0], null, 0)
-                                })
+                        .setUiccAccessRule(Arrays.asList(new UiccAccessRule(new byte[0], null, 0)))
                         .build();
 
         assertEquals("21430000000000006587", p.getIccid());
@@ -130,14 +123,13 @@
         assertFalse(p.hasPolicyRule(EuiccProfileInfo.POLICY_RULE_DO_NOT_DISABLE));
         assertArrayEquals(
                 new UiccAccessRule[] {new UiccAccessRule(new byte[0], null, 0)},
-                p.getUiccAccessRules());
+                p.getUiccAccessRules().toArray());
     }
 
     @Test
     public void testBuilder_BasedOnAnotherProfile() {
         EuiccProfileInfo p =
-                new EuiccProfileInfo.Builder()
-                        .setIccid("21430000000000006587")
+                new EuiccProfileInfo.Builder("21430000000000006587")
                         .setNickname("profile nickname")
                         .setProfileName("profile name")
                         .setServiceProviderName("service provider")
@@ -150,9 +142,7 @@
                         .setProfileClass(EuiccProfileInfo.PROFILE_CLASS_OPERATIONAL)
                         .setPolicyRules(EuiccProfileInfo.POLICY_RULE_DO_NOT_DELETE)
                         .setUiccAccessRule(
-                                new UiccAccessRule[] {
-                                        new UiccAccessRule(new byte[0], null, 0)
-                                })
+                                Arrays.asList(new UiccAccessRule(new byte[] {}, "package", 12345L)))
                         .build();
 
         EuiccProfileInfo copied = new EuiccProfileInfo.Builder(p).build();
@@ -164,8 +154,7 @@
     @Test
     public void testEqualsHashCode() {
         EuiccProfileInfo p =
-                new EuiccProfileInfo.Builder()
-                        .setIccid("21430000000000006587")
+                new EuiccProfileInfo.Builder("21430000000000006587")
                         .setNickname("profile nickname")
                         .setProfileName("profile name")
                         .setServiceProviderName("service provider")
@@ -177,10 +166,7 @@
                         .setState(EuiccProfileInfo.PROFILE_STATE_ENABLED)
                         .setProfileClass(EuiccProfileInfo.PROFILE_STATE_ENABLED)
                         .setPolicyRules(EuiccProfileInfo.POLICY_RULE_DO_NOT_DELETE)
-                        .setUiccAccessRule(
-                                new UiccAccessRule[] {
-                                        new UiccAccessRule(new byte[0], null, 0)
-                                })
+                        .setUiccAccessRule(Arrays.asList(new UiccAccessRule(new byte[0], null, 0)))
                         .build();
 
         assertTrue(p.equals(p));
@@ -229,13 +215,13 @@
     }
 
     @Test(expected = IllegalStateException.class)
-    public void testBuilderBuild_NoIccid() {
-        new EuiccProfileInfo.Builder().build();
+    public void testBuilderBuild_IllegalIccid() {
+        new EuiccProfileInfo.Builder("abc").build();
     }
 
     @Test(expected = IllegalArgumentException.class)
     public void testBuilderSetOperatorMccMnc_Illegal() {
-        new EuiccProfileInfo.Builder()
+        new EuiccProfileInfo.Builder("21430000000000006587")
                 .setCarrierIdentifier(new CarrierIdentifier(new byte[] {1, 2, 3, 4}, null, null));
     }
 
diff --git a/core/tests/coretests/src/android/view/textclassifier/TextClassificationTest.java b/core/tests/coretests/src/android/view/textclassifier/TextClassificationTest.java
index cf41eb8..ada19fc 100644
--- a/core/tests/coretests/src/android/view/textclassifier/TextClassificationTest.java
+++ b/core/tests/coretests/src/android/view/textclassifier/TextClassificationTest.java
@@ -19,6 +19,7 @@
 import static org.junit.Assert.assertEquals;
 
 import android.content.Intent;
+import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.Color;
 import android.graphics.drawable.BitmapDrawable;
@@ -47,7 +48,7 @@
             colors[i] = colorValue;
         }
         final Bitmap bitmap = Bitmap.createBitmap(colors, width, height, Bitmap.Config.ARGB_8888);
-        final BitmapDrawable drawable = new BitmapDrawable(null, bitmap);
+        final BitmapDrawable drawable = new BitmapDrawable(Resources.getSystem(), bitmap);
         drawable.setTargetDensity(bitmap.getDensity());
         return drawable;
     }
diff --git a/core/tests/coretests/src/com/android/internal/os/BstatsCpuTimesValidationTest.java b/core/tests/coretests/src/com/android/internal/os/BstatsCpuTimesValidationTest.java
index ce3ffb9..d425dcc 100644
--- a/core/tests/coretests/src/com/android/internal/os/BstatsCpuTimesValidationTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BstatsCpuTimesValidationTest.java
@@ -59,6 +59,7 @@
 import android.util.DebugUtils;
 import android.util.Log;
 
+import org.junit.AfterClass;
 import org.junit.BeforeClass;
 import org.junit.Rule;
 import org.junit.Test;
@@ -118,6 +119,11 @@
         checkCpuTimesAvailability();
     }
 
+    @AfterClass
+    public static void tearDownOnce() throws Exception {
+        batteryReset();
+    }
+
     // Checks cpu freq times of system uid as an indication of whether /proc/uid_time_in_state
     // and /proc/uid/<uid>/time_in_state kernel nodes are available.
     private static void checkCpuTimesAvailability() throws Exception {
@@ -127,7 +133,7 @@
         final long[] totalCpuTimes = getAllCpuFreqTimes(Process.SYSTEM_UID);
         sCpuFreqTimesAvailable = totalCpuTimes != null;
         final long[] fgSvcCpuTimes = getAllCpuFreqTimes(Process.SYSTEM_UID,
-                PROCESS_STATE_FOREGROUND_SERVICE);
+                PROCESS_STATE_FOREGROUND);
         sPerProcStateTimesAvailable = fgSvcCpuTimes != null;
     }
 
@@ -868,12 +874,16 @@
 
     private static void batteryOn() throws Exception {
         executeCmd("dumpsys battery unplug");
-        assertBatteryState(false);
+        assertBatteryState(false /* pluggedIn */);
     }
 
     private static void batteryOff() throws Exception {
+        executeCmd("dumpsys battery set ac " + BatteryManager.BATTERY_PLUGGED_AC);
+        assertBatteryState(true /* pluggedIn */);
+    }
+
+    private static void batteryReset() throws Exception {
         executeCmd("dumpsys battery reset");
-        assertBatteryState(true);
     }
 
     private void screenOn() throws Exception {
diff --git a/core/tests/coretests/src/com/android/internal/os/KernelSingleUidTimeReaderTest.java b/core/tests/coretests/src/com/android/internal/os/KernelSingleUidTimeReaderTest.java
index 5d72942..29227f9 100644
--- a/core/tests/coretests/src/com/android/internal/os/KernelSingleUidTimeReaderTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/KernelSingleUidTimeReaderTest.java
@@ -115,6 +115,30 @@
     }
 
     @Test
+    public void readDelta_incorrectCount() {
+        assertTrue(mReader.singleUidCpuTimesAvailable());
+
+        long[] cpuTimes = new long[TEST_FREQ_COUNT - 1];
+        for (int i = 0; i < cpuTimes.length; ++i) {
+            cpuTimes[i] = 111 + i;
+        }
+        mInjector.setData(cpuTimes);
+        assertCpuTimesEqual(null, mReader.readDeltaMs(TEST_UID));
+        assertFalse(mReader.singleUidCpuTimesAvailable());
+
+        // Reset
+        mReader.setSingleUidCpuTimesAvailable(true);
+
+        cpuTimes = new long[TEST_FREQ_COUNT + 1];
+        for (int i = 0; i < cpuTimes.length; ++i) {
+            cpuTimes[i] = 222 + i;
+        }
+        mInjector.setData(cpuTimes);
+        assertCpuTimesEqual(null, mReader.readDeltaMs(TEST_UID));
+        assertFalse(mReader.singleUidCpuTimesAvailable());
+    }
+
+    @Test
     public void testComputeDelta() {
         // proc file not available
         mReader.setSingleUidCpuTimesAvailable(false);
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 3495b84..9d1fdbd 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -176,7 +176,7 @@
         <permission name="android.permission.UPDATE_LOCK"/>
         <permission name="android.permission.WRITE_APN_SETTINGS"/>
         <permission name="android.permission.WRITE_SECURE_SETTINGS"/>
-        <permission name="com.android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS"/>
+        <permission name="android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS"/>
         <permission name="com.android.voicemail.permission.READ_VOICEMAIL"/>
         <permission name="com.android.voicemail.permission.WRITE_VOICEMAIL"/>
     </privapp-permissions>
@@ -381,7 +381,7 @@
         <permission name="android.permission.WRITE_DREAM_STATE"/>
         <permission name="android.permission.WRITE_MEDIA_STORAGE"/>
         <permission name="android.permission.WRITE_SECURE_SETTINGS"/>
-        <permission name="com.android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS"/>
+        <permission name="android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS"/>
     </privapp-permissions>
 
     <privapp-permissions package="com.android.tv">
diff --git a/graphics/java/android/graphics/BaseCanvas.java b/graphics/java/android/graphics/BaseCanvas.java
index eacb727..07df045 100644
--- a/graphics/java/android/graphics/BaseCanvas.java
+++ b/graphics/java/android/graphics/BaseCanvas.java
@@ -22,7 +22,7 @@
 import android.annotation.Size;
 import android.graphics.Canvas.VertexMode;
 import android.text.GraphicsOperations;
-import android.text.MeasuredText;
+import android.text.PrecomputedText;
 import android.text.SpannableString;
 import android.text.SpannedString;
 import android.text.TextUtils;
@@ -487,8 +487,8 @@
             TextUtils.getChars(text, contextStart, contextEnd, buf, 0);
             long measuredTextPtr = 0;
             int measuredTextOffset = 0;
-            if (text instanceof MeasuredText) {
-                MeasuredText mt = (MeasuredText) text;
+            if (text instanceof PrecomputedText) {
+                PrecomputedText mt = (PrecomputedText) text;
                 int paraIndex = mt.findParaIndex(start);
                 if (end <= mt.getParagraphEnd(paraIndex)) {
                     // Only suppor the same paragraph.
@@ -647,7 +647,7 @@
 
     private static native void nDrawTextRun(long nativeCanvas, char[] text, int start, int count,
             int contextStart, int contextCount, float x, float y, boolean isRtl, long nativePaint,
-            long nativeMeasuredText, int measuredTextOffset);
+            long nativePrecomputedText, int measuredTextOffset);
 
     private static native void nDrawTextOnPath(long nativeCanvas, char[] text, int index, int count,
             long nativePath, float hOffset, float vOffset, int bidiFlags, long nativePaint);
diff --git a/graphics/java/android/graphics/ImageDecoder.java b/graphics/java/android/graphics/ImageDecoder.java
index acefead..ee7abc5 100644
--- a/graphics/java/android/graphics/ImageDecoder.java
+++ b/graphics/java/android/graphics/ImageDecoder.java
@@ -444,7 +444,6 @@
     private boolean mPreferRamOverQuality = false;
     private boolean mAsAlphaMask = false;
     private Rect    mCropRect;
-    private Rect    mOutPaddingRect;
     private Source  mSource;
 
     private PostProcessor          mPostProcessor;
@@ -783,18 +782,6 @@
     }
 
     /**
-     *  Set a Rect for retrieving nine patch padding.
-     *
-     *  If the image is a nine patch, this Rect will be set to the padding
-     *  rectangle during decode. Otherwise it will not be modified.
-     *
-     *  @hide
-     */
-    public void setOutPaddingRect(@NonNull Rect outPadding) {
-        mOutPaddingRect = outPadding;
-    }
-
-    /**
      *  Specify whether the {@link Bitmap} should be mutable.
      *
      *  <p>By default, a {@link Bitmap} created will be immutable, but that can
@@ -905,6 +892,7 @@
                 postProcessPtr, mDesiredWidth, mDesiredHeight, mCropRect,
                 mMutable, mAllocator, mRequireUnpremultiplied,
                 mPreferRamOverQuality, mAsAlphaMask);
+
     }
 
     private void callHeaderDecoded(@Nullable OnHeaderDecodedListener listener,
@@ -977,10 +965,7 @@
             if (np != null && NinePatch.isNinePatchChunk(np)) {
                 Rect opticalInsets = new Rect();
                 bm.getOpticalInsets(opticalInsets);
-                Rect padding = decoder.mOutPaddingRect;
-                if (padding == null) {
-                    padding = new Rect();
-                }
+                Rect padding = new Rect();
                 nGetPadding(decoder.mNativePtr, padding);
                 return new NinePatchDrawable(res, bm, np, padding,
                         opticalInsets, null);
@@ -1023,15 +1008,6 @@
             final int srcDensity = computeDensity(src, decoder);
             Bitmap bm = decoder.decodeBitmap();
             bm.setDensity(srcDensity);
-
-            Rect padding = decoder.mOutPaddingRect;
-            if (padding != null) {
-                byte[] np = bm.getNinePatchChunk();
-                if (np != null && NinePatch.isNinePatchChunk(np)) {
-                    nGetPadding(decoder.mNativePtr, padding);
-                }
-            }
-
             return bm;
         }
     }
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index ed147e9..42dac38 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -2835,6 +2835,16 @@
         return result;
     }
 
+    /**
+     * Returns true of the passed {@link Paint} will have the same effect on text measurement
+     *
+     * @param other A {@link Paint} object.
+     * @return true if the other {@link Paint} has the same effect on text measurement.
+     */
+    public boolean equalsForTextMeasurement(@NonNull Paint other) {
+        return nEqualsForTextMeasurement(mNativePaint, other.mNativePaint);
+    }
+
     // regular JNI
     private static native long nGetNativeFinalizer();
     private static native long nInit();
@@ -3002,4 +3012,6 @@
     private static native float nGetStrikeThruThickness(long paintPtr);
     @CriticalNative
     private static native void nSetTextSize(long paintPtr, float textSize);
+    @CriticalNative
+    private static native boolean nEqualsForTextMeasurement(long leftPaintPtr, long rightPaintPtr);
 }
diff --git a/graphics/java/android/graphics/drawable/BitmapDrawable.java b/graphics/java/android/graphics/drawable/BitmapDrawable.java
index 44b783b..7ad062a 100644
--- a/graphics/java/android/graphics/drawable/BitmapDrawable.java
+++ b/graphics/java/android/graphics/drawable/BitmapDrawable.java
@@ -27,7 +27,6 @@
 import android.graphics.BitmapShader;
 import android.graphics.Canvas;
 import android.graphics.ColorFilter;
-import android.graphics.ImageDecoder;
 import android.graphics.Insets;
 import android.graphics.Matrix;
 import android.graphics.Outline;
@@ -50,7 +49,6 @@
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
-import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 
@@ -113,7 +111,7 @@
      */
     @Deprecated
     public BitmapDrawable() {
-        init(new BitmapState((Bitmap) null), null);
+        mBitmapState = new BitmapState((Bitmap) null);
     }
 
     /**
@@ -126,7 +124,8 @@
     @SuppressWarnings("unused")
     @Deprecated
     public BitmapDrawable(Resources res) {
-        init(new BitmapState((Bitmap) null), res);
+        mBitmapState = new BitmapState((Bitmap) null);
+        mBitmapState.mTargetDensity = mTargetDensity;
     }
 
     /**
@@ -136,7 +135,7 @@
      */
     @Deprecated
     public BitmapDrawable(Bitmap bitmap) {
-        init(new BitmapState(bitmap), null);
+        this(new BitmapState(bitmap), null);
     }
 
     /**
@@ -144,7 +143,8 @@
      * the display metrics of the resources.
      */
     public BitmapDrawable(Resources res, Bitmap bitmap) {
-        init(new BitmapState(bitmap), res);
+        this(new BitmapState(bitmap), res);
+        mBitmapState.mTargetDensity = mTargetDensity;
     }
 
     /**
@@ -154,7 +154,10 @@
      */
     @Deprecated
     public BitmapDrawable(String filepath) {
-        this(null, filepath);
+        this(new BitmapState(BitmapFactory.decodeFile(filepath)), null);
+        if (mBitmapState.mBitmap == null) {
+            android.util.Log.w("BitmapDrawable", "BitmapDrawable cannot decode " + filepath);
+        }
     }
 
     /**
@@ -162,21 +165,10 @@
      */
     @SuppressWarnings({ "unused", "ChainingConstructorIgnoresParameter" })
     public BitmapDrawable(Resources res, String filepath) {
-        Bitmap bitmap = null;
-        try (FileInputStream stream = new FileInputStream(filepath)) {
-            bitmap = ImageDecoder.decodeBitmap(ImageDecoder.createSource(res, stream),
-                    (decoder, info, src) -> {
-                decoder.setAllocator(ImageDecoder.ALLOCATOR_SOFTWARE);
-            });
-        } catch (Exception e) {
-            /*  do nothing. This matches the behavior of BitmapFactory.decodeFile()
-                If the exception happened on decode, mBitmapState.mBitmap will be null.
-            */
-        } finally {
-            init(new BitmapState(bitmap), res);
-            if (mBitmapState.mBitmap == null) {
-                android.util.Log.w("BitmapDrawable", "BitmapDrawable cannot decode " + filepath);
-            }
+        this(new BitmapState(BitmapFactory.decodeFile(filepath)), null);
+        mBitmapState.mTargetDensity = mTargetDensity;
+        if (mBitmapState.mBitmap == null) {
+            android.util.Log.w("BitmapDrawable", "BitmapDrawable cannot decode " + filepath);
         }
     }
 
@@ -187,7 +179,10 @@
      */
     @Deprecated
     public BitmapDrawable(java.io.InputStream is) {
-        this(null, is);
+        this(new BitmapState(BitmapFactory.decodeStream(is)), null);
+        if (mBitmapState.mBitmap == null) {
+            android.util.Log.w("BitmapDrawable", "BitmapDrawable cannot decode " + is);
+        }
     }
 
     /**
@@ -195,21 +190,10 @@
      */
     @SuppressWarnings({ "unused", "ChainingConstructorIgnoresParameter" })
     public BitmapDrawable(Resources res, java.io.InputStream is) {
-        Bitmap bitmap = null;
-        try {
-            bitmap = ImageDecoder.decodeBitmap(ImageDecoder.createSource(res, is),
-                    (decoder, info, src) -> {
-                decoder.setAllocator(ImageDecoder.ALLOCATOR_SOFTWARE);
-            });
-        } catch (Exception e) {
-            /*  do nothing. This matches the behavior of BitmapFactory.decodeStream()
-                If the exception happened on decode, mBitmapState.mBitmap will be null.
-            */
-        } finally {
-            init(new BitmapState(bitmap), res);
-            if (mBitmapState.mBitmap == null) {
-                android.util.Log.w("BitmapDrawable", "BitmapDrawable cannot decode " + is);
-            }
+        this(new BitmapState(BitmapFactory.decodeStream(is)), null);
+        mBitmapState.mTargetDensity = mTargetDensity;
+        if (mBitmapState.mBitmap == null) {
+            android.util.Log.w("BitmapDrawable", "BitmapDrawable cannot decode " + is);
         }
     }
 
@@ -828,19 +812,9 @@
                 }
             }
 
-            int density = Bitmap.DENSITY_NONE;
-            if (value.density == TypedValue.DENSITY_DEFAULT) {
-                density = DisplayMetrics.DENSITY_DEFAULT;
-            } else if (value.density != TypedValue.DENSITY_NONE) {
-                density = value.density;
-            }
-
             Bitmap bitmap = null;
             try (InputStream is = r.openRawResource(srcResId, value)) {
-                ImageDecoder.Source source = ImageDecoder.createSource(r, is, density);
-                bitmap = ImageDecoder.decodeBitmap(source, (decoder, info, src) -> {
-                    decoder.setAllocator(ImageDecoder.ALLOCATOR_SOFTWARE);
-                });
+                bitmap = BitmapFactory.decodeResourceStream(r, value, is, null, null);
             } catch (Exception e) {
                 // Do nothing and pick up the error below.
             }
@@ -1039,21 +1013,14 @@
         }
     }
 
-    private BitmapDrawable(BitmapState state, Resources res) {
-        init(state, res);
-    }
-
     /**
-     * The one helper to rule them all. This is called by all public & private
+     * The one constructor to rule them all. This is called by all public
      * constructors to set the state and initialize local properties.
      */
-    private void init(BitmapState state, Resources res) {
+    private BitmapDrawable(BitmapState state, Resources res) {
         mBitmapState = state;
-        updateLocalState(res);
 
-        if (mBitmapState != null && res != null) {
-            mBitmapState.mTargetDensity = mTargetDensity;
-        }
+        updateLocalState(res);
     }
 
     /**
diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java
index 8af2fd8..05533d7 100644
--- a/graphics/java/android/graphics/drawable/Drawable.java
+++ b/graphics/java/android/graphics/drawable/Drawable.java
@@ -37,7 +37,6 @@
 import android.graphics.Canvas;
 import android.graphics.Color;
 import android.graphics.ColorFilter;
-import android.graphics.ImageDecoder;
 import android.graphics.Insets;
 import android.graphics.NinePatch;
 import android.graphics.Outline;
@@ -51,13 +50,11 @@
 import android.os.Trace;
 import android.util.AttributeSet;
 import android.util.DisplayMetrics;
-import android.util.Log;
 import android.util.StateSet;
 import android.util.TypedValue;
 import android.util.Xml;
 import android.view.View;
 
-import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.lang.ref.WeakReference;
@@ -1182,10 +1179,6 @@
             return null;
         }
 
-        if (opts == null) {
-            return getBitmapDrawable(res, value, is);
-        }
-
         /*  ugh. The decodeStream contract is that we have already allocated
             the pad rect, but if the bitmap does not had a ninepatch chunk,
             then the pad will be ignored. If we could change this to lazily
@@ -1201,6 +1194,7 @@
         // an application in compatibility mode, without scaling those down
         // to the compatibility density only to have them scaled back up when
         // drawn to the screen.
+        if (opts == null) opts = new BitmapFactory.Options();
         opts.inScreenDensity = Drawable.resolveDensity(res, 0);
         Bitmap  bm = BitmapFactory.decodeResourceStream(res, value, is, pad, opts);
         if (bm != null) {
@@ -1217,33 +1211,6 @@
         return null;
     }
 
-    private static Drawable getBitmapDrawable(Resources res, TypedValue value, InputStream is) {
-        try {
-            ImageDecoder.Source source = null;
-            if (value != null) {
-                int density = Bitmap.DENSITY_NONE;
-                if (value.density == TypedValue.DENSITY_DEFAULT) {
-                    density = DisplayMetrics.DENSITY_DEFAULT;
-                } else if (value.density != TypedValue.DENSITY_NONE) {
-                    density = value.density;
-                }
-                source = ImageDecoder.createSource(res, is, density);
-            } else {
-                source = ImageDecoder.createSource(res, is);
-            }
-
-            return ImageDecoder.decodeDrawable(source, (decoder, info, src) -> {
-                decoder.setAllocator(ImageDecoder.ALLOCATOR_SOFTWARE);
-            });
-        } catch (IOException e) {
-            /*  do nothing.
-                If the exception happened on decode, the drawable will be null.
-            */
-            Log.e("Drawable", "Unable to decode stream: " + e);
-        }
-        return null;
-    }
-
     /**
      * Create a drawable from an XML document. For more information on how to
      * create resources in XML, see
@@ -1343,10 +1310,11 @@
         }
 
         Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, pathName);
-        try (FileInputStream stream = new FileInputStream(pathName)) {
-            return getBitmapDrawable(null, null, stream);
-        } catch(IOException e) {
-            // Do nothing; we will just return null if the FileInputStream had an error
+        try {
+            Bitmap bm = BitmapFactory.decodeFile(pathName);
+            if (bm != null) {
+                return drawableFromBitmap(null, bm, null, null, null, pathName);
+            }
         } finally {
             Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
         }
diff --git a/graphics/java/android/graphics/drawable/NinePatchDrawable.java b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
index a56e8d1..1790020 100644
--- a/graphics/java/android/graphics/drawable/NinePatchDrawable.java
+++ b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
@@ -24,9 +24,9 @@
 import android.content.res.Resources.Theme;
 import android.content.res.TypedArray;
 import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
 import android.graphics.Canvas;
 import android.graphics.ColorFilter;
-import android.graphics.ImageDecoder;
 import android.graphics.Insets;
 import android.graphics.NinePatch;
 import android.graphics.Outline;
@@ -211,8 +211,7 @@
             restoreAlpha = -1;
         }
 
-        final boolean needsDensityScaling = canvas.getDensity() == 0
-                && Bitmap.DENSITY_NONE != state.mNinePatch.getDensity();
+        final boolean needsDensityScaling = canvas.getDensity() == 0;
         if (needsDensityScaling) {
             restoreToCount = restoreToCount >= 0 ? restoreToCount : canvas.save();
 
@@ -422,6 +421,10 @@
 
         final int srcResId = a.getResourceId(R.styleable.NinePatchDrawable_src, 0);
         if (srcResId != 0) {
+            final BitmapFactory.Options options = new BitmapFactory.Options();
+            options.inDither = !state.mDither;
+            options.inScreenDensity = r.getDisplayMetrics().noncompatDensityDpi;
+
             final Rect padding = new Rect();
             final Rect opticalInsets = new Rect();
             Bitmap bitmap = null;
@@ -430,17 +433,7 @@
                 final TypedValue value = new TypedValue();
                 final InputStream is = r.openRawResource(srcResId, value);
 
-                int density = Bitmap.DENSITY_NONE;
-                if (value.density == TypedValue.DENSITY_DEFAULT) {
-                    density = DisplayMetrics.DENSITY_DEFAULT;
-                } else if (value.density != TypedValue.DENSITY_NONE) {
-                    density = value.density;
-                }
-                ImageDecoder.Source source = ImageDecoder.createSource(r, is, density);
-                bitmap = ImageDecoder.decodeBitmap(source, (decoder, info, src) -> {
-                    decoder.setOutPaddingRect(padding);
-                    decoder.setAllocator(ImageDecoder.ALLOCATOR_SOFTWARE);
-                });
+                bitmap = BitmapFactory.decodeResourceStream(r, value, is, padding, options);
 
                 is.close();
             } catch (IOException e) {
diff --git a/libs/androidfw/Android.bp b/libs/androidfw/Android.bp
index 70d5216..251b2e7 100644
--- a/libs/androidfw/Android.bp
+++ b/libs/androidfw/Android.bp
@@ -145,7 +145,6 @@
         "tests/TypeWrappers_test.cpp",
         "tests/ZipUtils_test.cpp",
     ],
-    static_libs: ["libgmock"],
     target: {
         android: {
             srcs: [
@@ -172,7 +171,6 @@
 
         // Actual benchmarks.
         "tests/AssetManager2_bench.cpp",
-        "tests/AttributeResolution_bench.cpp",
         "tests/SparseEntry_bench.cpp",
         "tests/Theme_bench.cpp",
     ],
diff --git a/libs/androidfw/ApkAssets.cpp b/libs/androidfw/ApkAssets.cpp
index 60f8a18..da0205d 100644
--- a/libs/androidfw/ApkAssets.cpp
+++ b/libs/androidfw/ApkAssets.cpp
@@ -231,16 +231,12 @@
   while ((result = ::Next(cookie, &entry, &name)) == 0) {
     StringPiece full_file_path(reinterpret_cast<const char*>(name.name), name.name_length);
     StringPiece leaf_file_path = full_file_path.substr(root_path_full.size());
-
-    if (!leaf_file_path.empty()) {
-      auto iter = std::find(leaf_file_path.begin(), leaf_file_path.end(), '/');
-      if (iter != leaf_file_path.end()) {
-        std::string dir =
-            leaf_file_path.substr(0, std::distance(leaf_file_path.begin(), iter)).to_string();
-        dirs.insert(std::move(dir));
-      } else {
-        f(leaf_file_path, kFileTypeRegular);
-      }
+    auto iter = std::find(leaf_file_path.begin(), leaf_file_path.end(), '/');
+    if (iter != leaf_file_path.end()) {
+      dirs.insert(
+          leaf_file_path.substr(0, std::distance(leaf_file_path.begin(), iter)).to_string());
+    } else if (!leaf_file_path.empty()) {
+      f(leaf_file_path, kFileTypeRegular);
     }
   }
   ::EndIteration(cookie);
diff --git a/libs/androidfw/AssetManager2.cpp b/libs/androidfw/AssetManager2.cpp
index a8c916b..415d3e3 100644
--- a/libs/androidfw/AssetManager2.cpp
+++ b/libs/androidfw/AssetManager2.cpp
@@ -36,31 +36,6 @@
 
 namespace android {
 
-struct FindEntryResult {
-  // A pointer to the resource table entry for this resource.
-  // If the size of the entry is > sizeof(ResTable_entry), it can be cast to
-  // a ResTable_map_entry and processed as a bag/map.
-  const ResTable_entry* entry;
-
-  // The configuration for which the resulting entry was defined. This is already swapped to host
-  // endianness.
-  ResTable_config config;
-
-  // The bitmask of configuration axis with which the resource value varies.
-  uint32_t type_flags;
-
-  // The dynamic package ID map for the package from which this resource came from.
-  const DynamicRefTable* dynamic_ref_table;
-
-  // The string pool reference to the type's name. This uses a different string pool than
-  // the global string pool, but this is hidden from the caller.
-  StringPoolRef type_string_ref;
-
-  // The string pool reference to the entry's name. This uses a different string pool than
-  // the global string pool, but this is hidden from the caller.
-  StringPoolRef entry_string_ref;
-};
-
 AssetManager2::AssetManager2() {
   memset(&configuration_, 0, sizeof(configuration_));
 }
@@ -69,7 +44,6 @@
                                  bool invalidate_caches) {
   apk_assets_ = apk_assets;
   BuildDynamicRefTable();
-  RebuildFilterList();
   if (invalidate_caches) {
     InvalidateCaches(static_cast<uint32_t>(-1));
   }
@@ -100,14 +74,12 @@
       if (idx == 0xff) {
         package_ids_[package_id] = idx = static_cast<uint8_t>(package_groups_.size());
         package_groups_.push_back({});
-        DynamicRefTable& ref_table = package_groups_.back().dynamic_ref_table;
-        ref_table.mAssignedPackageId = package_id;
-        ref_table.mAppAsLib = package->IsDynamic() && package->GetPackageId() == 0x7f;
+        package_groups_.back().dynamic_ref_table.mAssignedPackageId = package_id;
       }
       PackageGroup* package_group = &package_groups_[idx];
 
       // Add the package and to the set of packages with the same ID.
-      package_group->packages_.push_back(ConfiguredPackage{package.get(), {}});
+      package_group->packages_.push_back(package.get());
       package_group->cookies_.push_back(static_cast<ApkAssetsCookie>(i));
 
       // Add the package name -> build time ID mappings.
@@ -122,7 +94,7 @@
   // Now assign the runtime IDs so that we have a build-time to runtime ID map.
   const auto package_groups_end = package_groups_.end();
   for (auto iter = package_groups_.begin(); iter != package_groups_end; ++iter) {
-    const std::string& package_name = iter->packages_[0].loaded_package_->GetPackageName();
+    const std::string& package_name = iter->packages_[0]->GetPackageName();
     for (auto iter2 = package_groups_.begin(); iter2 != package_groups_end; ++iter2) {
       iter2->dynamic_ref_table.addMapping(String16(package_name.c_str(), package_name.size()),
                                           iter->dynamic_ref_table.mAssignedPackageId);
@@ -133,33 +105,20 @@
 void AssetManager2::DumpToLog() const {
   base::ScopedLogSeverity _log(base::INFO);
 
-  LOG(INFO) << base::StringPrintf("AssetManager2(this=%p)", this);
-
   std::string list;
-  for (const auto& apk_assets : apk_assets_) {
-    base::StringAppendF(&list, "%s,", apk_assets->GetPath().c_str());
-  }
-  LOG(INFO) << "ApkAssets: " << list;
-
-  list = "";
   for (size_t i = 0; i < package_ids_.size(); i++) {
     if (package_ids_[i] != 0xff) {
-      base::StringAppendF(&list, "%02x -> %d, ", (int)i, package_ids_[i]);
+      base::StringAppendF(&list, "%02x -> %d, ", (int) i, package_ids_[i]);
     }
   }
   LOG(INFO) << "Package ID map: " << list;
 
   for (const auto& package_group: package_groups_) {
-    list = "";
-    for (const auto& package : package_group.packages_) {
-      const LoadedPackage* loaded_package = package.loaded_package_;
-      base::StringAppendF(&list, "%s(%02x%s), ", loaded_package->GetPackageName().c_str(),
-                          loaded_package->GetPackageId(),
-                          (loaded_package->IsDynamic() ? " dynamic" : ""));
-    }
-    LOG(INFO) << base::StringPrintf("PG (%02x): ",
-                                    package_group.dynamic_ref_table.mAssignedPackageId)
-              << list;
+      list = "";
+      for (const auto& package : package_group.packages_) {
+        base::StringAppendF(&list, "%s(%02x), ", package->GetPackageName().c_str(), package->GetPackageId());
+      }
+      LOG(INFO) << base::StringPrintf("PG (%02x): ", package_group.dynamic_ref_table.mAssignedPackageId) << list;
   }
 }
 
@@ -198,54 +157,52 @@
   configuration_ = configuration;
 
   if (diff) {
-    RebuildFilterList();
     InvalidateCaches(static_cast<uint32_t>(diff));
   }
 }
 
 std::set<ResTable_config> AssetManager2::GetResourceConfigurations(bool exclude_system,
-                                                                   bool exclude_mipmap) const {
+                                                                   bool exclude_mipmap) {
   ATRACE_CALL();
   std::set<ResTable_config> configurations;
   for (const PackageGroup& package_group : package_groups_) {
-    for (const ConfiguredPackage& package : package_group.packages_) {
-      if (exclude_system && package.loaded_package_->IsSystem()) {
+    for (const LoadedPackage* package : package_group.packages_) {
+      if (exclude_system && package->IsSystem()) {
         continue;
       }
-      package.loaded_package_->CollectConfigurations(exclude_mipmap, &configurations);
+      package->CollectConfigurations(exclude_mipmap, &configurations);
     }
   }
   return configurations;
 }
 
 std::set<std::string> AssetManager2::GetResourceLocales(bool exclude_system,
-                                                        bool merge_equivalent_languages) const {
+                                                        bool merge_equivalent_languages) {
   ATRACE_CALL();
   std::set<std::string> locales;
   for (const PackageGroup& package_group : package_groups_) {
-    for (const ConfiguredPackage& package : package_group.packages_) {
-      if (exclude_system && package.loaded_package_->IsSystem()) {
+    for (const LoadedPackage* package : package_group.packages_) {
+      if (exclude_system && package->IsSystem()) {
         continue;
       }
-      package.loaded_package_->CollectLocales(merge_equivalent_languages, &locales);
+      package->CollectLocales(merge_equivalent_languages, &locales);
     }
   }
   return locales;
 }
 
-std::unique_ptr<Asset> AssetManager2::Open(const std::string& filename,
-                                           Asset::AccessMode mode) const {
+std::unique_ptr<Asset> AssetManager2::Open(const std::string& filename, Asset::AccessMode mode) {
   const std::string new_path = "assets/" + filename;
   return OpenNonAsset(new_path, mode);
 }
 
 std::unique_ptr<Asset> AssetManager2::Open(const std::string& filename, ApkAssetsCookie cookie,
-                                           Asset::AccessMode mode) const {
+                                           Asset::AccessMode mode) {
   const std::string new_path = "assets/" + filename;
   return OpenNonAsset(new_path, cookie, mode);
 }
 
-std::unique_ptr<AssetDir> AssetManager2::OpenDir(const std::string& dirname) const {
+std::unique_ptr<AssetDir> AssetManager2::OpenDir(const std::string& dirname) {
   ATRACE_CALL();
 
   std::string full_path = "assets/" + dirname;
@@ -279,7 +236,7 @@
 // is inconsistent for split APKs.
 std::unique_ptr<Asset> AssetManager2::OpenNonAsset(const std::string& filename,
                                                    Asset::AccessMode mode,
-                                                   ApkAssetsCookie* out_cookie) const {
+                                                   ApkAssetsCookie* out_cookie) {
   ATRACE_CALL();
   for (int32_t i = apk_assets_.size() - 1; i >= 0; i--) {
     std::unique_ptr<Asset> asset = apk_assets_[i]->Open(filename, mode);
@@ -298,8 +255,7 @@
 }
 
 std::unique_ptr<Asset> AssetManager2::OpenNonAsset(const std::string& filename,
-                                                   ApkAssetsCookie cookie,
-                                                   Asset::AccessMode mode) const {
+                                                   ApkAssetsCookie cookie, Asset::AccessMode mode) {
   ATRACE_CALL();
   if (cookie < 0 || static_cast<size_t>(cookie) >= apk_assets_.size()) {
     return {};
@@ -308,13 +264,14 @@
 }
 
 ApkAssetsCookie AssetManager2::FindEntry(uint32_t resid, uint16_t density_override,
-                                         bool /*stop_at_first_match*/,
-                                         FindEntryResult* out_entry) const {
+                                         bool stop_at_first_match, FindEntryResult* out_entry) {
+  ATRACE_CALL();
+
   // Might use this if density_override != 0.
   ResTable_config density_override_config;
 
   // Select our configuration or generate a density override configuration.
-  const ResTable_config* desired_config = &configuration_;
+  ResTable_config* desired_config = &configuration_;
   if (density_override != 0 && density_override != configuration_.density) {
     density_override_config = configuration_;
     density_override_config.density = density_override;
@@ -328,135 +285,53 @@
 
   const uint32_t package_id = get_package_id(resid);
   const uint8_t type_idx = get_type_id(resid) - 1;
-  const uint16_t entry_idx = get_entry_id(resid);
+  const uint16_t entry_id = get_entry_id(resid);
 
-  const uint8_t package_idx = package_ids_[package_id];
-  if (package_idx == 0xff) {
+  const uint8_t idx = package_ids_[package_id];
+  if (idx == 0xff) {
     LOG(ERROR) << base::StringPrintf("No package ID %02x found for ID 0x%08x.", package_id, resid);
     return kInvalidCookie;
   }
 
-  const PackageGroup& package_group = package_groups_[package_idx];
-  const size_t package_count = package_group.packages_.size();
-
+  FindEntryResult best_entry;
   ApkAssetsCookie best_cookie = kInvalidCookie;
-  const LoadedPackage* best_package = nullptr;
-  const ResTable_type* best_type = nullptr;
-  const ResTable_config* best_config = nullptr;
-  ResTable_config best_config_copy;
-  uint32_t best_offset = 0u;
-  uint32_t type_flags = 0u;
+  uint32_t cumulated_flags = 0u;
 
-  // If desired_config is the same as the set configuration, then we can use our filtered list
-  // and we don't need to match the configurations, since they already matched.
-  const bool use_fast_path = desired_config == &configuration_;
-
-  for (size_t pi = 0; pi < package_count; pi++) {
-    const ConfiguredPackage& loaded_package_impl = package_group.packages_[pi];
-    const LoadedPackage* loaded_package = loaded_package_impl.loaded_package_;
-    ApkAssetsCookie cookie = package_group.cookies_[pi];
-
-    // If the type IDs are offset in this package, we need to take that into account when searching
-    // for a type.
-    const TypeSpec* type_spec = loaded_package->GetTypeSpecByTypeIndex(type_idx);
-    if (UNLIKELY(type_spec == nullptr)) {
+  const PackageGroup& package_group = package_groups_[idx];
+  const size_t package_count = package_group.packages_.size();
+  FindEntryResult current_entry;
+  for (size_t i = 0; i < package_count; i++) {
+    const LoadedPackage* loaded_package = package_group.packages_[i];
+    if (!loaded_package->FindEntry(type_idx, entry_id, *desired_config, &current_entry)) {
       continue;
     }
 
-    uint16_t local_entry_idx = entry_idx;
+    cumulated_flags |= current_entry.type_flags;
 
-    // If there is an IDMAP supplied with this package, translate the entry ID.
-    if (type_spec->idmap_entries != nullptr) {
-      if (!LoadedIdmap::Lookup(type_spec->idmap_entries, local_entry_idx, &local_entry_idx)) {
-        // There is no mapping, so the resource is not meant to be in this overlay package.
-        continue;
-      }
-    }
-
-    type_flags |= type_spec->GetFlagsForEntryIndex(local_entry_idx);
-
-    // If the package is an overlay, then even configurations that are the same MUST be chosen.
-    const bool package_is_overlay = loaded_package->IsOverlay();
-
-    const FilteredConfigGroup& filtered_group = loaded_package_impl.filtered_configs_[type_idx];
-    if (use_fast_path) {
-      const std::vector<ResTable_config>& candidate_configs = filtered_group.configurations;
-      const size_t type_count = candidate_configs.size();
-      for (uint32_t i = 0; i < type_count; i++) {
-        const ResTable_config& this_config = candidate_configs[i];
-
-        // We can skip calling ResTable_config::match() because we know that all candidate
-        // configurations that do NOT match have been filtered-out.
-        if ((best_config == nullptr || this_config.isBetterThan(*best_config, desired_config)) ||
-            (package_is_overlay && this_config.compare(*best_config) == 0)) {
-          // The configuration matches and is better than the previous selection.
-          // Find the entry value if it exists for this configuration.
-          const ResTable_type* type_chunk = filtered_group.types[i];
-          const uint32_t offset = LoadedPackage::GetEntryOffset(type_chunk, local_entry_idx);
-          if (offset == ResTable_type::NO_ENTRY) {
-            continue;
-          }
-
-          best_cookie = cookie;
-          best_package = loaded_package;
-          best_type = type_chunk;
-          best_config = &this_config;
-          best_offset = offset;
-        }
-      }
-    } else {
-      // This is the slower path, which doesn't use the filtered list of configurations.
-      // Here we must read the ResTable_config from the mmapped APK, convert it to host endianness
-      // and fill in any new fields that did not exist when the APK was compiled.
-      // Furthermore when selecting configurations we can't just record the pointer to the
-      // ResTable_config, we must copy it.
-      const auto iter_end = type_spec->types + type_spec->type_count;
-      for (auto iter = type_spec->types; iter != iter_end; ++iter) {
-        ResTable_config this_config;
-        this_config.copyFromDtoH((*iter)->config);
-
-        if (this_config.match(*desired_config)) {
-          if ((best_config == nullptr || this_config.isBetterThan(*best_config, desired_config)) ||
-              (package_is_overlay && this_config.compare(*best_config) == 0)) {
-            // The configuration matches and is better than the previous selection.
-            // Find the entry value if it exists for this configuration.
-            const uint32_t offset = LoadedPackage::GetEntryOffset(*iter, local_entry_idx);
-            if (offset == ResTable_type::NO_ENTRY) {
-              continue;
-            }
-
-            best_cookie = cookie;
-            best_package = loaded_package;
-            best_type = *iter;
-            best_config_copy = this_config;
-            best_config = &best_config_copy;
-            best_offset = offset;
-          }
-        }
+    const ResTable_config* current_config = current_entry.config;
+    const ResTable_config* best_config = best_entry.config;
+    if (best_cookie == kInvalidCookie ||
+        current_config->isBetterThan(*best_config, desired_config) ||
+        (loaded_package->IsOverlay() && current_config->compare(*best_config) == 0)) {
+      best_entry = current_entry;
+      best_cookie = package_group.cookies_[i];
+      if (stop_at_first_match) {
+        break;
       }
     }
   }
 
-  if (UNLIKELY(best_cookie == kInvalidCookie)) {
+  if (best_cookie == kInvalidCookie) {
     return kInvalidCookie;
   }
 
-  const ResTable_entry* best_entry = LoadedPackage::GetEntryFromOffset(best_type, best_offset);
-  if (UNLIKELY(best_entry == nullptr)) {
-    return kInvalidCookie;
-  }
-
-  out_entry->entry = best_entry;
-  out_entry->config = *best_config;
-  out_entry->type_flags = type_flags;
-  out_entry->type_string_ref = StringPoolRef(best_package->GetTypeStringPool(), best_type->id - 1);
-  out_entry->entry_string_ref =
-      StringPoolRef(best_package->GetKeyStringPool(), best_entry->key.index);
+  *out_entry = best_entry;
   out_entry->dynamic_ref_table = &package_group.dynamic_ref_table;
+  out_entry->type_flags = cumulated_flags;
   return best_cookie;
 }
 
-bool AssetManager2::GetResourceName(uint32_t resid, ResourceName* out_name) const {
+bool AssetManager2::GetResourceName(uint32_t resid, ResourceName* out_name) {
   ATRACE_CALL();
 
   FindEntryResult entry;
@@ -466,8 +341,7 @@
     return false;
   }
 
-  const LoadedPackage* package =
-      apk_assets_[cookie]->GetLoadedArsc()->GetPackageById(get_package_id(resid));
+  const LoadedPackage* package = apk_assets_[cookie]->GetLoadedArsc()->GetPackageForId(resid);
   if (package == nullptr) {
     return false;
   }
@@ -495,7 +369,7 @@
   return true;
 }
 
-bool AssetManager2::GetResourceFlags(uint32_t resid, uint32_t* out_flags) const {
+bool AssetManager2::GetResourceFlags(uint32_t resid, uint32_t* out_flags) {
   FindEntryResult entry;
   ApkAssetsCookie cookie =
       FindEntry(resid, 0u /* density_override */, false /* stop_at_first_match */, &entry);
@@ -509,7 +383,7 @@
 ApkAssetsCookie AssetManager2::GetResource(uint32_t resid, bool may_be_bag,
                                            uint16_t density_override, Res_value* out_value,
                                            ResTable_config* out_selected_config,
-                                           uint32_t* out_flags) const {
+                                           uint32_t* out_flags) {
   ATRACE_CALL();
 
   FindEntryResult entry;
@@ -528,7 +402,7 @@
     // Create a reference since we can't represent this complex type as a Res_value.
     out_value->dataType = Res_value::TYPE_REFERENCE;
     out_value->data = resid;
-    *out_selected_config = entry.config;
+    *out_selected_config = *entry.config;
     *out_flags = entry.type_flags;
     return cookie;
   }
@@ -540,7 +414,7 @@
   // Convert the package ID to the runtime assigned package ID.
   entry.dynamic_ref_table->lookupResourceValue(out_value);
 
-  *out_selected_config = entry.config;
+  *out_selected_config = *entry.config;
   *out_flags = entry.type_flags;
   return cookie;
 }
@@ -548,14 +422,16 @@
 ApkAssetsCookie AssetManager2::ResolveReference(ApkAssetsCookie cookie, Res_value* in_out_value,
                                                 ResTable_config* in_out_selected_config,
                                                 uint32_t* in_out_flags,
-                                                uint32_t* out_last_reference) const {
+                                                uint32_t* out_last_reference) {
   ATRACE_CALL();
   constexpr const int kMaxIterations = 20;
 
   for (size_t iteration = 0u; in_out_value->dataType == Res_value::TYPE_REFERENCE &&
                               in_out_value->data != 0u && iteration < kMaxIterations;
        iteration++) {
-    *out_last_reference = in_out_value->data;
+    if (out_last_reference != nullptr) {
+      *out_last_reference = in_out_value->data;
+    }
     uint32_t new_flags = 0u;
     cookie = GetResource(in_out_value->data, true /*may_be_bag*/, 0u /*density_override*/,
                          in_out_value, in_out_selected_config, &new_flags);
@@ -616,8 +492,7 @@
         // Attributes, arrays, etc don't have a resource id as the name. They specify
         // other data, which would be wrong to change via a lookup.
         if (entry.dynamic_ref_table->lookupResourceId(&new_key) != NO_ERROR) {
-          LOG(ERROR) << base::StringPrintf("Failed to resolve key 0x%08x in bag 0x%08x.", new_key,
-                                           resid);
+          LOG(ERROR) << base::StringPrintf("Failed to resolve key 0x%08x in bag 0x%08x.", new_key, resid);
           return nullptr;
         }
       }
@@ -649,8 +524,7 @@
   const ResolvedBag* parent_bag = GetBag(parent_resid);
   if (parent_bag == nullptr) {
     // Failed to get the parent that should exist.
-    LOG(ERROR) << base::StringPrintf("Failed to find parent 0x%08x of bag 0x%08x.", parent_resid,
-                                     resid);
+    LOG(ERROR) << base::StringPrintf("Failed to find parent 0x%08x of bag 0x%08x.", parent_resid, resid);
     return nullptr;
   }
 
@@ -669,8 +543,7 @@
     uint32_t child_key = dtohl(map_entry->name.ident);
     if (!is_internal_resid(child_key)) {
       if (entry.dynamic_ref_table->lookupResourceId(&child_key) != NO_ERROR) {
-        LOG(ERROR) << base::StringPrintf("Failed to resolve key 0x%08x in bag 0x%08x.", child_key,
-                                         resid);
+        LOG(ERROR) << base::StringPrintf("Failed to resolve key 0x%08x in bag 0x%08x.", child_key, resid);
         return nullptr;
       }
     }
@@ -709,8 +582,7 @@
     uint32_t new_key = dtohl(map_entry->name.ident);
     if (!is_internal_resid(new_key)) {
       if (entry.dynamic_ref_table->lookupResourceId(&new_key) != NO_ERROR) {
-        LOG(ERROR) << base::StringPrintf("Failed to resolve key 0x%08x in bag 0x%08x.", new_key,
-                                         resid);
+        LOG(ERROR) << base::StringPrintf("Failed to resolve key 0x%08x in bag 0x%08x.", new_key, resid);
         return nullptr;
       }
     }
@@ -766,7 +638,7 @@
 
 uint32_t AssetManager2::GetResourceId(const std::string& resource_name,
                                       const std::string& fallback_type,
-                                      const std::string& fallback_package) const {
+                                      const std::string& fallback_package) {
   StringPiece package_name, type, entry;
   if (!ExtractResourceName(resource_name, &package_name, &type, &entry)) {
     return 0u;
@@ -798,8 +670,7 @@
   const static std::u16string kAttrPrivate16 = u"^attr-private";
 
   for (const PackageGroup& package_group : package_groups_) {
-    for (const ConfiguredPackage& package_impl : package_group.packages_) {
-      const LoadedPackage* package = package_impl.loaded_package_;
+    for (const LoadedPackage* package : package_group.packages_) {
       if (package_name != package->GetPackageName()) {
         // All packages in the same group are expected to have the same package name.
         break;
@@ -821,32 +692,6 @@
   return 0u;
 }
 
-void AssetManager2::RebuildFilterList() {
-  for (PackageGroup& group : package_groups_) {
-    for (ConfiguredPackage& impl : group.packages_) {
-      // Destroy it.
-      impl.filtered_configs_.~ByteBucketArray();
-
-      // Re-create it.
-      new (&impl.filtered_configs_) ByteBucketArray<FilteredConfigGroup>();
-
-      // Create the filters here.
-      impl.loaded_package_->ForEachTypeSpec([&](const TypeSpec* spec, uint8_t type_index) {
-        FilteredConfigGroup& group = impl.filtered_configs_.editItemAt(type_index);
-        const auto iter_end = spec->types + spec->type_count;
-        for (auto iter = spec->types; iter != iter_end; ++iter) {
-          ResTable_config this_config;
-          this_config.copyFromDtoH((*iter)->config);
-          if (this_config.match(configuration_)) {
-            group.configurations.push_back(this_config);
-            group.types.push_back(*iter);
-          }
-        }
-      });
-    }
-  }
-}
-
 void AssetManager2::InvalidateCaches(uint32_t diff) {
   if (diff == 0xffffffffu) {
     // Everything must go.
@@ -1027,7 +872,7 @@
 ApkAssetsCookie Theme::ResolveAttributeReference(ApkAssetsCookie cookie, Res_value* in_out_value,
                                                  ResTable_config* in_out_selected_config,
                                                  uint32_t* in_out_type_spec_flags,
-                                                 uint32_t* out_last_ref) const {
+                                                 uint32_t* out_last_ref) {
   if (in_out_value->dataType == Res_value::TYPE_ATTRIBUTE) {
     uint32_t new_flags;
     cookie = GetAttribute(in_out_value->data, in_out_value, &new_flags);
diff --git a/libs/androidfw/AttributeResolution.cpp b/libs/androidfw/AttributeResolution.cpp
index f912af4..60e3845 100644
--- a/libs/androidfw/AttributeResolution.cpp
+++ b/libs/androidfw/AttributeResolution.cpp
@@ -20,18 +20,13 @@
 
 #include <log/log.h>
 
-#include "androidfw/AssetManager2.h"
 #include "androidfw/AttributeFinder.h"
+#include "androidfw/ResourceTypes.h"
 
 constexpr bool kDebugStyles = false;
 
 namespace android {
 
-// Java asset cookies have 0 as an invalid cookie, but TypedArray expects < 0.
-static uint32_t ApkAssetsCookieToJavaCookie(ApkAssetsCookie cookie) {
-  return cookie != kInvalidCookie ? static_cast<uint32_t>(cookie + 1) : static_cast<uint32_t>(-1);
-}
-
 class XmlAttributeFinder
     : public BackTrackingAttributeFinder<XmlAttributeFinder, size_t> {
  public:
@@ -49,53 +44,58 @@
 };
 
 class BagAttributeFinder
-    : public BackTrackingAttributeFinder<BagAttributeFinder, const ResolvedBag::Entry*> {
+    : public BackTrackingAttributeFinder<BagAttributeFinder, const ResTable::bag_entry*> {
  public:
-  BagAttributeFinder(const ResolvedBag* bag)
-      : BackTrackingAttributeFinder(bag != nullptr ? bag->entries : nullptr,
-                                    bag != nullptr ? bag->entries + bag->entry_count : nullptr) {
-  }
+  BagAttributeFinder(const ResTable::bag_entry* start,
+                     const ResTable::bag_entry* end)
+      : BackTrackingAttributeFinder(start, end) {}
 
-  inline uint32_t GetAttribute(const ResolvedBag::Entry* entry) const {
-    return entry->key;
+  inline uint32_t GetAttribute(const ResTable::bag_entry* entry) const {
+    return entry->map.name.ident;
   }
 };
 
-bool ResolveAttrs(Theme* theme, uint32_t def_style_attr, uint32_t def_style_res,
-                  uint32_t* src_values, size_t src_values_length, uint32_t* attrs,
-                  size_t attrs_length, uint32_t* out_values, uint32_t* out_indices) {
+bool ResolveAttrs(ResTable::Theme* theme, uint32_t def_style_attr,
+                  uint32_t def_style_res, uint32_t* src_values,
+                  size_t src_values_length, uint32_t* attrs,
+                  size_t attrs_length, uint32_t* out_values,
+                  uint32_t* out_indices) {
   if (kDebugStyles) {
     ALOGI("APPLY STYLE: theme=0x%p defStyleAttr=0x%x defStyleRes=0x%x", theme,
           def_style_attr, def_style_res);
   }
 
-  AssetManager2* assetmanager = theme->GetAssetManager();
+  const ResTable& res = theme->getResTable();
   ResTable_config config;
   Res_value value;
 
   int indices_idx = 0;
 
   // Load default style from attribute, if specified...
-  uint32_t def_style_flags = 0u;
+  uint32_t def_style_bag_type_set_flags = 0;
   if (def_style_attr != 0) {
     Res_value value;
-    if (theme->GetAttribute(def_style_attr, &value, &def_style_flags) != kInvalidCookie) {
+    if (theme->getAttribute(def_style_attr, &value, &def_style_bag_type_set_flags) >= 0) {
       if (value.dataType == Res_value::TYPE_REFERENCE) {
         def_style_res = value.data;
       }
     }
   }
 
-  // Retrieve the default style bag, if requested.
-  const ResolvedBag* default_style_bag = nullptr;
-  if (def_style_res != 0) {
-    default_style_bag = assetmanager->GetBag(def_style_res);
-    if (default_style_bag != nullptr) {
-      def_style_flags |= default_style_bag->type_spec_flags;
-    }
-  }
+  // Now lock down the resource object and start pulling stuff from it.
+  res.lock();
 
-  BagAttributeFinder def_style_attr_finder(default_style_bag);
+  // Retrieve the default style bag, if requested.
+  const ResTable::bag_entry* def_style_start = nullptr;
+  uint32_t def_style_type_set_flags = 0;
+  ssize_t bag_off = def_style_res != 0
+                        ? res.getBagLocked(def_style_res, &def_style_start,
+                                           &def_style_type_set_flags)
+                        : -1;
+  def_style_type_set_flags |= def_style_bag_type_set_flags;
+  const ResTable::bag_entry* const def_style_end =
+      def_style_start + (bag_off >= 0 ? bag_off : 0);
+  BagAttributeFinder def_style_attr_finder(def_style_start, def_style_end);
 
   // Now iterate through all of the attributes that the client has requested,
   // filling in each with whatever data we can find.
@@ -106,7 +106,7 @@
       ALOGI("RETRIEVING ATTR 0x%08x...", cur_ident);
     }
 
-    ApkAssetsCookie cookie = kInvalidCookie;
+    ssize_t block = -1;
     uint32_t type_set_flags = 0;
 
     value.dataType = Res_value::TYPE_NULL;
@@ -122,14 +122,15 @@
       value.dataType = Res_value::TYPE_ATTRIBUTE;
       value.data = src_values[ii];
       if (kDebugStyles) {
-        ALOGI("-> From values: type=0x%x, data=0x%08x", value.dataType, value.data);
+        ALOGI("-> From values: type=0x%x, data=0x%08x", value.dataType,
+              value.data);
       }
     } else {
-      const ResolvedBag::Entry* const entry = def_style_attr_finder.Find(cur_ident);
-      if (entry != def_style_attr_finder.end()) {
-        cookie = entry->cookie;
-        type_set_flags = def_style_flags;
-        value = entry->value;
+      const ResTable::bag_entry* const def_style_entry = def_style_attr_finder.Find(cur_ident);
+      if (def_style_entry != def_style_end) {
+        block = def_style_entry->stringBlock;
+        type_set_flags = def_style_type_set_flags;
+        value = def_style_entry->map.value;
         if (kDebugStyles) {
           ALOGI("-> From def style: type=0x%x, data=0x%08x", value.dataType, value.data);
         }
@@ -139,26 +140,22 @@
     uint32_t resid = 0;
     if (value.dataType != Res_value::TYPE_NULL) {
       // Take care of resolving the found resource to its final value.
-      ApkAssetsCookie new_cookie =
-          theme->ResolveAttributeReference(cookie, &value, &config, &type_set_flags, &resid);
-      if (new_cookie != kInvalidCookie) {
-        cookie = new_cookie;
-      }
+      ssize_t new_block =
+          theme->resolveAttributeReference(&value, block, &resid, &type_set_flags, &config);
+      if (new_block >= 0) block = new_block;
       if (kDebugStyles) {
         ALOGI("-> Resolved attr: type=0x%x, data=0x%08x", value.dataType, value.data);
       }
     } else if (value.data != Res_value::DATA_NULL_EMPTY) {
-      // If we still don't have a value for this attribute, try to find it in the theme!
-      ApkAssetsCookie new_cookie = theme->GetAttribute(cur_ident, &value, &type_set_flags);
-      if (new_cookie != kInvalidCookie) {
+      // If we still don't have a value for this attribute, try to find
+      // it in the theme!
+      ssize_t new_block = theme->getAttribute(cur_ident, &value, &type_set_flags);
+      if (new_block >= 0) {
         if (kDebugStyles) {
           ALOGI("-> From theme: type=0x%x, data=0x%08x", value.dataType, value.data);
         }
-        new_cookie =
-            assetmanager->ResolveReference(new_cookie, &value, &config, &type_set_flags, &resid);
-        if (new_cookie != kInvalidCookie) {
-          cookie = new_cookie;
-        }
+        new_block = res.resolveReference(&value, new_block, &resid, &type_set_flags, &config);
+        if (new_block >= 0) block = new_block;
         if (kDebugStyles) {
           ALOGI("-> Resolved theme: type=0x%x, data=0x%08x", value.dataType, value.data);
         }
@@ -172,7 +169,7 @@
       }
       value.dataType = Res_value::TYPE_NULL;
       value.data = Res_value::DATA_NULL_UNDEFINED;
-      cookie = kInvalidCookie;
+      block = -1;
     }
 
     if (kDebugStyles) {
@@ -182,7 +179,9 @@
     // Write the final value back to Java.
     out_values[STYLE_TYPE] = value.dataType;
     out_values[STYLE_DATA] = value.data;
-    out_values[STYLE_ASSET_COOKIE] = ApkAssetsCookieToJavaCookie(cookie);
+    out_values[STYLE_ASSET_COOKIE] =
+        block != -1 ? static_cast<uint32_t>(res.getTableCookie(block))
+                    : static_cast<uint32_t>(-1);
     out_values[STYLE_RESOURCE_ID] = resid;
     out_values[STYLE_CHANGING_CONFIGURATIONS] = type_set_flags;
     out_values[STYLE_DENSITY] = config.density;
@@ -196,80 +195,90 @@
     out_values += STYLE_NUM_ENTRIES;
   }
 
+  res.unlock();
+
   if (out_indices != nullptr) {
     out_indices[0] = indices_idx;
   }
   return true;
 }
 
-void ApplyStyle(Theme* theme, ResXMLParser* xml_parser, uint32_t def_style_attr,
-                uint32_t def_style_resid, const uint32_t* attrs, size_t attrs_length,
+void ApplyStyle(ResTable::Theme* theme, ResXMLParser* xml_parser, uint32_t def_style_attr,
+                uint32_t def_style_res, const uint32_t* attrs, size_t attrs_length,
                 uint32_t* out_values, uint32_t* out_indices) {
   if (kDebugStyles) {
-    ALOGI("APPLY STYLE: theme=0x%p defStyleAttr=0x%x defStyleRes=0x%x xml=0x%p", theme,
-          def_style_attr, def_style_resid, xml_parser);
+    ALOGI("APPLY STYLE: theme=0x%p defStyleAttr=0x%x defStyleRes=0x%x xml=0x%p",
+          theme, def_style_attr, def_style_res, xml_parser);
   }
 
-  AssetManager2* assetmanager = theme->GetAssetManager();
+  const ResTable& res = theme->getResTable();
   ResTable_config config;
   Res_value value;
 
   int indices_idx = 0;
 
   // Load default style from attribute, if specified...
-  uint32_t def_style_flags = 0u;
+  uint32_t def_style_bag_type_set_flags = 0;
   if (def_style_attr != 0) {
     Res_value value;
-    if (theme->GetAttribute(def_style_attr, &value, &def_style_flags) != kInvalidCookie) {
+    if (theme->getAttribute(def_style_attr, &value,
+                            &def_style_bag_type_set_flags) >= 0) {
       if (value.dataType == Res_value::TYPE_REFERENCE) {
-        def_style_resid = value.data;
+        def_style_res = value.data;
       }
     }
   }
 
-  // Retrieve the style resource ID associated with the current XML tag's style attribute.
-  uint32_t style_resid = 0u;
-  uint32_t style_flags = 0u;
+  // Retrieve the style class associated with the current XML tag.
+  int style = 0;
+  uint32_t style_bag_type_set_flags = 0;
   if (xml_parser != nullptr) {
     ssize_t idx = xml_parser->indexOfStyle();
     if (idx >= 0 && xml_parser->getAttributeValue(idx, &value) >= 0) {
       if (value.dataType == value.TYPE_ATTRIBUTE) {
-        // Resolve the attribute with out theme.
-        if (theme->GetAttribute(value.data, &value, &style_flags) == kInvalidCookie) {
+        if (theme->getAttribute(value.data, &value, &style_bag_type_set_flags) < 0) {
           value.dataType = Res_value::TYPE_NULL;
         }
       }
-
       if (value.dataType == value.TYPE_REFERENCE) {
-        style_resid = value.data;
+        style = value.data;
       }
     }
   }
 
-  // Retrieve the default style bag, if requested.
-  const ResolvedBag* default_style_bag = nullptr;
-  if (def_style_resid != 0) {
-    default_style_bag = assetmanager->GetBag(def_style_resid);
-    if (default_style_bag != nullptr) {
-      def_style_flags |= default_style_bag->type_spec_flags;
-    }
-  }
+  // Now lock down the resource object and start pulling stuff from it.
+  res.lock();
 
-  BagAttributeFinder def_style_attr_finder(default_style_bag);
+  // Retrieve the default style bag, if requested.
+  const ResTable::bag_entry* def_style_attr_start = nullptr;
+  uint32_t def_style_type_set_flags = 0;
+  ssize_t bag_off = def_style_res != 0
+                        ? res.getBagLocked(def_style_res, &def_style_attr_start,
+                                           &def_style_type_set_flags)
+                        : -1;
+  def_style_type_set_flags |= def_style_bag_type_set_flags;
+  const ResTable::bag_entry* const def_style_attr_end =
+      def_style_attr_start + (bag_off >= 0 ? bag_off : 0);
+  BagAttributeFinder def_style_attr_finder(def_style_attr_start,
+                                           def_style_attr_end);
 
   // Retrieve the style class bag, if requested.
-  const ResolvedBag* xml_style_bag = nullptr;
-  if (style_resid != 0) {
-    xml_style_bag = assetmanager->GetBag(style_resid);
-    if (xml_style_bag != nullptr) {
-      style_flags |= xml_style_bag->type_spec_flags;
-    }
-  }
-
-  BagAttributeFinder xml_style_attr_finder(xml_style_bag);
+  const ResTable::bag_entry* style_attr_start = nullptr;
+  uint32_t style_type_set_flags = 0;
+  bag_off =
+      style != 0
+          ? res.getBagLocked(style, &style_attr_start, &style_type_set_flags)
+          : -1;
+  style_type_set_flags |= style_bag_type_set_flags;
+  const ResTable::bag_entry* const style_attr_end =
+      style_attr_start + (bag_off >= 0 ? bag_off : 0);
+  BagAttributeFinder style_attr_finder(style_attr_start, style_attr_end);
 
   // Retrieve the XML attributes, if requested.
+  static const ssize_t kXmlBlock = 0x10000000;
   XmlAttributeFinder xml_attr_finder(xml_parser);
+  const size_t xml_attr_end =
+      xml_parser != nullptr ? xml_parser->getAttributeCount() : 0;
 
   // Now iterate through all of the attributes that the client has requested,
   // filling in each with whatever data we can find.
@@ -280,8 +289,8 @@
       ALOGI("RETRIEVING ATTR 0x%08x...", cur_ident);
     }
 
-    ApkAssetsCookie cookie = kInvalidCookie;
-    uint32_t type_set_flags = 0u;
+    ssize_t block = kXmlBlock;
+    uint32_t type_set_flags = 0;
 
     value.dataType = Res_value::TYPE_NULL;
     value.data = Res_value::DATA_NULL_UNDEFINED;
@@ -293,7 +302,7 @@
 
     // Walk through the xml attributes looking for the requested attribute.
     const size_t xml_attr_idx = xml_attr_finder.Find(cur_ident);
-    if (xml_attr_idx != xml_attr_finder.end()) {
+    if (xml_attr_idx != xml_attr_end) {
       // We found the attribute we were looking for.
       xml_parser->getAttributeValue(xml_attr_idx, &value);
       if (kDebugStyles) {
@@ -303,12 +312,12 @@
 
     if (value.dataType == Res_value::TYPE_NULL && value.data != Res_value::DATA_NULL_EMPTY) {
       // Walk through the style class values looking for the requested attribute.
-      const ResolvedBag::Entry* entry = xml_style_attr_finder.Find(cur_ident);
-      if (entry != xml_style_attr_finder.end()) {
+      const ResTable::bag_entry* const style_attr_entry = style_attr_finder.Find(cur_ident);
+      if (style_attr_entry != style_attr_end) {
         // We found the attribute we were looking for.
-        cookie = entry->cookie;
-        type_set_flags = style_flags;
-        value = entry->value;
+        block = style_attr_entry->stringBlock;
+        type_set_flags = style_type_set_flags;
+        value = style_attr_entry->map.value;
         if (kDebugStyles) {
           ALOGI("-> From style: type=0x%x, data=0x%08x", value.dataType, value.data);
         }
@@ -317,25 +326,25 @@
 
     if (value.dataType == Res_value::TYPE_NULL && value.data != Res_value::DATA_NULL_EMPTY) {
       // Walk through the default style values looking for the requested attribute.
-      const ResolvedBag::Entry* entry = def_style_attr_finder.Find(cur_ident);
-      if (entry != def_style_attr_finder.end()) {
+      const ResTable::bag_entry* const def_style_attr_entry = def_style_attr_finder.Find(cur_ident);
+      if (def_style_attr_entry != def_style_attr_end) {
         // We found the attribute we were looking for.
-        cookie = entry->cookie;
-        type_set_flags = def_style_flags;
-        value = entry->value;
+        block = def_style_attr_entry->stringBlock;
+        type_set_flags = style_type_set_flags;
+        value = def_style_attr_entry->map.value;
         if (kDebugStyles) {
           ALOGI("-> From def style: type=0x%x, data=0x%08x", value.dataType, value.data);
         }
       }
     }
 
-    uint32_t resid = 0u;
+    uint32_t resid = 0;
     if (value.dataType != Res_value::TYPE_NULL) {
       // Take care of resolving the found resource to its final value.
-      ApkAssetsCookie new_cookie =
-          theme->ResolveAttributeReference(cookie, &value, &config, &type_set_flags, &resid);
-      if (new_cookie != kInvalidCookie) {
-        cookie = new_cookie;
+      ssize_t new_block =
+          theme->resolveAttributeReference(&value, block, &resid, &type_set_flags, &config);
+      if (new_block >= 0) {
+        block = new_block;
       }
 
       if (kDebugStyles) {
@@ -343,15 +352,14 @@
       }
     } else if (value.data != Res_value::DATA_NULL_EMPTY) {
       // If we still don't have a value for this attribute, try to find it in the theme!
-      ApkAssetsCookie new_cookie = theme->GetAttribute(cur_ident, &value, &type_set_flags);
-      if (new_cookie != kInvalidCookie) {
+      ssize_t new_block = theme->getAttribute(cur_ident, &value, &type_set_flags);
+      if (new_block >= 0) {
         if (kDebugStyles) {
           ALOGI("-> From theme: type=0x%x, data=0x%08x", value.dataType, value.data);
         }
-        new_cookie =
-            assetmanager->ResolveReference(new_cookie, &value, &config, &type_set_flags, &resid);
-        if (new_cookie != kInvalidCookie) {
-          cookie = new_cookie;
+        new_block = res.resolveReference(&value, new_block, &resid, &type_set_flags, &config);
+        if (new_block >= 0) {
+          block = new_block;
         }
 
         if (kDebugStyles) {
@@ -367,7 +375,7 @@
       }
       value.dataType = Res_value::TYPE_NULL;
       value.data = Res_value::DATA_NULL_UNDEFINED;
-      cookie = kInvalidCookie;
+      block = kXmlBlock;
     }
 
     if (kDebugStyles) {
@@ -377,7 +385,9 @@
     // Write the final value back to Java.
     out_values[STYLE_TYPE] = value.dataType;
     out_values[STYLE_DATA] = value.data;
-    out_values[STYLE_ASSET_COOKIE] = ApkAssetsCookieToJavaCookie(cookie);
+    out_values[STYLE_ASSET_COOKIE] =
+        block != kXmlBlock ? static_cast<uint32_t>(res.getTableCookie(block))
+                           : static_cast<uint32_t>(-1);
     out_values[STYLE_RESOURCE_ID] = resid;
     out_values[STYLE_CHANGING_CONFIGURATIONS] = type_set_flags;
     out_values[STYLE_DENSITY] = config.density;
@@ -392,28 +402,36 @@
     out_values += STYLE_NUM_ENTRIES;
   }
 
+  res.unlock();
+
   // out_indices must NOT be nullptr.
   out_indices[0] = indices_idx;
 }
 
-bool RetrieveAttributes(AssetManager2* assetmanager, ResXMLParser* xml_parser, uint32_t* attrs,
-                        size_t attrs_length, uint32_t* out_values, uint32_t* out_indices) {
+bool RetrieveAttributes(const ResTable* res, ResXMLParser* xml_parser,
+                        uint32_t* attrs, size_t attrs_length,
+                        uint32_t* out_values, uint32_t* out_indices) {
   ResTable_config config;
   Res_value value;
 
   int indices_idx = 0;
 
+  // Now lock down the resource object and start pulling stuff from it.
+  res->lock();
+
   // Retrieve the XML attributes, if requested.
   const size_t xml_attr_count = xml_parser->getAttributeCount();
   size_t ix = 0;
   uint32_t cur_xml_attr = xml_parser->getAttributeNameResID(ix);
 
+  static const ssize_t kXmlBlock = 0x10000000;
+
   // Now iterate through all of the attributes that the client has requested,
   // filling in each with whatever data we can find.
   for (size_t ii = 0; ii < attrs_length; ii++) {
     const uint32_t cur_ident = attrs[ii];
-    ApkAssetsCookie cookie = kInvalidCookie;
-    uint32_t type_set_flags = 0u;
+    ssize_t block = kXmlBlock;
+    uint32_t type_set_flags = 0;
 
     value.dataType = Res_value::TYPE_NULL;
     value.data = Res_value::DATA_NULL_UNDEFINED;
@@ -432,27 +450,28 @@
       cur_xml_attr = xml_parser->getAttributeNameResID(ix);
     }
 
-    uint32_t resid = 0u;
+    uint32_t resid = 0;
     if (value.dataType != Res_value::TYPE_NULL) {
       // Take care of resolving the found resource to its final value.
-      ApkAssetsCookie new_cookie =
-          assetmanager->ResolveReference(cookie, &value, &config, &type_set_flags, &resid);
-      if (new_cookie != kInvalidCookie) {
-        cookie = new_cookie;
-      }
+      // printf("Resolving attribute reference\n");
+      ssize_t new_block = res->resolveReference(&value, block, &resid,
+                                                &type_set_flags, &config);
+      if (new_block >= 0) block = new_block;
     }
 
     // Deal with the special @null value -- it turns back to TYPE_NULL.
     if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
       value.dataType = Res_value::TYPE_NULL;
       value.data = Res_value::DATA_NULL_UNDEFINED;
-      cookie = kInvalidCookie;
+      block = kXmlBlock;
     }
 
     // Write the final value back to Java.
     out_values[STYLE_TYPE] = value.dataType;
     out_values[STYLE_DATA] = value.data;
-    out_values[STYLE_ASSET_COOKIE] = ApkAssetsCookieToJavaCookie(cookie);
+    out_values[STYLE_ASSET_COOKIE] =
+        block != kXmlBlock ? static_cast<uint32_t>(res->getTableCookie(block))
+                           : static_cast<uint32_t>(-1);
     out_values[STYLE_RESOURCE_ID] = resid;
     out_values[STYLE_CHANGING_CONFIGURATIONS] = type_set_flags;
     out_values[STYLE_DENSITY] = config.density;
@@ -466,6 +485,8 @@
     out_values += STYLE_NUM_ENTRIES;
   }
 
+  res->unlock();
+
   if (out_indices != nullptr) {
     out_indices[0] = indices_idx;
   }
diff --git a/libs/androidfw/LoadedArsc.cpp b/libs/androidfw/LoadedArsc.cpp
index a65d49b..28548e2 100644
--- a/libs/androidfw/LoadedArsc.cpp
+++ b/libs/androidfw/LoadedArsc.cpp
@@ -44,6 +44,44 @@
 
 constexpr const static int kAppPackageId = 0x7f;
 
+// Element of a TypeSpec array. See TypeSpec.
+struct Type {
+  // The configuration for which this type defines entries.
+  // This is already converted to host endianness.
+  ResTable_config configuration;
+
+  // Pointer to the mmapped data where entry definitions are kept.
+  const ResTable_type* type;
+};
+
+// TypeSpec is going to be immediately proceeded by
+// an array of Type structs, all in the same block of memory.
+struct TypeSpec {
+  // Pointer to the mmapped data where flags are kept.
+  // Flags denote whether the resource entry is public
+  // and under which configurations it varies.
+  const ResTable_typeSpec* type_spec;
+
+  // Pointer to the mmapped data where the IDMAP mappings for this type
+  // exist. May be nullptr if no IDMAP exists.
+  const IdmapEntry_header* idmap_entries;
+
+  // The number of types that follow this struct.
+  // There is a type for each configuration
+  // that entries are defined for.
+  size_t type_count;
+
+  // Trick to easily access a variable number of Type structs
+  // proceeding this struct, and to ensure their alignment.
+  const Type types[0];
+};
+
+// TypeSpecPtr points to the block of memory that holds
+// a TypeSpec struct, followed by an array of Type structs.
+// TypeSpecPtr is a managed pointer that knows how to delete
+// itself.
+using TypeSpecPtr = util::unique_cptr<TypeSpec>;
+
 namespace {
 
 // Builder that helps accumulate Type structs and then create a single
@@ -57,22 +95,21 @@
   }
 
   void AddType(const ResTable_type* type) {
-    types_.push_back(type);
+    ResTable_config config;
+    config.copyFromDtoH(type->config);
+    types_.push_back(Type{config, type});
   }
 
   TypeSpecPtr Build() {
     // Check for overflow.
-    using ElementType = const ResTable_type*;
-    if ((std::numeric_limits<size_t>::max() - sizeof(TypeSpec)) / sizeof(ElementType) <
-        types_.size()) {
+    if ((std::numeric_limits<size_t>::max() - sizeof(TypeSpec)) / sizeof(Type) < types_.size()) {
       return {};
     }
-    TypeSpec* type_spec =
-        (TypeSpec*)::malloc(sizeof(TypeSpec) + (types_.size() * sizeof(ElementType)));
+    TypeSpec* type_spec = (TypeSpec*)::malloc(sizeof(TypeSpec) + (types_.size() * sizeof(Type)));
     type_spec->type_spec = header_;
     type_spec->idmap_entries = idmap_header_;
     type_spec->type_count = types_.size();
-    memcpy(type_spec + 1, types_.data(), types_.size() * sizeof(ElementType));
+    memcpy(type_spec + 1, types_.data(), types_.size() * sizeof(Type));
     return TypeSpecPtr(type_spec);
   }
 
@@ -81,7 +118,7 @@
 
   const ResTable_typeSpec* header_;
   const IdmapEntry_header* idmap_header_;
-  std::vector<const ResTable_type*> types_;
+  std::vector<Type> types_;
 };
 
 }  // namespace
@@ -125,17 +162,18 @@
   return true;
 }
 
-static bool VerifyResTableEntry(const ResTable_type* type, uint32_t entry_offset) {
+static bool VerifyResTableEntry(const ResTable_type* type, uint32_t entry_offset,
+                                size_t entry_idx) {
   // Check that the offset is aligned.
   if (entry_offset & 0x03) {
-    LOG(ERROR) << "Entry at offset " << entry_offset << " is not 4-byte aligned.";
+    LOG(ERROR) << "Entry offset at index " << entry_idx << " is not 4-byte aligned.";
     return false;
   }
 
   // Check that the offset doesn't overflow.
   if (entry_offset > std::numeric_limits<uint32_t>::max() - dtohl(type->entriesStart)) {
     // Overflow in offset.
-    LOG(ERROR) << "Entry at offset " << entry_offset << " is too large.";
+    LOG(ERROR) << "Entry offset at index " << entry_idx << " is too large.";
     return false;
   }
 
@@ -143,7 +181,7 @@
 
   entry_offset += dtohl(type->entriesStart);
   if (entry_offset > chunk_size - sizeof(ResTable_entry)) {
-    LOG(ERROR) << "Entry at offset " << entry_offset
+    LOG(ERROR) << "Entry offset at index " << entry_idx
                << " is too large. No room for ResTable_entry.";
     return false;
   }
@@ -153,13 +191,13 @@
 
   const size_t entry_size = dtohs(entry->size);
   if (entry_size < sizeof(*entry)) {
-    LOG(ERROR) << "ResTable_entry size " << entry_size << " at offset " << entry_offset
+    LOG(ERROR) << "ResTable_entry size " << entry_size << " at index " << entry_idx
                << " is too small.";
     return false;
   }
 
   if (entry_size > chunk_size || entry_offset > chunk_size - entry_size) {
-    LOG(ERROR) << "ResTable_entry size " << entry_size << " at offset " << entry_offset
+    LOG(ERROR) << "ResTable_entry size " << entry_size << " at index " << entry_idx
                << " is too large.";
     return false;
   }
@@ -167,7 +205,7 @@
   if (entry_size < sizeof(ResTable_map_entry)) {
     // There needs to be room for one Res_value struct.
     if (entry_offset + entry_size > chunk_size - sizeof(Res_value)) {
-      LOG(ERROR) << "No room for Res_value after ResTable_entry at offset " << entry_offset
+      LOG(ERROR) << "No room for Res_value after ResTable_entry at index " << entry_idx
                  << " for type " << (int)type->id << ".";
       return false;
     }
@@ -176,12 +214,12 @@
         reinterpret_cast<const Res_value*>(reinterpret_cast<const uint8_t*>(entry) + entry_size);
     const size_t value_size = dtohs(value->size);
     if (value_size < sizeof(Res_value)) {
-      LOG(ERROR) << "Res_value at offset " << entry_offset << " is too small.";
+      LOG(ERROR) << "Res_value at index " << entry_idx << " is too small.";
       return false;
     }
 
     if (value_size > chunk_size || entry_offset + entry_size > chunk_size - value_size) {
-      LOG(ERROR) << "Res_value size " << value_size << " at offset " << entry_offset
+      LOG(ERROR) << "Res_value size " << value_size << " at index " << entry_idx
                  << " is too large.";
       return false;
     }
@@ -190,76 +228,119 @@
     const size_t map_entry_count = dtohl(map->count);
     size_t map_entries_start = entry_offset + entry_size;
     if (map_entries_start & 0x03) {
-      LOG(ERROR) << "Map entries at offset " << entry_offset << " start at unaligned offset.";
+      LOG(ERROR) << "Map entries at index " << entry_idx << " start at unaligned offset.";
       return false;
     }
 
     // Each entry is sizeof(ResTable_map) big.
     if (map_entry_count > ((chunk_size - map_entries_start) / sizeof(ResTable_map))) {
-      LOG(ERROR) << "Too many map entries in ResTable_map_entry at offset " << entry_offset << ".";
+      LOG(ERROR) << "Too many map entries in ResTable_map_entry at index " << entry_idx << ".";
       return false;
     }
   }
   return true;
 }
 
-const ResTable_entry* LoadedPackage::GetEntry(const ResTable_type* type_chunk,
-                                              uint16_t entry_index) {
-  uint32_t entry_offset = GetEntryOffset(type_chunk, entry_index);
-  if (entry_offset == ResTable_type::NO_ENTRY) {
-    return nullptr;
-  }
-  return GetEntryFromOffset(type_chunk, entry_offset);
-}
+bool LoadedPackage::FindEntry(const TypeSpecPtr& type_spec_ptr, uint16_t entry_idx,
+                              const ResTable_config& config, FindEntryResult* out_entry) const {
+  const ResTable_config* best_config = nullptr;
+  const ResTable_type* best_type = nullptr;
+  uint32_t best_offset = 0;
 
-uint32_t LoadedPackage::GetEntryOffset(const ResTable_type* type_chunk, uint16_t entry_index) {
-  // The configuration matches and is better than the previous selection.
-  // Find the entry value if it exists for this configuration.
-  const size_t entry_count = dtohl(type_chunk->entryCount);
-  const size_t offsets_offset = dtohs(type_chunk->header.headerSize);
+  for (uint32_t i = 0; i < type_spec_ptr->type_count; i++) {
+    const Type* type = &type_spec_ptr->types[i];
+    const ResTable_type* type_chunk = type->type;
 
-  // Check if there is the desired entry in this type.
+    if (type->configuration.match(config) &&
+        (best_config == nullptr || type->configuration.isBetterThan(*best_config, &config))) {
+      // The configuration matches and is better than the previous selection.
+      // Find the entry value if it exists for this configuration.
+      const size_t entry_count = dtohl(type_chunk->entryCount);
+      const size_t offsets_offset = dtohs(type_chunk->header.headerSize);
 
-  if (type_chunk->flags & ResTable_type::FLAG_SPARSE) {
-    // This is encoded as a sparse map, so perform a binary search.
-    const ResTable_sparseTypeEntry* sparse_indices =
-        reinterpret_cast<const ResTable_sparseTypeEntry*>(
+      // Check if there is the desired entry in this type.
+
+      if (type_chunk->flags & ResTable_type::FLAG_SPARSE) {
+        // This is encoded as a sparse map, so perform a binary search.
+        const ResTable_sparseTypeEntry* sparse_indices =
+            reinterpret_cast<const ResTable_sparseTypeEntry*>(
+                reinterpret_cast<const uint8_t*>(type_chunk) + offsets_offset);
+        const ResTable_sparseTypeEntry* sparse_indices_end = sparse_indices + entry_count;
+        const ResTable_sparseTypeEntry* result =
+            std::lower_bound(sparse_indices, sparse_indices_end, entry_idx,
+                             [](const ResTable_sparseTypeEntry& entry, uint16_t entry_idx) {
+                               return dtohs(entry.idx) < entry_idx;
+                             });
+
+        if (result == sparse_indices_end || dtohs(result->idx) != entry_idx) {
+          // No entry found.
+          continue;
+        }
+
+        // Extract the offset from the entry. Each offset must be a multiple of 4 so we store it as
+        // the real offset divided by 4.
+        best_offset = uint32_t{dtohs(result->offset)} * 4u;
+      } else {
+        if (entry_idx >= entry_count) {
+          // This entry cannot be here.
+          continue;
+        }
+
+        const uint32_t* entry_offsets = reinterpret_cast<const uint32_t*>(
             reinterpret_cast<const uint8_t*>(type_chunk) + offsets_offset);
-    const ResTable_sparseTypeEntry* sparse_indices_end = sparse_indices + entry_count;
-    const ResTable_sparseTypeEntry* result =
-        std::lower_bound(sparse_indices, sparse_indices_end, entry_index,
-                         [](const ResTable_sparseTypeEntry& entry, uint16_t entry_idx) {
-                           return dtohs(entry.idx) < entry_idx;
-                         });
+        const uint32_t offset = dtohl(entry_offsets[entry_idx]);
+        if (offset == ResTable_type::NO_ENTRY) {
+          continue;
+        }
 
-    if (result == sparse_indices_end || dtohs(result->idx) != entry_index) {
-      // No entry found.
-      return ResTable_type::NO_ENTRY;
+        // There is an entry for this resource, record it.
+        best_offset = offset;
+      }
+
+      best_config = &type->configuration;
+      best_type = type_chunk;
     }
-
-    // Extract the offset from the entry. Each offset must be a multiple of 4 so we store it as
-    // the real offset divided by 4.
-    return uint32_t{dtohs(result->offset)} * 4u;
   }
 
-  // This type is encoded as a dense array.
-  if (entry_index >= entry_count) {
-    // This entry cannot be here.
-    return ResTable_type::NO_ENTRY;
+  if (best_type == nullptr) {
+    return false;
   }
 
-  const uint32_t* entry_offsets = reinterpret_cast<const uint32_t*>(
-      reinterpret_cast<const uint8_t*>(type_chunk) + offsets_offset);
-  return dtohl(entry_offsets[entry_index]);
+  if (UNLIKELY(!VerifyResTableEntry(best_type, best_offset, entry_idx))) {
+    return false;
+  }
+
+  const ResTable_entry* best_entry = reinterpret_cast<const ResTable_entry*>(
+      reinterpret_cast<const uint8_t*>(best_type) + best_offset + dtohl(best_type->entriesStart));
+
+  const uint32_t* flags = reinterpret_cast<const uint32_t*>(type_spec_ptr->type_spec + 1);
+  out_entry->type_flags = dtohl(flags[entry_idx]);
+  out_entry->entry = best_entry;
+  out_entry->config = best_config;
+  out_entry->type_string_ref = StringPoolRef(&type_string_pool_, best_type->id - 1);
+  out_entry->entry_string_ref = StringPoolRef(&key_string_pool_, dtohl(best_entry->key.index));
+  return true;
 }
 
-const ResTable_entry* LoadedPackage::GetEntryFromOffset(const ResTable_type* type_chunk,
-                                                        uint32_t offset) {
-  if (UNLIKELY(!VerifyResTableEntry(type_chunk, offset))) {
-    return nullptr;
+bool LoadedPackage::FindEntry(uint8_t type_idx, uint16_t entry_idx, const ResTable_config& config,
+                              FindEntryResult* out_entry) const {
+  ATRACE_CALL();
+
+  // If the type IDs are offset in this package, we need to take that into account when searching
+  // for a type.
+  const TypeSpecPtr& ptr = type_specs_[type_idx - type_id_offset_];
+  if (UNLIKELY(ptr == nullptr)) {
+    return false;
   }
-  return reinterpret_cast<const ResTable_entry*>(reinterpret_cast<const uint8_t*>(type_chunk) +
-                                                 offset + dtohl(type_chunk->entriesStart));
+
+  // If there is an IDMAP supplied with this package, translate the entry ID.
+  if (ptr->idmap_entries != nullptr) {
+    if (!LoadedIdmap::Lookup(ptr->idmap_entries, entry_idx, &entry_idx)) {
+      // There is no mapping, so the resource is not meant to be in this overlay package.
+      return false;
+    }
+  }
+  return FindEntry(ptr, entry_idx, config, out_entry);
 }
 
 void LoadedPackage::CollectConfigurations(bool exclude_mipmap,
@@ -267,7 +348,7 @@
   const static std::u16string kMipMap = u"mipmap";
   const size_t type_count = type_specs_.size();
   for (size_t i = 0; i < type_count; i++) {
-    const TypeSpecPtr& type_spec = type_specs_[i];
+    const util::unique_cptr<TypeSpec>& type_spec = type_specs_[i];
     if (type_spec != nullptr) {
       if (exclude_mipmap) {
         const int type_idx = type_spec->type_spec->id - 1;
@@ -288,11 +369,8 @@
         }
       }
 
-      const auto iter_end = type_spec->types + type_spec->type_count;
-      for (auto iter = type_spec->types; iter != iter_end; ++iter) {
-        ResTable_config config;
-        config.copyFromDtoH((*iter)->config);
-        out_configs->insert(config);
+      for (size_t j = 0; j < type_spec->type_count; j++) {
+        out_configs->insert(type_spec->types[j].configuration);
       }
     }
   }
@@ -302,12 +380,10 @@
   char temp_locale[RESTABLE_MAX_LOCALE_LEN];
   const size_t type_count = type_specs_.size();
   for (size_t i = 0; i < type_count; i++) {
-    const TypeSpecPtr& type_spec = type_specs_[i];
+    const util::unique_cptr<TypeSpec>& type_spec = type_specs_[i];
     if (type_spec != nullptr) {
-      const auto iter_end = type_spec->types + type_spec->type_count;
-      for (auto iter = type_spec->types; iter != iter_end; ++iter) {
-        ResTable_config configuration;
-        configuration.copyFromDtoH((*iter)->config);
+      for (size_t j = 0; j < type_spec->type_count; j++) {
+        const ResTable_config& configuration = type_spec->types[j].configuration;
         if (configuration.locale != 0) {
           configuration.getBcp47Locale(temp_locale, canonicalize);
           std::string locale(temp_locale);
@@ -335,17 +411,17 @@
     return 0u;
   }
 
-  const auto iter_end = type_spec->types + type_spec->type_count;
-  for (auto iter = type_spec->types; iter != iter_end; ++iter) {
-    const ResTable_type* type = *iter;
-    size_t entry_count = dtohl(type->entryCount);
+  for (size_t ti = 0; ti < type_spec->type_count; ti++) {
+    const Type* type = &type_spec->types[ti];
+    size_t entry_count = dtohl(type->type->entryCount);
     for (size_t entry_idx = 0; entry_idx < entry_count; entry_idx++) {
       const uint32_t* entry_offsets = reinterpret_cast<const uint32_t*>(
-          reinterpret_cast<const uint8_t*>(type) + dtohs(type->header.headerSize));
+          reinterpret_cast<const uint8_t*>(type->type) + dtohs(type->type->header.headerSize));
       const uint32_t offset = dtohl(entry_offsets[entry_idx]);
       if (offset != ResTable_type::NO_ENTRY) {
-        const ResTable_entry* entry = reinterpret_cast<const ResTable_entry*>(
-            reinterpret_cast<const uint8_t*>(type) + dtohl(type->entriesStart) + offset);
+        const ResTable_entry* entry =
+            reinterpret_cast<const ResTable_entry*>(reinterpret_cast<const uint8_t*>(type->type) +
+                                                    dtohl(type->type->entriesStart) + offset);
         if (dtohl(entry->key.index) == static_cast<uint32_t>(key_idx)) {
           // The package ID will be overridden by the caller (due to runtime assignment of package
           // IDs for shared libraries).
@@ -357,7 +433,8 @@
   return 0u;
 }
 
-const LoadedPackage* LoadedArsc::GetPackageById(uint8_t package_id) const {
+const LoadedPackage* LoadedArsc::GetPackageForId(uint32_t resid) const {
+  const uint8_t package_id = get_package_id(resid);
   for (const auto& loaded_package : packages_) {
     if (loaded_package->GetPackageId() == package_id) {
       return loaded_package.get();
@@ -409,10 +486,14 @@
   util::ReadUtf16StringFromDevice(header->name, arraysize(header->name),
                                   &loaded_package->package_name_);
 
-  // A map of TypeSpec builders, each associated with an type index.
-  // We use these to accumulate the set of Types available for a TypeSpec, and later build a single,
-  // contiguous block of memory that holds all the Types together with the TypeSpec.
-  std::unordered_map<int, std::unique_ptr<TypeSpecPtrBuilder>> type_builder_map;
+  // A TypeSpec builder. We use this to accumulate the set of Types
+  // available for a TypeSpec, and later build a single, contiguous block
+  // of memory that holds all the Types together with the TypeSpec.
+  std::unique_ptr<TypeSpecPtrBuilder> types_builder;
+
+  // Keep track of the last seen type index. Since type IDs are 1-based,
+  // this records their index, which is 0-based (type ID - 1).
+  uint8_t last_type_idx = 0;
 
   ChunkIterator iter(chunk.data_ptr(), chunk.data_size());
   while (iter.HasNext()) {
@@ -446,6 +527,28 @@
       case RES_TABLE_TYPE_SPEC_TYPE: {
         ATRACE_NAME("LoadTableTypeSpec");
 
+        // Starting a new TypeSpec, so finish the old one if there was one.
+        if (types_builder) {
+          TypeSpecPtr type_spec_ptr = types_builder->Build();
+          if (type_spec_ptr == nullptr) {
+            LOG(ERROR) << "Too many type configurations, overflow detected.";
+            return {};
+          }
+
+          // We only add the type to the package if there is no IDMAP, or if the type is
+          // overlaying something.
+          if (loaded_idmap == nullptr || type_spec_ptr->idmap_entries != nullptr) {
+            // If this is an overlay, insert it at the target type ID.
+            if (type_spec_ptr->idmap_entries != nullptr) {
+              last_type_idx = dtohs(type_spec_ptr->idmap_entries->target_type_id) - 1;
+            }
+            loaded_package->type_specs_.editItemAt(last_type_idx) = std::move(type_spec_ptr);
+          }
+
+          types_builder = {};
+          last_type_idx = 0;
+        }
+
         const ResTable_typeSpec* type_spec = child_chunk.header<ResTable_typeSpec>();
         if (type_spec == nullptr) {
           LOG(ERROR) << "RES_TABLE_TYPE_SPEC_TYPE too small.";
@@ -480,6 +583,8 @@
           return {};
         }
 
+        last_type_idx = type_spec->id - 1;
+
         // If this is an overlay, associate the mapping of this type to the target type
         // from the IDMAP.
         const IdmapEntry_header* idmap_entry_header = nullptr;
@@ -487,13 +592,7 @@
           idmap_entry_header = loaded_idmap->GetEntryMapForType(type_spec->id);
         }
 
-        std::unique_ptr<TypeSpecPtrBuilder>& builder_ptr = type_builder_map[type_spec->id - 1];
-        if (builder_ptr == nullptr) {
-          builder_ptr = util::make_unique<TypeSpecPtrBuilder>(type_spec, idmap_entry_header);
-        } else {
-          LOG(WARNING) << StringPrintf("RES_TABLE_TYPE_SPEC_TYPE already defined for ID %02x",
-                                       type_spec->id);
-        }
+        types_builder = util::make_unique<TypeSpecPtrBuilder>(type_spec, idmap_entry_header);
       } break;
 
       case RES_TABLE_TYPE_TYPE: {
@@ -508,15 +607,12 @@
         }
 
         // Type chunks must be preceded by their TypeSpec chunks.
-        std::unique_ptr<TypeSpecPtrBuilder>& builder_ptr = type_builder_map[type->id - 1];
-        if (builder_ptr != nullptr) {
-          builder_ptr->AddType(type);
-        } else {
-          LOG(ERROR) << StringPrintf(
-              "RES_TABLE_TYPE_TYPE with ID %02x found without preceding RES_TABLE_TYPE_SPEC_TYPE.",
-              type->id);
+        if (!types_builder || type->id - 1 != last_type_idx) {
+          LOG(ERROR) << "RES_TABLE_TYPE_TYPE found without preceding RES_TABLE_TYPE_SPEC_TYPE.";
           return {};
         }
+
+        types_builder->AddType(type);
       } break;
 
       case RES_TABLE_LIBRARY_TYPE: {
@@ -542,7 +638,7 @@
                                           arraysize(entry_iter->packageName), &package_name);
 
           if (dtohl(entry_iter->packageId) >= std::numeric_limits<uint8_t>::max()) {
-            LOG(ERROR) << StringPrintf(
+            LOG(ERROR) << base::StringPrintf(
                 "Package ID %02x in RES_TABLE_LIBRARY_TYPE too large for package '%s'.",
                 dtohl(entry_iter->packageId), package_name.c_str());
             return {};
@@ -555,20 +651,14 @@
       } break;
 
       default:
-        LOG(WARNING) << StringPrintf("Unknown chunk type '%02x'.", chunk.type());
+        LOG(WARNING) << base::StringPrintf("Unknown chunk type '%02x'.", chunk.type());
         break;
     }
   }
 
-  if (iter.HadError()) {
-    LOG(ERROR) << iter.GetLastError();
-    return {};
-  }
-
-  // Flatten and construct the TypeSpecs.
-  for (auto& entry : type_builder_map) {
-    uint8_t type_idx = static_cast<uint8_t>(entry.first);
-    TypeSpecPtr type_spec_ptr = entry.second->Build();
+  // Finish the last TypeSpec.
+  if (types_builder) {
+    TypeSpecPtr type_spec_ptr = types_builder->Build();
     if (type_spec_ptr == nullptr) {
       LOG(ERROR) << "Too many type configurations, overflow detected.";
       return {};
@@ -579,15 +669,40 @@
     if (loaded_idmap == nullptr || type_spec_ptr->idmap_entries != nullptr) {
       // If this is an overlay, insert it at the target type ID.
       if (type_spec_ptr->idmap_entries != nullptr) {
-        type_idx = dtohs(type_spec_ptr->idmap_entries->target_type_id) - 1;
+        last_type_idx = dtohs(type_spec_ptr->idmap_entries->target_type_id) - 1;
       }
-      loaded_package->type_specs_.editItemAt(type_idx) = std::move(type_spec_ptr);
+      loaded_package->type_specs_.editItemAt(last_type_idx) = std::move(type_spec_ptr);
     }
   }
 
+  if (iter.HadError()) {
+    LOG(ERROR) << iter.GetLastError();
+    return {};
+  }
   return std::move(loaded_package);
 }
 
+bool LoadedArsc::FindEntry(uint32_t resid, const ResTable_config& config,
+                           FindEntryResult* out_entry) const {
+  ATRACE_CALL();
+
+  const uint8_t package_id = get_package_id(resid);
+  const uint8_t type_id = get_type_id(resid);
+  const uint16_t entry_id = get_entry_id(resid);
+
+  if (UNLIKELY(type_id == 0)) {
+    LOG(ERROR) << base::StringPrintf("Invalid ID 0x%08x.", resid);
+    return false;
+  }
+
+  for (const auto& loaded_package : packages_) {
+    if (loaded_package->GetPackageId() == package_id) {
+      return loaded_package->FindEntry(type_id - 1, entry_id, config, out_entry);
+    }
+  }
+  return false;
+}
+
 bool LoadedArsc::LoadTable(const Chunk& chunk, const LoadedIdmap* loaded_idmap,
                            bool load_as_shared_library) {
   ATRACE_CALL();
@@ -637,7 +752,7 @@
       } break;
 
       default:
-        LOG(WARNING) << StringPrintf("Unknown chunk type '%02x'.", chunk.type());
+        LOG(WARNING) << base::StringPrintf("Unknown chunk type '%02x'.", chunk.type());
         break;
     }
   }
@@ -669,7 +784,7 @@
         break;
 
       default:
-        LOG(WARNING) << StringPrintf("Unknown chunk type '%02x'.", chunk.type());
+        LOG(WARNING) << base::StringPrintf("Unknown chunk type '%02x'.", chunk.type());
         break;
     }
   }
diff --git a/libs/androidfw/include/androidfw/AssetManager2.h b/libs/androidfw/include/androidfw/AssetManager2.h
index ef08897..b033137 100644
--- a/libs/androidfw/include/androidfw/AssetManager2.h
+++ b/libs/androidfw/include/androidfw/AssetManager2.h
@@ -69,8 +69,6 @@
   Entry entries[0];
 };
 
-struct FindEntryResult;
-
 // AssetManager2 is the main entry point for accessing assets and resources.
 // AssetManager2 provides caching of resources retrieved via the underlying ApkAssets.
 class AssetManager2 {
@@ -129,7 +127,7 @@
   // If `exclude_mipmap` is set to true, resource configurations defined for resource type 'mipmap'
   // will be excluded from the list.
   std::set<ResTable_config> GetResourceConfigurations(bool exclude_system = false,
-                                                      bool exclude_mipmap = false) const;
+                                                      bool exclude_mipmap = false);
 
   // Returns all the locales for which there are resources defined. This includes resource
   // locales in all the ApkAssets set for this AssetManager.
@@ -138,24 +136,24 @@
   // If `merge_equivalent_languages` is set to true, resource locales will be canonicalized
   // and de-duped in the resulting list.
   std::set<std::string> GetResourceLocales(bool exclude_system = false,
-                                           bool merge_equivalent_languages = false) const;
+                                           bool merge_equivalent_languages = false);
 
   // Searches the set of APKs loaded by this AssetManager and opens the first one found located
   // in the assets/ directory.
   // `mode` controls how the file is opened.
   //
   // NOTE: The loaded APKs are searched in reverse order.
-  std::unique_ptr<Asset> Open(const std::string& filename, Asset::AccessMode mode) const;
+  std::unique_ptr<Asset> Open(const std::string& filename, Asset::AccessMode mode);
 
   // Opens a file within the assets/ directory of the APK specified by `cookie`.
   // `mode` controls how the file is opened.
   std::unique_ptr<Asset> Open(const std::string& filename, ApkAssetsCookie cookie,
-                              Asset::AccessMode mode) const;
+                              Asset::AccessMode mode);
 
   // Opens the directory specified by `dirname`. The result is an AssetDir that is the combination
   // of all directories matching `dirname` under the assets/ directory of every ApkAssets loaded.
   // The entries are sorted by their ASCII name.
-  std::unique_ptr<AssetDir> OpenDir(const std::string& dirname) const;
+  std::unique_ptr<AssetDir> OpenDir(const std::string& dirname);
 
   // Searches the set of APKs loaded by this AssetManager and opens the first one found.
   // `mode` controls how the file is opened.
@@ -163,24 +161,24 @@
   //
   // NOTE: The loaded APKs are searched in reverse order.
   std::unique_ptr<Asset> OpenNonAsset(const std::string& filename, Asset::AccessMode mode,
-                                      ApkAssetsCookie* out_cookie = nullptr) const;
+                                      ApkAssetsCookie* out_cookie = nullptr);
 
   // Opens a file in the APK specified by `cookie`. `mode` controls how the file is opened.
   // This is typically used to open a specific AndroidManifest.xml, or a binary XML file
   // referenced by a resource lookup with GetResource().
   std::unique_ptr<Asset> OpenNonAsset(const std::string& filename, ApkAssetsCookie cookie,
-                                      Asset::AccessMode mode) const;
+                                      Asset::AccessMode mode);
 
   // Populates the `out_name` parameter with resource name information.
   // Utf8 strings are preferred, and only if they are unavailable are
   // the Utf16 variants populated.
   // Returns false if the resource was not found or the name was missing/corrupt.
-  bool GetResourceName(uint32_t resid, ResourceName* out_name) const;
+  bool GetResourceName(uint32_t resid, ResourceName* out_name);
 
   // Populates `out_flags` with the bitmask of configuration axis that this resource varies with.
   // See ResTable_config for the list of configuration axis.
   // Returns false if the resource was not found.
-  bool GetResourceFlags(uint32_t resid, uint32_t* out_flags) const;
+  bool GetResourceFlags(uint32_t resid, uint32_t* out_flags);
 
   // Finds the resource ID assigned to `resource_name`.
   // `resource_name` must be of the form '[package:][type/]entry'.
@@ -188,7 +186,7 @@
   // If no type is specified in `resource_name`, then `fallback_type` is used as the type.
   // Returns 0x0 if no resource by that name was found.
   uint32_t GetResourceId(const std::string& resource_name, const std::string& fallback_type = {},
-                         const std::string& fallback_package = {}) const;
+                         const std::string& fallback_package = {});
 
   // Retrieves the best matching resource with ID `resid`. The resource value is filled into
   // `out_value` and the configuration for the selected value is populated in `out_selected_config`.
@@ -201,7 +199,7 @@
   // this function logs if the resource was a map/bag type before returning kInvalidCookie.
   ApkAssetsCookie GetResource(uint32_t resid, bool may_be_bag, uint16_t density_override,
                               Res_value* out_value, ResTable_config* out_selected_config,
-                              uint32_t* out_flags) const;
+                              uint32_t* out_flags);
 
   // Resolves the resource reference in `in_out_value` if the data type is
   // Res_value::TYPE_REFERENCE.
@@ -217,7 +215,7 @@
   // it was not found.
   ApkAssetsCookie ResolveReference(ApkAssetsCookie cookie, Res_value* in_out_value,
                                    ResTable_config* in_out_selected_config, uint32_t* in_out_flags,
-                                   uint32_t* out_last_reference) const;
+                                   uint32_t* out_last_reference);
 
   // Retrieves the best matching bag/map resource with ID `resid`.
   // This method will resolve all parent references for this bag and merge keys with the child.
@@ -235,9 +233,9 @@
   std::unique_ptr<Theme> NewTheme();
 
   template <typename Func>
-  void ForEachPackage(Func func) const {
+  void ForEachPackage(Func func) {
     for (const PackageGroup& package_group : package_groups_) {
-      func(package_group.packages_.front().loaded_package_->GetPackageName(),
+      func(package_group.packages_.front()->GetPackageName(),
            package_group.dynamic_ref_table.mAssignedPackageId);
     }
   }
@@ -262,7 +260,7 @@
   // NOTE: FindEntry takes care of ensuring that structs within FindEntryResult have been properly
   // bounds-checked. Callers of FindEntry are free to trust the data if this method succeeds.
   ApkAssetsCookie FindEntry(uint32_t resid, uint16_t density_override, bool stop_at_first_match,
-                            FindEntryResult* out_entry) const;
+                            FindEntryResult* out_entry);
 
   // Assigns package IDs to all shared library ApkAssets.
   // Should be called whenever the ApkAssets are changed.
@@ -272,43 +270,13 @@
   // bitmask `diff`.
   void InvalidateCaches(uint32_t diff);
 
-  // Triggers the re-construction of lists of types that match the set configuration.
-  // This should always be called when mutating the AssetManager's configuration or ApkAssets set.
-  void RebuildFilterList();
-
   // The ordered list of ApkAssets to search. These are not owned by the AssetManager, and must
   // have a longer lifetime.
   std::vector<const ApkAssets*> apk_assets_;
 
-  // A collection of configurations and their associated ResTable_type that match the current
-  // AssetManager configuration.
-  struct FilteredConfigGroup {
-    std::vector<ResTable_config> configurations;
-    std::vector<const ResTable_type*> types;
-  };
-
-  // Represents an single package.
-  struct ConfiguredPackage {
-    // A pointer to the immutable, loaded package info.
-    const LoadedPackage* loaded_package_;
-
-    // A mutable AssetManager-specific list of configurations that match the AssetManager's
-    // current configuration. This is used as an optimization to avoid checking every single
-    // candidate configuration when looking up resources.
-    ByteBucketArray<FilteredConfigGroup> filtered_configs_;
-  };
-
-  // Represents a logical package, which can be made up of many individual packages. Each package
-  // in a PackageGroup shares the same package name and package ID.
   struct PackageGroup {
-    // The set of packages that make-up this group.
-    std::vector<ConfiguredPackage> packages_;
-
-    // The cookies associated with each package in the group. They share the same order as
-    // packages_.
+    std::vector<const LoadedPackage*> packages_;
     std::vector<ApkAssetsCookie> cookies_;
-
-    // A library reference table that contains build-package ID to runtime-package ID mappings.
     DynamicRefTable dynamic_ref_table;
   };
 
@@ -382,7 +350,7 @@
   ApkAssetsCookie ResolveAttributeReference(ApkAssetsCookie cookie, Res_value* in_out_value,
                                             ResTable_config* in_out_selected_config = nullptr,
                                             uint32_t* in_out_type_spec_flags = nullptr,
-                                            uint32_t* out_last_ref = nullptr) const;
+                                            uint32_t* out_last_ref = nullptr);
 
  private:
   DISALLOW_COPY_AND_ASSIGN(Theme);
diff --git a/libs/androidfw/include/androidfw/AttributeFinder.h b/libs/androidfw/include/androidfw/AttributeFinder.h
index 03fad49..f281921 100644
--- a/libs/androidfw/include/androidfw/AttributeFinder.h
+++ b/libs/androidfw/include/androidfw/AttributeFinder.h
@@ -58,7 +58,6 @@
   BackTrackingAttributeFinder(const Iterator& begin, const Iterator& end);
 
   Iterator Find(uint32_t attr);
-  inline Iterator end();
 
  private:
   void JumpToClosestAttribute(uint32_t package_id);
@@ -202,11 +201,6 @@
   return end_;
 }
 
-template <typename Derived, typename Iterator>
-Iterator BackTrackingAttributeFinder<Derived, Iterator>::end() {
-  return end_;
-}
-
 }  // namespace android
 
 #endif  // ANDROIDFW_ATTRIBUTE_FINDER_H
diff --git a/libs/androidfw/include/androidfw/AttributeResolution.h b/libs/androidfw/include/androidfw/AttributeResolution.h
index 35ef98d..69b76041 100644
--- a/libs/androidfw/include/androidfw/AttributeResolution.h
+++ b/libs/androidfw/include/androidfw/AttributeResolution.h
@@ -17,8 +17,7 @@
 #ifndef ANDROIDFW_ATTRIBUTERESOLUTION_H
 #define ANDROIDFW_ATTRIBUTERESOLUTION_H
 
-#include "androidfw/AssetManager2.h"
-#include "androidfw/ResourceTypes.h"
+#include <androidfw/ResourceTypes.h>
 
 namespace android {
 
@@ -43,19 +42,19 @@
 
 // `out_values` must NOT be nullptr.
 // `out_indices` may be nullptr.
-bool ResolveAttrs(Theme* theme, uint32_t def_style_attr, uint32_t def_style_resid,
+bool ResolveAttrs(ResTable::Theme* theme, uint32_t def_style_attr, uint32_t def_style_res,
                   uint32_t* src_values, size_t src_values_length, uint32_t* attrs,
                   size_t attrs_length, uint32_t* out_values, uint32_t* out_indices);
 
 // `out_values` must NOT be nullptr.
 // `out_indices` is NOT optional and must NOT be nullptr.
-void ApplyStyle(Theme* theme, ResXMLParser* xml_parser, uint32_t def_style_attr,
-                uint32_t def_style_resid, const uint32_t* attrs, size_t attrs_length,
+void ApplyStyle(ResTable::Theme* theme, ResXMLParser* xml_parser, uint32_t def_style_attr,
+                uint32_t def_style_res, const uint32_t* attrs, size_t attrs_length,
                 uint32_t* out_values, uint32_t* out_indices);
 
 // `out_values` must NOT be nullptr.
 // `out_indices` may be nullptr.
-bool RetrieveAttributes(AssetManager2* assetmanager, ResXMLParser* xml_parser, uint32_t* attrs,
+bool RetrieveAttributes(const ResTable* res, ResXMLParser* xml_parser, uint32_t* attrs,
                         size_t attrs_length, uint32_t* out_values, uint32_t* out_indices);
 
 }  // namespace android
diff --git a/libs/androidfw/include/androidfw/LoadedArsc.h b/libs/androidfw/include/androidfw/LoadedArsc.h
index 35ae5fc..965e2db 100644
--- a/libs/androidfw/include/androidfw/LoadedArsc.h
+++ b/libs/androidfw/include/androidfw/LoadedArsc.h
@@ -41,40 +41,32 @@
   int package_id = 0;
 };
 
-// TypeSpec is going to be immediately proceeded by
-// an array of Type structs, all in the same block of memory.
-struct TypeSpec {
-  // Pointer to the mmapped data where flags are kept.
-  // Flags denote whether the resource entry is public
-  // and under which configurations it varies.
-  const ResTable_typeSpec* type_spec;
+struct FindEntryResult {
+  // A pointer to the resource table entry for this resource.
+  // If the size of the entry is > sizeof(ResTable_entry), it can be cast to
+  // a ResTable_map_entry and processed as a bag/map.
+  const ResTable_entry* entry = nullptr;
 
-  // Pointer to the mmapped data where the IDMAP mappings for this type
-  // exist. May be nullptr if no IDMAP exists.
-  const IdmapEntry_header* idmap_entries;
+  // The configuration for which the resulting entry was defined.
+  const ResTable_config* config = nullptr;
 
-  // The number of types that follow this struct.
-  // There is a type for each configuration that entries are defined for.
-  size_t type_count;
+  // Stores the resulting bitmask of configuration axis with which the resource value varies.
+  uint32_t type_flags = 0u;
 
-  // Trick to easily access a variable number of Type structs
-  // proceeding this struct, and to ensure their alignment.
-  const ResTable_type* types[0];
+  // The dynamic package ID map for the package from which this resource came from.
+  const DynamicRefTable* dynamic_ref_table = nullptr;
 
-  inline uint32_t GetFlagsForEntryIndex(uint16_t entry_index) const {
-    if (entry_index >= dtohl(type_spec->entryCount)) {
-      return 0u;
-    }
+  // The string pool reference to the type's name. This uses a different string pool than
+  // the global string pool, but this is hidden from the caller.
+  StringPoolRef type_string_ref;
 
-    const uint32_t* flags = reinterpret_cast<const uint32_t*>(type_spec + 1);
-    return flags[entry_index];
-  }
+  // The string pool reference to the entry's name. This uses a different string pool than
+  // the global string pool, but this is hidden from the caller.
+  StringPoolRef entry_string_ref;
 };
 
-// TypeSpecPtr points to a block of memory that holds a TypeSpec struct, followed by an array of
-// ResTable_type pointers.
-// TypeSpecPtr is a managed pointer that knows how to delete itself.
-using TypeSpecPtr = util::unique_cptr<TypeSpec>;
+struct TypeSpec;
+class LoadedArsc;
 
 class LoadedPackage {
  public:
@@ -84,6 +76,9 @@
 
   ~LoadedPackage();
 
+  bool FindEntry(uint8_t type_idx, uint16_t entry_idx, const ResTable_config& config,
+                 FindEntryResult* out_entry) const;
+
   // Finds the entry with the specified type name and entry name. The names are in UTF-16 because
   // the underlying ResStringPool API expects this. For now this is acceptable, but since
   // the default policy in AAPT2 is to build UTF-8 string pools, this needs to change.
@@ -91,12 +86,6 @@
   // for patching the correct package ID to the resource ID.
   uint32_t FindEntryByName(const std::u16string& type_name, const std::u16string& entry_name) const;
 
-  static const ResTable_entry* GetEntry(const ResTable_type* type_chunk, uint16_t entry_index);
-
-  static uint32_t GetEntryOffset(const ResTable_type* type_chunk, uint16_t entry_index);
-
-  static const ResTable_entry* GetEntryFromOffset(const ResTable_type* type_chunk, uint32_t offset);
-
   // Returns the string pool where type names are stored.
   inline const ResStringPool* GetTypeStringPool() const {
     return &type_string_pool_;
@@ -146,32 +135,14 @@
   // before being inserted into the set. This may cause some equivalent locales to de-dupe.
   void CollectLocales(bool canonicalize, std::set<std::string>* out_locales) const;
 
-  // type_idx is TT - 1 from 0xPPTTEEEE.
-  inline const TypeSpec* GetTypeSpecByTypeIndex(uint8_t type_index) const {
-    // If the type IDs are offset in this package, we need to take that into account when searching
-    // for a type.
-    return type_specs_[type_index - type_id_offset_].get();
-  }
-
-  template <typename Func>
-  void ForEachTypeSpec(Func f) const {
-    for (size_t i = 0; i < type_specs_.size(); i++) {
-      const TypeSpecPtr& ptr = type_specs_[i];
-      if (ptr != nullptr) {
-        uint8_t type_id = ptr->type_spec->id;
-        if (ptr->idmap_entries != nullptr) {
-          type_id = ptr->idmap_entries->target_type_id;
-        }
-        f(ptr.get(), type_id - 1);
-      }
-    }
-  }
-
  private:
   DISALLOW_COPY_AND_ASSIGN(LoadedPackage);
 
   LoadedPackage();
 
+  bool FindEntry(const util::unique_cptr<TypeSpec>& type_spec_ptr, uint16_t entry_idx,
+                 const ResTable_config& config, FindEntryResult* out_entry) const;
+
   ResStringPool type_string_pool_;
   ResStringPool key_string_pool_;
   std::string package_name_;
@@ -181,7 +152,7 @@
   bool system_ = false;
   bool overlay_ = false;
 
-  ByteBucketArray<TypeSpecPtr> type_specs_;
+  ByteBucketArray<util::unique_cptr<TypeSpec>> type_specs_;
   std::vector<DynamicPackageEntry> dynamic_package_map_;
 };
 
@@ -209,20 +180,25 @@
     return &global_string_pool_;
   }
 
-  // Gets a pointer to the package with the specified package ID, or nullptr if no such package
-  // exists.
-  const LoadedPackage* GetPackageById(uint8_t package_id) const;
+  // Finds the resource with ID `resid` with the best value for configuration `config`.
+  // The parameter `out_entry` will be filled with the resulting resource entry.
+  // The resource entry can be a simple entry (ResTable_entry) or a complex bag
+  // (ResTable_entry_map).
+  bool FindEntry(uint32_t resid, const ResTable_config& config, FindEntryResult* out_entry) const;
 
-  // Returns a vector of LoadedPackage pointers, representing the packages in this LoadedArsc.
-  inline const std::vector<std::unique_ptr<const LoadedPackage>>& GetPackages() const {
-    return packages_;
-  }
+  // Gets a pointer to the name of the package in `resid`, or nullptr if the package doesn't exist.
+  const LoadedPackage* GetPackageForId(uint32_t resid) const;
 
   // Returns true if this is a system provided resource.
   inline bool IsSystem() const {
     return system_;
   }
 
+  // Returns a vector of LoadedPackage pointers, representing the packages in this LoadedArsc.
+  inline const std::vector<std::unique_ptr<const LoadedPackage>>& GetPackages() const {
+    return packages_;
+  }
+
  private:
   DISALLOW_COPY_AND_ASSIGN(LoadedArsc);
 
diff --git a/libs/androidfw/include/androidfw/MutexGuard.h b/libs/androidfw/include/androidfw/MutexGuard.h
deleted file mode 100644
index 64924f4..0000000
--- a/libs/androidfw/include/androidfw/MutexGuard.h
+++ /dev/null
@@ -1,101 +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.
- */
-
-#ifndef ANDROIDFW_MUTEXGUARD_H
-#define ANDROIDFW_MUTEXGUARD_H
-
-#include <mutex>
-#include <type_traits>
-
-#include "android-base/macros.h"
-
-namespace android {
-
-template <typename T>
-class ScopedLock;
-
-// Owns the guarded object and protects access to it via a mutex.
-// The guarded object is inaccessible via this class.
-// The mutex is locked and the object accessed via the ScopedLock<T> class.
-//
-// NOTE: The template parameter T should not be a raw pointer, since ownership
-// is ambiguous and error-prone. Instead use an std::unique_ptr<>.
-//
-// Example use:
-//
-//   Guarded<std::string> shared_string("hello");
-//   {
-//     ScopedLock<std::string> locked_string(shared_string);
-//     *locked_string += " world";
-//   }
-//
-template <typename T>
-class Guarded {
-  static_assert(!std::is_pointer<T>::value, "T must not be a raw pointer");
-
- public:
-  explicit Guarded() : guarded_() {
-  }
-
-  template <typename U = T>
-  explicit Guarded(const T& guarded,
-                   typename std::enable_if<std::is_copy_constructible<U>::value>::type = void())
-      : guarded_(guarded) {
-  }
-
-  template <typename U = T>
-  explicit Guarded(T&& guarded,
-                   typename std::enable_if<std::is_move_constructible<U>::value>::type = void())
-      : guarded_(std::move(guarded)) {
-  }
-
- private:
-  friend class ScopedLock<T>;
-
-  DISALLOW_COPY_AND_ASSIGN(Guarded);
-
-  std::mutex lock_;
-  T guarded_;
-};
-
-template <typename T>
-class ScopedLock {
- public:
-  explicit ScopedLock(Guarded<T>& guarded) : lock_(guarded.lock_), guarded_(guarded.guarded_) {
-  }
-
-  T& operator*() {
-    return guarded_;
-  }
-
-  T* operator->() {
-    return &guarded_;
-  }
-
-  T* get() {
-    return &guarded_;
-  }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(ScopedLock);
-
-  std::lock_guard<std::mutex> lock_;
-  T& guarded_;
-};
-
-}  // namespace android
-
-#endif  // ANDROIDFW_MUTEXGUARD_H
diff --git a/libs/androidfw/include/androidfw/ResourceUtils.h b/libs/androidfw/include/androidfw/ResourceUtils.h
index d94779b..c2eae85 100644
--- a/libs/androidfw/include/androidfw/ResourceUtils.h
+++ b/libs/androidfw/include/androidfw/ResourceUtils.h
@@ -28,7 +28,7 @@
                          StringPiece* out_entry);
 
 inline uint32_t fix_package_id(uint32_t resid, uint8_t package_id) {
-  return (resid & 0x00ffffffu) | (static_cast<uint32_t>(package_id) << 24);
+  return resid | (static_cast<uint32_t>(package_id) << 24);
 }
 
 inline uint8_t get_package_id(uint32_t resid) {
diff --git a/libs/androidfw/tests/ApkAssets_test.cpp b/libs/androidfw/tests/ApkAssets_test.cpp
index e2b9f00..6c43a67 100644
--- a/libs/androidfw/tests/ApkAssets_test.cpp
+++ b/libs/androidfw/tests/ApkAssets_test.cpp
@@ -26,56 +26,58 @@
 
 using ::android::base::unique_fd;
 using ::com::android::basic::R;
-using ::testing::Eq;
-using ::testing::Ge;
-using ::testing::NotNull;
-using ::testing::SizeIs;
-using ::testing::StrEq;
 
 namespace android {
 
 TEST(ApkAssetsTest, LoadApk) {
   std::unique_ptr<const ApkAssets> loaded_apk =
       ApkAssets::Load(GetTestDataPath() + "/basic/basic.apk");
-  ASSERT_THAT(loaded_apk, NotNull());
+  ASSERT_NE(nullptr, loaded_apk);
 
   const LoadedArsc* loaded_arsc = loaded_apk->GetLoadedArsc();
-  ASSERT_THAT(loaded_arsc, NotNull());
-  ASSERT_THAT(loaded_arsc->GetPackageById(0x7fu), NotNull());
-  ASSERT_THAT(loaded_apk->Open("res/layout/main.xml"), NotNull());
+  ASSERT_NE(nullptr, loaded_arsc);
+
+  const LoadedPackage* loaded_package = loaded_arsc->GetPackageForId(0x7f010000);
+  ASSERT_NE(nullptr, loaded_package);
+
+  std::unique_ptr<Asset> asset = loaded_apk->Open("res/layout/main.xml");
+  ASSERT_NE(nullptr, asset);
 }
 
 TEST(ApkAssetsTest, LoadApkFromFd) {
   const std::string path = GetTestDataPath() + "/basic/basic.apk";
   unique_fd fd(::open(path.c_str(), O_RDONLY | O_BINARY));
-  ASSERT_THAT(fd.get(), Ge(0));
+  ASSERT_GE(fd.get(), 0);
 
   std::unique_ptr<const ApkAssets> loaded_apk =
       ApkAssets::LoadFromFd(std::move(fd), path, false /*system*/, false /*force_shared_lib*/);
-  ASSERT_THAT(loaded_apk, NotNull());
+  ASSERT_NE(nullptr, loaded_apk);
 
   const LoadedArsc* loaded_arsc = loaded_apk->GetLoadedArsc();
-  ASSERT_THAT(loaded_arsc, NotNull());
-  ASSERT_THAT(loaded_arsc->GetPackageById(0x7fu), NotNull());
-  ASSERT_THAT(loaded_apk->Open("res/layout/main.xml"), NotNull());
+  ASSERT_NE(nullptr, loaded_arsc);
+
+  const LoadedPackage* loaded_package = loaded_arsc->GetPackageForId(0x7f010000);
+  ASSERT_NE(nullptr, loaded_package);
+
+  std::unique_ptr<Asset> asset = loaded_apk->Open("res/layout/main.xml");
+  ASSERT_NE(nullptr, asset);
 }
 
 TEST(ApkAssetsTest, LoadApkAsSharedLibrary) {
   std::unique_ptr<const ApkAssets> loaded_apk =
       ApkAssets::Load(GetTestDataPath() + "/appaslib/appaslib.apk");
-  ASSERT_THAT(loaded_apk, NotNull());
-
+  ASSERT_NE(nullptr, loaded_apk);
   const LoadedArsc* loaded_arsc = loaded_apk->GetLoadedArsc();
-  ASSERT_THAT(loaded_arsc, NotNull());
-  ASSERT_THAT(loaded_arsc->GetPackages(), SizeIs(1u));
+  ASSERT_NE(nullptr, loaded_arsc);
+  ASSERT_EQ(1u, loaded_arsc->GetPackages().size());
   EXPECT_FALSE(loaded_arsc->GetPackages()[0]->IsDynamic());
 
   loaded_apk = ApkAssets::LoadAsSharedLibrary(GetTestDataPath() + "/appaslib/appaslib.apk");
-  ASSERT_THAT(loaded_apk, NotNull());
+  ASSERT_NE(nullptr, loaded_apk);
 
   loaded_arsc = loaded_apk->GetLoadedArsc();
-  ASSERT_THAT(loaded_arsc, NotNull());
-  ASSERT_THAT(loaded_arsc->GetPackages(), SizeIs(1u));
+  ASSERT_NE(nullptr, loaded_arsc);
+  ASSERT_EQ(1u, loaded_arsc->GetPackages().size());
   EXPECT_TRUE(loaded_arsc->GetPackages()[0]->IsDynamic());
 }
 
@@ -84,22 +86,19 @@
   ResTable target_table;
   const std::string target_path = GetTestDataPath() + "/basic/basic.apk";
   ASSERT_TRUE(ReadFileFromZipToString(target_path, "resources.arsc", &contents));
-  ASSERT_THAT(target_table.add(contents.data(), contents.size(), 0, true /*copyData*/),
-              Eq(NO_ERROR));
+  ASSERT_EQ(NO_ERROR, target_table.add(contents.data(), contents.size(), 0, true /*copyData*/));
 
   ResTable overlay_table;
   const std::string overlay_path = GetTestDataPath() + "/overlay/overlay.apk";
   ASSERT_TRUE(ReadFileFromZipToString(overlay_path, "resources.arsc", &contents));
-  ASSERT_THAT(overlay_table.add(contents.data(), contents.size(), 0, true /*copyData*/),
-              Eq(NO_ERROR));
+  ASSERT_EQ(NO_ERROR, overlay_table.add(contents.data(), contents.size(), 0, true /*copyData*/));
 
   util::unique_cptr<void> idmap_data;
   void* temp_data;
   size_t idmap_len;
 
-  ASSERT_THAT(target_table.createIdmap(overlay_table, 0u, 0u, target_path.c_str(),
-                                       overlay_path.c_str(), &temp_data, &idmap_len),
-              Eq(NO_ERROR));
+  ASSERT_EQ(NO_ERROR, target_table.createIdmap(overlay_table, 0u, 0u, target_path.c_str(),
+                                               overlay_path.c_str(), &temp_data, &idmap_len));
   idmap_data.reset(temp_data);
 
   TemporaryFile tf;
@@ -109,30 +108,37 @@
   // Open something so that the destructor of TemporaryFile closes a valid fd.
   tf.fd = open("/dev/null", O_WRONLY);
 
-  ASSERT_THAT(ApkAssets::LoadOverlay(tf.path), NotNull());
+  std::unique_ptr<const ApkAssets> loaded_overlay_apk = ApkAssets::LoadOverlay(tf.path);
+  ASSERT_NE(nullptr, loaded_overlay_apk);
 }
 
 TEST(ApkAssetsTest, CreateAndDestroyAssetKeepsApkAssetsOpen) {
   std::unique_ptr<const ApkAssets> loaded_apk =
       ApkAssets::Load(GetTestDataPath() + "/basic/basic.apk");
-  ASSERT_THAT(loaded_apk, NotNull());
+  ASSERT_NE(nullptr, loaded_apk);
 
-  { ASSERT_THAT(loaded_apk->Open("res/layout/main.xml", Asset::ACCESS_BUFFER), NotNull()); }
+  {
+    std::unique_ptr<Asset> assets = loaded_apk->Open("res/layout/main.xml", Asset::ACCESS_BUFFER);
+    ASSERT_NE(nullptr, assets);
+  }
 
-  { ASSERT_THAT(loaded_apk->Open("res/layout/main.xml", Asset::ACCESS_BUFFER), NotNull()); }
+  {
+    std::unique_ptr<Asset> assets = loaded_apk->Open("res/layout/main.xml", Asset::ACCESS_BUFFER);
+    ASSERT_NE(nullptr, assets);
+  }
 }
 
 TEST(ApkAssetsTest, OpenUncompressedAssetFd) {
   std::unique_ptr<const ApkAssets> loaded_apk =
       ApkAssets::Load(GetTestDataPath() + "/basic/basic.apk");
-  ASSERT_THAT(loaded_apk, NotNull());
+  ASSERT_NE(nullptr, loaded_apk);
 
   auto asset = loaded_apk->Open("assets/uncompressed.txt", Asset::ACCESS_UNKNOWN);
-  ASSERT_THAT(asset, NotNull());
+  ASSERT_NE(nullptr, asset);
 
   off64_t start, length;
   unique_fd fd(asset->openFileDescriptor(&start, &length));
-  ASSERT_THAT(fd.get(), Ge(0));
+  EXPECT_GE(fd.get(), 0);
 
   lseek64(fd.get(), start, SEEK_SET);
 
@@ -140,7 +146,7 @@
   buffer.resize(length);
   ASSERT_TRUE(base::ReadFully(fd.get(), &*buffer.begin(), length));
 
-  EXPECT_THAT(buffer, StrEq("This should be uncompressed.\n\n"));
+  EXPECT_EQ("This should be uncompressed.\n\n", buffer);
 }
 
 }  // namespace android
diff --git a/libs/androidfw/tests/AssetManager2_bench.cpp b/libs/androidfw/tests/AssetManager2_bench.cpp
index 437e147..85e8f25 100644
--- a/libs/androidfw/tests/AssetManager2_bench.cpp
+++ b/libs/androidfw/tests/AssetManager2_bench.cpp
@@ -81,18 +81,17 @@
 }
 BENCHMARK(BM_AssetManagerLoadFrameworkAssetsOld);
 
-static void BM_AssetManagerGetResource(benchmark::State& state, uint32_t resid) {
-  GetResourceBenchmark({GetTestDataPath() + "/basic/basic.apk"}, nullptr /*config*/, resid, state);
+static void BM_AssetManagerGetResource(benchmark::State& state) {
+  GetResourceBenchmark({GetTestDataPath() + "/basic/basic.apk"}, nullptr /*config*/,
+                       basic::R::integer::number1, state);
 }
-BENCHMARK_CAPTURE(BM_AssetManagerGetResource, number1, basic::R::integer::number1);
-BENCHMARK_CAPTURE(BM_AssetManagerGetResource, deep_ref, basic::R::integer::deep_ref);
+BENCHMARK(BM_AssetManagerGetResource);
 
-static void BM_AssetManagerGetResourceOld(benchmark::State& state, uint32_t resid) {
-  GetResourceBenchmarkOld({GetTestDataPath() + "/basic/basic.apk"}, nullptr /*config*/, resid,
-                          state);
+static void BM_AssetManagerGetResourceOld(benchmark::State& state) {
+  GetResourceBenchmarkOld({GetTestDataPath() + "/basic/basic.apk"}, nullptr /*config*/,
+                          basic::R::integer::number1, state);
 }
-BENCHMARK_CAPTURE(BM_AssetManagerGetResourceOld, number1, basic::R::integer::number1);
-BENCHMARK_CAPTURE(BM_AssetManagerGetResourceOld, deep_ref, basic::R::integer::deep_ref);
+BENCHMARK(BM_AssetManagerGetResourceOld);
 
 static void BM_AssetManagerGetLibraryResource(benchmark::State& state) {
   GetResourceBenchmark(
@@ -197,7 +196,7 @@
 static void BM_AssetManagerGetResourceLocalesOld(benchmark::State& state) {
   AssetManager assets;
   if (!assets.addAssetPath(String8(kFrameworkPath), nullptr /*cookie*/, false /*appAsLib*/,
-                           true /*isSystemAssets*/)) {
+                           false /*isSystemAssets*/)) {
     state.SkipWithError("Failed to load assets");
     return;
   }
@@ -212,44 +211,4 @@
 }
 BENCHMARK(BM_AssetManagerGetResourceLocalesOld);
 
-static void BM_AssetManagerSetConfigurationFramework(benchmark::State& state) {
-  std::unique_ptr<const ApkAssets> apk = ApkAssets::Load(kFrameworkPath);
-  if (apk == nullptr) {
-    state.SkipWithError("Failed to load assets");
-    return;
-  }
-
-  AssetManager2 assets;
-  assets.SetApkAssets({apk.get()});
-
-  ResTable_config config;
-  memset(&config, 0, sizeof(config));
-
-  while (state.KeepRunning()) {
-    config.sdkVersion = ~config.sdkVersion;
-    assets.SetConfiguration(config);
-  }
-}
-BENCHMARK(BM_AssetManagerSetConfigurationFramework);
-
-static void BM_AssetManagerSetConfigurationFrameworkOld(benchmark::State& state) {
-  AssetManager assets;
-  if (!assets.addAssetPath(String8(kFrameworkPath), nullptr /*cookie*/, false /*appAsLib*/,
-                           true /*isSystemAssets*/)) {
-    state.SkipWithError("Failed to load assets");
-    return;
-  }
-
-  const ResTable& table = assets.getResources(true);
-
-  ResTable_config config;
-  memset(&config, 0, sizeof(config));
-
-  while (state.KeepRunning()) {
-    config.sdkVersion = ~config.sdkVersion;
-    assets.setConfiguration(config);
-  }
-}
-BENCHMARK(BM_AssetManagerSetConfigurationFrameworkOld);
-
 }  // namespace android
diff --git a/libs/androidfw/tests/AssetManager2_test.cpp b/libs/androidfw/tests/AssetManager2_test.cpp
index 7cac2b3..92462a6 100644
--- a/libs/androidfw/tests/AssetManager2_test.cpp
+++ b/libs/androidfw/tests/AssetManager2_test.cpp
@@ -36,10 +36,6 @@
 namespace lib_two = com::android::lib_two;
 namespace libclient = com::android::libclient;
 
-using ::testing::Eq;
-using ::testing::NotNull;
-using ::testing::StrEq;
-
 namespace android {
 
 class AssetManager2Test : public ::testing::Test {
@@ -63,14 +59,11 @@
     libclient_assets_ = ApkAssets::Load(GetTestDataPath() + "/libclient/libclient.apk");
     ASSERT_NE(nullptr, libclient_assets_);
 
-    appaslib_assets_ = ApkAssets::LoadAsSharedLibrary(GetTestDataPath() + "/appaslib/appaslib.apk");
+    appaslib_assets_ = ApkAssets::Load(GetTestDataPath() + "/appaslib/appaslib.apk");
     ASSERT_NE(nullptr, appaslib_assets_);
 
     system_assets_ = ApkAssets::Load(GetTestDataPath() + "/system/system.apk", true /*system*/);
     ASSERT_NE(nullptr, system_assets_);
-
-    app_assets_ = ApkAssets::Load(GetTestDataPath() + "/app/app.apk");
-    ASSERT_THAT(app_assets_, NotNull());
   }
 
  protected:
@@ -82,7 +75,6 @@
   std::unique_ptr<const ApkAssets> libclient_assets_;
   std::unique_ptr<const ApkAssets> appaslib_assets_;
   std::unique_ptr<const ApkAssets> system_assets_;
-  std::unique_ptr<const ApkAssets> app_assets_;
 };
 
 TEST_F(AssetManager2Test, FindsResourceFromSingleApkAssets) {
@@ -241,25 +233,6 @@
   assetmanager.SetApkAssets(
       {lib_two_assets_.get(), lib_one_assets_.get(), libclient_assets_.get()});
 
-  const ResolvedBag* bag = assetmanager.GetBag(fix_package_id(lib_one::R::style::Theme, 0x03));
-  ASSERT_NE(nullptr, bag);
-  ASSERT_GE(bag->entry_count, 2u);
-
-  // First two attributes come from lib_one.
-  EXPECT_EQ(1, bag->entries[0].cookie);
-  EXPECT_EQ(0x03, get_package_id(bag->entries[0].key));
-  EXPECT_EQ(1, bag->entries[1].cookie);
-  EXPECT_EQ(0x03, get_package_id(bag->entries[1].key));
-}
-
-TEST_F(AssetManager2Test, FindsStyleResourceWithParentFromSharedLibrary) {
-  AssetManager2 assetmanager;
-
-  // libclient is built with lib_one and then lib_two in order.
-  // Reverse the order to test that proper package ID re-assignment is happening.
-  assetmanager.SetApkAssets(
-      {lib_two_assets_.get(), lib_one_assets_.get(), libclient_assets_.get()});
-
   const ResolvedBag* bag = assetmanager.GetBag(libclient::R::style::Theme);
   ASSERT_NE(nullptr, bag);
   ASSERT_GE(bag->entry_count, 2u);
@@ -473,68 +446,8 @@
             assetmanager.GetResourceId("main", "layout", "com.android.basic"));
 }
 
-TEST_F(AssetManager2Test, OpensFileFromSingleApkAssets) {
-  AssetManager2 assetmanager;
-  assetmanager.SetApkAssets({system_assets_.get()});
+TEST_F(AssetManager2Test, OpensFileFromSingleApkAssets) {}
 
-  std::unique_ptr<Asset> asset = assetmanager.Open("file.txt", Asset::ACCESS_BUFFER);
-  ASSERT_THAT(asset, NotNull());
-
-  const char* data = reinterpret_cast<const char*>(asset->getBuffer(false /*wordAligned*/));
-  ASSERT_THAT(data, NotNull());
-  EXPECT_THAT(std::string(data, asset->getLength()), StrEq("file\n"));
-}
-
-TEST_F(AssetManager2Test, OpensFileFromMultipleApkAssets) {
-  AssetManager2 assetmanager;
-  assetmanager.SetApkAssets({system_assets_.get(), app_assets_.get()});
-
-  std::unique_ptr<Asset> asset = assetmanager.Open("file.txt", Asset::ACCESS_BUFFER);
-  ASSERT_THAT(asset, NotNull());
-
-  const char* data = reinterpret_cast<const char*>(asset->getBuffer(false /*wordAligned*/));
-  ASSERT_THAT(data, NotNull());
-  EXPECT_THAT(std::string(data, asset->getLength()), StrEq("app override file\n"));
-}
-
-TEST_F(AssetManager2Test, OpenDir) {
-  AssetManager2 assetmanager;
-  assetmanager.SetApkAssets({system_assets_.get()});
-
-  std::unique_ptr<AssetDir> asset_dir = assetmanager.OpenDir("");
-  ASSERT_THAT(asset_dir, NotNull());
-  ASSERT_THAT(asset_dir->getFileCount(), Eq(2u));
-
-  EXPECT_THAT(asset_dir->getFileName(0), Eq(String8("file.txt")));
-  EXPECT_THAT(asset_dir->getFileType(0), Eq(FileType::kFileTypeRegular));
-
-  EXPECT_THAT(asset_dir->getFileName(1), Eq(String8("subdir")));
-  EXPECT_THAT(asset_dir->getFileType(1), Eq(FileType::kFileTypeDirectory));
-
-  asset_dir = assetmanager.OpenDir("subdir");
-  ASSERT_THAT(asset_dir, NotNull());
-  ASSERT_THAT(asset_dir->getFileCount(), Eq(1u));
-
-  EXPECT_THAT(asset_dir->getFileName(0), Eq(String8("subdir_file.txt")));
-  EXPECT_THAT(asset_dir->getFileType(0), Eq(FileType::kFileTypeRegular));
-}
-
-TEST_F(AssetManager2Test, OpenDirFromManyApks) {
-  AssetManager2 assetmanager;
-  assetmanager.SetApkAssets({system_assets_.get(), app_assets_.get()});
-
-  std::unique_ptr<AssetDir> asset_dir = assetmanager.OpenDir("");
-  ASSERT_THAT(asset_dir, NotNull());
-  ASSERT_THAT(asset_dir->getFileCount(), Eq(3u));
-
-  EXPECT_THAT(asset_dir->getFileName(0), Eq(String8("app_file.txt")));
-  EXPECT_THAT(asset_dir->getFileType(0), Eq(FileType::kFileTypeRegular));
-
-  EXPECT_THAT(asset_dir->getFileName(1), Eq(String8("file.txt")));
-  EXPECT_THAT(asset_dir->getFileType(1), Eq(FileType::kFileTypeRegular));
-
-  EXPECT_THAT(asset_dir->getFileName(2), Eq(String8("subdir")));
-  EXPECT_THAT(asset_dir->getFileType(2), Eq(FileType::kFileTypeDirectory));
-}
+TEST_F(AssetManager2Test, OpensFileFromMultipleApkAssets) {}
 
 }  // namespace android
diff --git a/libs/androidfw/tests/AttributeResolution_bench.cpp b/libs/androidfw/tests/AttributeResolution_bench.cpp
deleted file mode 100644
index fa300c5..0000000
--- a/libs/androidfw/tests/AttributeResolution_bench.cpp
+++ /dev/null
@@ -1,175 +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 "benchmark/benchmark.h"
-
-//#include "android-base/stringprintf.h"
-#include "androidfw/ApkAssets.h"
-#include "androidfw/AssetManager.h"
-#include "androidfw/AssetManager2.h"
-#include "androidfw/AttributeResolution.h"
-#include "androidfw/ResourceTypes.h"
-
-#include "BenchmarkHelpers.h"
-#include "data/basic/R.h"
-#include "data/styles/R.h"
-
-namespace app = com::android::app;
-namespace basic = com::android::basic;
-
-namespace android {
-
-constexpr const static char* kFrameworkPath = "/system/framework/framework-res.apk";
-constexpr const static uint32_t Theme_Material_Light = 0x01030237u;
-
-static void BM_ApplyStyle(benchmark::State& state) {
-  std::unique_ptr<const ApkAssets> styles_apk =
-      ApkAssets::Load(GetTestDataPath() + "/styles/styles.apk");
-  if (styles_apk == nullptr) {
-    state.SkipWithError("failed to load assets");
-    return;
-  }
-
-  AssetManager2 assetmanager;
-  assetmanager.SetApkAssets({styles_apk.get()});
-
-  std::unique_ptr<Asset> asset =
-      assetmanager.OpenNonAsset("res/layout/layout.xml", Asset::ACCESS_BUFFER);
-  if (asset == nullptr) {
-    state.SkipWithError("failed to load layout");
-    return;
-  }
-
-  ResXMLTree xml_tree;
-  if (xml_tree.setTo(asset->getBuffer(true), asset->getLength(), false /*copyData*/) != NO_ERROR) {
-    state.SkipWithError("corrupt xml layout");
-    return;
-  }
-
-  // Skip to the first tag.
-  while (xml_tree.next() != ResXMLParser::START_TAG) {
-  }
-
-  std::unique_ptr<Theme> theme = assetmanager.NewTheme();
-  theme->ApplyStyle(app::R::style::StyleTwo);
-
-  std::array<uint32_t, 6> attrs{{app::R::attr::attr_one, app::R::attr::attr_two,
-                                 app::R::attr::attr_three, app::R::attr::attr_four,
-                                 app::R::attr::attr_five, app::R::attr::attr_empty}};
-  std::array<uint32_t, attrs.size() * STYLE_NUM_ENTRIES> values;
-  std::array<uint32_t, attrs.size() + 1> indices;
-
-  while (state.KeepRunning()) {
-    ApplyStyle(theme.get(), &xml_tree, 0u /*def_style_attr*/, 0u /*def_style_res*/, attrs.data(),
-               attrs.size(), values.data(), indices.data());
-  }
-}
-BENCHMARK(BM_ApplyStyle);
-
-static void BM_ApplyStyleFramework(benchmark::State& state) {
-  std::unique_ptr<const ApkAssets> framework_apk = ApkAssets::Load(kFrameworkPath);
-  if (framework_apk == nullptr) {
-    state.SkipWithError("failed to load framework assets");
-    return;
-  }
-
-  std::unique_ptr<const ApkAssets> basic_apk =
-      ApkAssets::Load(GetTestDataPath() + "/basic/basic.apk");
-  if (basic_apk == nullptr) {
-    state.SkipWithError("failed to load assets");
-    return;
-  }
-
-  AssetManager2 assetmanager;
-  assetmanager.SetApkAssets({framework_apk.get(), basic_apk.get()});
-
-  ResTable_config device_config;
-  memset(&device_config, 0, sizeof(device_config));
-  device_config.language[0] = 'e';
-  device_config.language[1] = 'n';
-  device_config.country[0] = 'U';
-  device_config.country[1] = 'S';
-  device_config.orientation = ResTable_config::ORIENTATION_PORT;
-  device_config.smallestScreenWidthDp = 700;
-  device_config.screenWidthDp = 700;
-  device_config.screenHeightDp = 1024;
-  device_config.sdkVersion = 27;
-
-  Res_value value;
-  ResTable_config config;
-  uint32_t flags = 0u;
-  ApkAssetsCookie cookie =
-      assetmanager.GetResource(basic::R::layout::layoutt, false /*may_be_bag*/,
-                               0u /*density_override*/, &value, &config, &flags);
-  if (cookie == kInvalidCookie) {
-    state.SkipWithError("failed to find R.layout.layout");
-    return;
-  }
-
-  size_t len = 0u;
-  const char* layout_path =
-      assetmanager.GetStringPoolForCookie(cookie)->string8At(value.data, &len);
-  if (layout_path == nullptr || len == 0u) {
-    state.SkipWithError("failed to lookup layout path");
-    return;
-  }
-
-  std::unique_ptr<Asset> asset = assetmanager.OpenNonAsset(
-      StringPiece(layout_path, len).to_string(), cookie, Asset::ACCESS_BUFFER);
-  if (asset == nullptr) {
-    state.SkipWithError("failed to load layout");
-    return;
-  }
-
-  ResXMLTree xml_tree;
-  if (xml_tree.setTo(asset->getBuffer(true), asset->getLength(), false /*copyData*/) != NO_ERROR) {
-    state.SkipWithError("corrupt xml layout");
-    return;
-  }
-
-  // Skip to the first tag.
-  while (xml_tree.next() != ResXMLParser::START_TAG) {
-  }
-
-  std::unique_ptr<Theme> theme = assetmanager.NewTheme();
-  theme->ApplyStyle(Theme_Material_Light);
-
-  std::array<uint32_t, 92> attrs{
-      {0x0101000e, 0x01010034, 0x01010095, 0x01010096, 0x01010097, 0x01010098, 0x01010099,
-       0x0101009a, 0x0101009b, 0x010100ab, 0x010100af, 0x010100b0, 0x010100b1, 0x0101011f,
-       0x01010120, 0x0101013f, 0x01010140, 0x0101014e, 0x0101014f, 0x01010150, 0x01010151,
-       0x01010152, 0x01010153, 0x01010154, 0x01010155, 0x01010156, 0x01010157, 0x01010158,
-       0x01010159, 0x0101015a, 0x0101015b, 0x0101015c, 0x0101015d, 0x0101015e, 0x0101015f,
-       0x01010160, 0x01010161, 0x01010162, 0x01010163, 0x01010164, 0x01010165, 0x01010166,
-       0x01010167, 0x01010168, 0x01010169, 0x0101016a, 0x0101016b, 0x0101016c, 0x0101016d,
-       0x0101016e, 0x0101016f, 0x01010170, 0x01010171, 0x01010217, 0x01010218, 0x0101021d,
-       0x01010220, 0x01010223, 0x01010224, 0x01010264, 0x01010265, 0x01010266, 0x010102c5,
-       0x010102c6, 0x010102c7, 0x01010314, 0x01010315, 0x01010316, 0x0101035e, 0x0101035f,
-       0x01010362, 0x01010374, 0x0101038c, 0x01010392, 0x01010393, 0x010103ac, 0x0101045d,
-       0x010104b6, 0x010104b7, 0x010104d6, 0x010104d7, 0x010104dd, 0x010104de, 0x010104df,
-       0x01010535, 0x01010536, 0x01010537, 0x01010538, 0x01010546, 0x01010567, 0x011100c9,
-       0x011100ca}};
-
-  std::array<uint32_t, attrs.size() * STYLE_NUM_ENTRIES> values;
-  std::array<uint32_t, attrs.size() + 1> indices;
-  while (state.KeepRunning()) {
-    ApplyStyle(theme.get(), &xml_tree, 0x01010084u /*def_style_attr*/, 0u /*def_style_res*/,
-               attrs.data(), attrs.size(), values.data(), indices.data());
-  }
-}
-BENCHMARK(BM_ApplyStyleFramework);
-
-}  // namespace android
diff --git a/libs/androidfw/tests/AttributeResolution_test.cpp b/libs/androidfw/tests/AttributeResolution_test.cpp
index c8dbe20..2d73ce8 100644
--- a/libs/androidfw/tests/AttributeResolution_test.cpp
+++ b/libs/androidfw/tests/AttributeResolution_test.cpp
@@ -21,8 +21,6 @@
 #include "android-base/file.h"
 #include "android-base/logging.h"
 #include "android-base/macros.h"
-#include "androidfw/AssetManager2.h"
-#include "androidfw/ResourceUtils.h"
 
 #include "TestHelpers.h"
 #include "data/styles/R.h"
@@ -34,14 +32,15 @@
 class AttributeResolutionTest : public ::testing::Test {
  public:
   virtual void SetUp() override {
-    styles_assets_ = ApkAssets::Load(GetTestDataPath() + "/styles/styles.apk");
-    ASSERT_NE(nullptr, styles_assets_);
-    assetmanager_.SetApkAssets({styles_assets_.get()});
+    std::string contents;
+    ASSERT_TRUE(ReadFileFromZipToString(
+        GetTestDataPath() + "/styles/styles.apk", "resources.arsc", &contents));
+    ASSERT_EQ(NO_ERROR, table_.add(contents.data(), contents.size(),
+                                   1 /*cookie*/, true /*copyData*/));
   }
 
  protected:
-  std::unique_ptr<const ApkAssets> styles_assets_;
-  AssetManager2 assetmanager_;
+  ResTable table_;
 };
 
 class AttributeResolutionXmlTest : public AttributeResolutionTest {
@@ -49,12 +48,13 @@
   virtual void SetUp() override {
     AttributeResolutionTest::SetUp();
 
-    std::unique_ptr<Asset> asset =
-        assetmanager_.OpenNonAsset("res/layout/layout.xml", Asset::ACCESS_BUFFER);
-    ASSERT_NE(nullptr, asset);
+    std::string contents;
+    ASSERT_TRUE(
+        ReadFileFromZipToString(GetTestDataPath() + "/styles/styles.apk",
+                                "res/layout/layout.xml", &contents));
 
-    ASSERT_EQ(NO_ERROR,
-              xml_parser_.setTo(asset->getBuffer(true), asset->getLength(), true /*copyData*/));
+    ASSERT_EQ(NO_ERROR, xml_parser_.setTo(contents.data(), contents.size(),
+                                          true /*copyData*/));
 
     // Skip to the first tag.
     while (xml_parser_.next() != ResXMLParser::START_TAG) {
@@ -65,50 +65,15 @@
   ResXMLTree xml_parser_;
 };
 
-TEST(AttributeResolutionLibraryTest, ApplyStyleWithDefaultStyleResId) {
-  AssetManager2 assetmanager;
-  auto apk_assets = ApkAssets::LoadAsSharedLibrary(GetTestDataPath() + "/styles/styles.apk");
-  ASSERT_NE(nullptr, apk_assets);
-  assetmanager.SetApkAssets({apk_assets.get()});
-
-  std::unique_ptr<Theme> theme = assetmanager.NewTheme();
-
-  std::array<uint32_t, 2> attrs{
-      {fix_package_id(R::attr::attr_one, 0x02), fix_package_id(R::attr::attr_two, 0x02)}};
-  std::array<uint32_t, attrs.size() * STYLE_NUM_ENTRIES> values;
-  std::array<uint32_t, attrs.size() + 1> indices;
-  ApplyStyle(theme.get(), nullptr /*xml_parser*/, 0u /*def_style_attr*/,
-             fix_package_id(R::style::StyleOne, 0x02), attrs.data(), attrs.size(), values.data(),
-             indices.data());
-
-  const uint32_t public_flag = ResTable_typeSpec::SPEC_PUBLIC;
-
-  const uint32_t* values_cursor = values.data();
-  EXPECT_EQ(Res_value::TYPE_INT_DEC, values_cursor[STYLE_TYPE]);
-  EXPECT_EQ(1u, values_cursor[STYLE_DATA]);
-  EXPECT_EQ(0u, values_cursor[STYLE_RESOURCE_ID]);
-  EXPECT_EQ(1u, values_cursor[STYLE_ASSET_COOKIE]);
-  EXPECT_EQ(0u, values_cursor[STYLE_DENSITY]);
-  EXPECT_EQ(public_flag, values_cursor[STYLE_CHANGING_CONFIGURATIONS]);
-
-  values_cursor += STYLE_NUM_ENTRIES;
-  EXPECT_EQ(Res_value::TYPE_INT_DEC, values_cursor[STYLE_TYPE]);
-  EXPECT_EQ(2u, values_cursor[STYLE_DATA]);
-  EXPECT_EQ(0u, values_cursor[STYLE_RESOURCE_ID]);
-  EXPECT_EQ(1u, values_cursor[STYLE_ASSET_COOKIE]);
-  EXPECT_EQ(0u, values_cursor[STYLE_DENSITY]);
-  EXPECT_EQ(public_flag, values_cursor[STYLE_CHANGING_CONFIGURATIONS]);
-}
-
 TEST_F(AttributeResolutionTest, Theme) {
-  std::unique_ptr<Theme> theme = assetmanager_.NewTheme();
-  ASSERT_TRUE(theme->ApplyStyle(R::style::StyleTwo));
+  ResTable::Theme theme(table_);
+  ASSERT_EQ(NO_ERROR, theme.applyStyle(R::style::StyleTwo));
 
   std::array<uint32_t, 5> attrs{{R::attr::attr_one, R::attr::attr_two, R::attr::attr_three,
                                  R::attr::attr_four, R::attr::attr_empty}};
   std::array<uint32_t, attrs.size() * STYLE_NUM_ENTRIES> values;
 
-  ASSERT_TRUE(ResolveAttrs(theme.get(), 0u /*def_style_attr*/, 0u /*def_style_res*/,
+  ASSERT_TRUE(ResolveAttrs(&theme, 0 /*def_style_attr*/, 0 /*def_style_res*/,
                            nullptr /*src_values*/, 0 /*src_values_length*/, attrs.data(),
                            attrs.size(), values.data(), nullptr /*out_indices*/));
 
@@ -161,8 +126,8 @@
                                  R::attr::attr_four, R::attr::attr_empty}};
   std::array<uint32_t, attrs.size() * STYLE_NUM_ENTRIES> values;
 
-  ASSERT_TRUE(RetrieveAttributes(&assetmanager_, &xml_parser_, attrs.data(), attrs.size(),
-                                 values.data(), nullptr /*out_indices*/));
+  ASSERT_TRUE(RetrieveAttributes(&table_, &xml_parser_, attrs.data(), attrs.size(), values.data(),
+                                 nullptr /*out_indices*/));
 
   uint32_t* values_cursor = values.data();
   EXPECT_EQ(Res_value::TYPE_NULL, values_cursor[STYLE_TYPE]);
@@ -206,15 +171,15 @@
 }
 
 TEST_F(AttributeResolutionXmlTest, ThemeAndXmlParser) {
-  std::unique_ptr<Theme> theme = assetmanager_.NewTheme();
-  ASSERT_TRUE(theme->ApplyStyle(R::style::StyleTwo));
+  ResTable::Theme theme(table_);
+  ASSERT_EQ(NO_ERROR, theme.applyStyle(R::style::StyleTwo));
 
   std::array<uint32_t, 6> attrs{{R::attr::attr_one, R::attr::attr_two, R::attr::attr_three,
                                  R::attr::attr_four, R::attr::attr_five, R::attr::attr_empty}};
   std::array<uint32_t, attrs.size() * STYLE_NUM_ENTRIES> values;
   std::array<uint32_t, attrs.size() + 1> indices;
 
-  ApplyStyle(theme.get(), &xml_parser_, 0u /*def_style_attr*/, 0u /*def_style_res*/, attrs.data(),
+  ApplyStyle(&theme, &xml_parser_, 0 /*def_style_attr*/, 0 /*def_style_res*/, attrs.data(),
              attrs.size(), values.data(), indices.data());
 
   const uint32_t public_flag = ResTable_typeSpec::SPEC_PUBLIC;
diff --git a/libs/androidfw/tests/BenchmarkHelpers.cpp b/libs/androidfw/tests/BenchmarkHelpers.cpp
index faddfe5..7149bee 100644
--- a/libs/androidfw/tests/BenchmarkHelpers.cpp
+++ b/libs/androidfw/tests/BenchmarkHelpers.cpp
@@ -33,21 +33,19 @@
     }
   }
 
-  // Make sure to force creation of the ResTable first, or else the configuration doesn't get set.
-  const ResTable& table = assetmanager.getResources(true);
   if (config != nullptr) {
     assetmanager.setConfiguration(*config);
   }
 
+  const ResTable& table = assetmanager.getResources(true);
+
   Res_value value;
   ResTable_config selected_config;
   uint32_t flags;
-  uint32_t last_ref = 0u;
 
   while (state.KeepRunning()) {
-    ssize_t block = table.getResource(resid, &value, false /*may_be_bag*/, 0u /*density*/, &flags,
-                                      &selected_config);
-    table.resolveReference(&value, block, &last_ref, &flags, &selected_config);
+    table.getResource(resid, &value, false /*may_be_bag*/, 0u /*density*/, &flags,
+                      &selected_config);
   }
 }
 
@@ -74,12 +72,10 @@
   Res_value value;
   ResTable_config selected_config;
   uint32_t flags;
-  uint32_t last_id = 0u;
 
   while (state.KeepRunning()) {
-    ApkAssetsCookie cookie = assetmanager.GetResource(
-        resid, false /* may_be_bag */, 0u /* density_override */, &value, &selected_config, &flags);
-    assetmanager.ResolveReference(cookie, &value, &selected_config, &flags, &last_id);
+    assetmanager.GetResource(resid, false /* may_be_bag */, 0u /* density_override */, &value,
+                             &selected_config, &flags);
   }
 }
 
diff --git a/libs/androidfw/tests/LoadedArsc_test.cpp b/libs/androidfw/tests/LoadedArsc_test.cpp
index cae632d..37ddafb 100644
--- a/libs/androidfw/tests/LoadedArsc_test.cpp
+++ b/libs/androidfw/tests/LoadedArsc_test.cpp
@@ -16,9 +16,6 @@
 
 #include "androidfw/LoadedArsc.h"
 
-#include "android-base/file.h"
-#include "androidfw/ResourceUtils.h"
-
 #include "TestHelpers.h"
 #include "data/basic/R.h"
 #include "data/libclient/R.h"
@@ -30,14 +27,6 @@
 namespace libclient = com::android::libclient;
 namespace sparse = com::android::sparse;
 
-using ::android::base::ReadFileToString;
-using ::testing::Eq;
-using ::testing::Ge;
-using ::testing::IsNull;
-using ::testing::NotNull;
-using ::testing::SizeIs;
-using ::testing::StrEq;
-
 namespace android {
 
 TEST(LoadedArscTest, LoadSinglePackageArsc) {
@@ -46,24 +35,39 @@
                                       &contents));
 
   std::unique_ptr<const LoadedArsc> loaded_arsc = LoadedArsc::Load(StringPiece(contents));
-  ASSERT_THAT(loaded_arsc, NotNull());
+  ASSERT_NE(nullptr, loaded_arsc);
 
-  const LoadedPackage* package =
-      loaded_arsc->GetPackageById(get_package_id(app::R::string::string_one));
-  ASSERT_THAT(package, NotNull());
-  EXPECT_THAT(package->GetPackageName(), StrEq("com.android.app"));
-  EXPECT_THAT(package->GetPackageId(), Eq(0x7f));
+  const std::vector<std::unique_ptr<const LoadedPackage>>& packages = loaded_arsc->GetPackages();
+  ASSERT_EQ(1u, packages.size());
+  EXPECT_EQ(std::string("com.android.app"), packages[0]->GetPackageName());
+  EXPECT_EQ(0x7f, packages[0]->GetPackageId());
 
-  const uint8_t type_index = get_type_id(app::R::string::string_one) - 1;
-  const uint16_t entry_index = get_entry_id(app::R::string::string_one);
+  ResTable_config config;
+  memset(&config, 0, sizeof(config));
+  config.sdkVersion = 24;
 
-  const TypeSpec* type_spec = package->GetTypeSpecByTypeIndex(type_index);
-  ASSERT_THAT(type_spec, NotNull());
-  ASSERT_THAT(type_spec->type_count, Ge(1u));
+  FindEntryResult entry;
 
-  const ResTable_type* type = type_spec->types[0];
-  ASSERT_THAT(type, NotNull());
-  ASSERT_THAT(LoadedPackage::GetEntry(type, entry_index), NotNull());
+  ASSERT_TRUE(loaded_arsc->FindEntry(app::R::string::string_one, config, &entry));
+  ASSERT_NE(nullptr, entry.entry);
+}
+
+TEST(LoadedArscTest, FindDefaultEntry) {
+  std::string contents;
+  ASSERT_TRUE(
+      ReadFileFromZipToString(GetTestDataPath() + "/basic/basic.apk", "resources.arsc", &contents));
+
+  std::unique_ptr<const LoadedArsc> loaded_arsc = LoadedArsc::Load(StringPiece(contents));
+  ASSERT_NE(nullptr, loaded_arsc);
+
+  ResTable_config desired_config;
+  memset(&desired_config, 0, sizeof(desired_config));
+  desired_config.language[0] = 'd';
+  desired_config.language[1] = 'e';
+
+  FindEntryResult entry;
+  ASSERT_TRUE(loaded_arsc->FindEntry(basic::R::string::test1, desired_config, &entry));
+  ASSERT_NE(nullptr, entry.entry);
 }
 
 TEST(LoadedArscTest, LoadSparseEntryApp) {
@@ -72,22 +76,15 @@
                                       &contents));
 
   std::unique_ptr<const LoadedArsc> loaded_arsc = LoadedArsc::Load(StringPiece(contents));
-  ASSERT_THAT(loaded_arsc, NotNull());
+  ASSERT_NE(nullptr, loaded_arsc);
 
-  const LoadedPackage* package =
-      loaded_arsc->GetPackageById(get_package_id(sparse::R::integer::foo_9));
-  ASSERT_THAT(package, NotNull());
+  ResTable_config config;
+  memset(&config, 0, sizeof(config));
+  config.sdkVersion = 26;
 
-  const uint8_t type_index = get_type_id(sparse::R::integer::foo_9) - 1;
-  const uint16_t entry_index = get_entry_id(sparse::R::integer::foo_9);
-
-  const TypeSpec* type_spec = package->GetTypeSpecByTypeIndex(type_index);
-  ASSERT_THAT(type_spec, NotNull());
-  ASSERT_THAT(type_spec->type_count, Ge(1u));
-
-  const ResTable_type* type = type_spec->types[0];
-  ASSERT_THAT(type, NotNull());
-  ASSERT_THAT(LoadedPackage::GetEntry(type, entry_index), NotNull());
+  FindEntryResult entry;
+  ASSERT_TRUE(loaded_arsc->FindEntry(sparse::R::integer::foo_9, config, &entry));
+  ASSERT_NE(nullptr, entry.entry);
 }
 
 TEST(LoadedArscTest, LoadSharedLibrary) {
@@ -96,13 +93,14 @@
                                       &contents));
 
   std::unique_ptr<const LoadedArsc> loaded_arsc = LoadedArsc::Load(StringPiece(contents));
-  ASSERT_THAT(loaded_arsc, NotNull());
+  ASSERT_NE(nullptr, loaded_arsc);
 
   const auto& packages = loaded_arsc->GetPackages();
-  ASSERT_THAT(packages, SizeIs(1u));
+  ASSERT_EQ(1u, packages.size());
+
   EXPECT_TRUE(packages[0]->IsDynamic());
-  EXPECT_THAT(packages[0]->GetPackageName(), StrEq("com.android.lib_one"));
-  EXPECT_THAT(packages[0]->GetPackageId(), Eq(0));
+  EXPECT_EQ(std::string("com.android.lib_one"), packages[0]->GetPackageName());
+  EXPECT_EQ(0, packages[0]->GetPackageId());
 
   const auto& dynamic_pkg_map = packages[0]->GetDynamicPackageMap();
 
@@ -116,23 +114,25 @@
                                       "resources.arsc", &contents));
 
   std::unique_ptr<const LoadedArsc> loaded_arsc = LoadedArsc::Load(StringPiece(contents));
-  ASSERT_THAT(loaded_arsc, NotNull());
+  ASSERT_NE(nullptr, loaded_arsc);
 
   const auto& packages = loaded_arsc->GetPackages();
-  ASSERT_THAT(packages, SizeIs(1u));
+  ASSERT_EQ(1u, packages.size());
+
   EXPECT_FALSE(packages[0]->IsDynamic());
-  EXPECT_THAT(packages[0]->GetPackageName(), StrEq("com.android.libclient"));
-  EXPECT_THAT(packages[0]->GetPackageId(), Eq(0x7f));
+  EXPECT_EQ(std::string("com.android.libclient"), packages[0]->GetPackageName());
+  EXPECT_EQ(0x7f, packages[0]->GetPackageId());
 
   const auto& dynamic_pkg_map = packages[0]->GetDynamicPackageMap();
 
   // The library has two dependencies.
-  ASSERT_THAT(dynamic_pkg_map, SizeIs(2u));
-  EXPECT_THAT(dynamic_pkg_map[0].package_name, StrEq("com.android.lib_one"));
-  EXPECT_THAT(dynamic_pkg_map[0].package_id, Eq(0x02));
+  ASSERT_EQ(2u, dynamic_pkg_map.size());
 
-  EXPECT_THAT(dynamic_pkg_map[1].package_name, StrEq("com.android.lib_two"));
-  EXPECT_THAT(dynamic_pkg_map[1].package_id, Eq(0x03));
+  EXPECT_EQ(std::string("com.android.lib_one"), dynamic_pkg_map[0].package_name);
+  EXPECT_EQ(0x02, dynamic_pkg_map[0].package_id);
+
+  EXPECT_EQ(std::string("com.android.lib_two"), dynamic_pkg_map[1].package_name);
+  EXPECT_EQ(0x03, dynamic_pkg_map[1].package_id);
 }
 
 TEST(LoadedArscTest, LoadAppAsSharedLibrary) {
@@ -143,12 +143,13 @@
   std::unique_ptr<const LoadedArsc> loaded_arsc =
       LoadedArsc::Load(StringPiece(contents), nullptr /*loaded_idmap*/, false /*system*/,
                        true /*load_as_shared_library*/);
-  ASSERT_THAT(loaded_arsc, NotNull());
+  ASSERT_NE(nullptr, loaded_arsc);
 
   const auto& packages = loaded_arsc->GetPackages();
-  ASSERT_THAT(packages, SizeIs(1u));
+  ASSERT_EQ(1u, packages.size());
+
   EXPECT_TRUE(packages[0]->IsDynamic());
-  EXPECT_THAT(packages[0]->GetPackageId(), Eq(0x7f));
+  EXPECT_EQ(0x7f, packages[0]->GetPackageId());
 }
 
 TEST(LoadedArscTest, LoadFeatureSplit) {
@@ -156,67 +157,21 @@
   ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/feature/feature.apk", "resources.arsc",
                                       &contents));
   std::unique_ptr<const LoadedArsc> loaded_arsc = LoadedArsc::Load(StringPiece(contents));
-  ASSERT_THAT(loaded_arsc, NotNull());
+  ASSERT_NE(nullptr, loaded_arsc);
 
-  const LoadedPackage* package =
-      loaded_arsc->GetPackageById(get_package_id(basic::R::string::test3));
-  ASSERT_THAT(package, NotNull());
+  ResTable_config desired_config;
+  memset(&desired_config, 0, sizeof(desired_config));
 
-  uint8_t type_index = get_type_id(basic::R::string::test3) - 1;
-  uint8_t entry_index = get_entry_id(basic::R::string::test3);
-
-  const TypeSpec* type_spec = package->GetTypeSpecByTypeIndex(type_index);
-  ASSERT_THAT(type_spec, NotNull());
-  ASSERT_THAT(type_spec->type_count, Ge(1u));
-  ASSERT_THAT(type_spec->types[0], NotNull());
+  FindEntryResult entry;
+  ASSERT_TRUE(loaded_arsc->FindEntry(basic::R::string::test3, desired_config, &entry));
 
   size_t len;
-  const char16_t* type_name16 =
-      package->GetTypeStringPool()->stringAt(type_spec->type_spec->id - 1, &len);
-  ASSERT_THAT(type_name16, NotNull());
-  EXPECT_THAT(util::Utf16ToUtf8(StringPiece16(type_name16, len)), StrEq("string"));
+  const char16_t* type_name16 = entry.type_string_ref.string16(&len);
+  ASSERT_NE(nullptr, type_name16);
+  ASSERT_NE(0u, len);
 
-  ASSERT_THAT(LoadedPackage::GetEntry(type_spec->types[0], entry_index), NotNull());
-}
-
-// AAPT(2) generates resource tables with chunks in a certain order. The rule is that
-// a RES_TABLE_TYPE_TYPE with id `i` must always be preceded by a RES_TABLE_TYPE_SPEC_TYPE with
-// id `i`. The RES_TABLE_TYPE_SPEC_TYPE does not need to be directly preceding, however.
-//
-// AAPT(2) generates something like:
-//   RES_TABLE_TYPE_SPEC_TYPE id=1
-//   RES_TABLE_TYPE_TYPE id=1
-//   RES_TABLE_TYPE_SPEC_TYPE id=2
-//   RES_TABLE_TYPE_TYPE id=2
-//
-// But the following is valid too:
-//   RES_TABLE_TYPE_SPEC_TYPE id=1
-//   RES_TABLE_TYPE_SPEC_TYPE id=2
-//   RES_TABLE_TYPE_TYPE id=1
-//   RES_TABLE_TYPE_TYPE id=2
-//
-TEST(LoadedArscTest, LoadOutOfOrderTypeSpecs) {
-  std::string contents;
-  ASSERT_TRUE(
-      ReadFileFromZipToString(GetTestDataPath() + "/out_of_order_types/out_of_order_types.apk",
-                              "resources.arsc", &contents));
-
-  std::unique_ptr<const LoadedArsc> loaded_arsc = LoadedArsc::Load(StringPiece(contents));
-  ASSERT_THAT(loaded_arsc, NotNull());
-
-  ASSERT_THAT(loaded_arsc->GetPackages(), SizeIs(1u));
-  const auto& package = loaded_arsc->GetPackages()[0];
-  ASSERT_THAT(package, NotNull());
-
-  const TypeSpec* type_spec = package->GetTypeSpecByTypeIndex(0);
-  ASSERT_THAT(type_spec, NotNull());
-  ASSERT_THAT(type_spec->type_count, Ge(1u));
-  ASSERT_THAT(type_spec->types[0], NotNull());
-
-  type_spec = package->GetTypeSpecByTypeIndex(1);
-  ASSERT_THAT(type_spec, NotNull());
-  ASSERT_THAT(type_spec->type_count, Ge(1u));
-  ASSERT_THAT(type_spec->types[0], NotNull());
+  std::string type_name = util::Utf16ToUtf8(StringPiece16(type_name16, len));
+  EXPECT_EQ(std::string("string"), type_name);
 }
 
 class MockLoadedIdmap : public LoadedIdmap {
@@ -244,33 +199,23 @@
 };
 
 TEST(LoadedArscTest, LoadOverlay) {
-  std::string contents;
+  std::string contents, overlay_contents;
+  ASSERT_TRUE(
+      ReadFileFromZipToString(GetTestDataPath() + "/basic/basic.apk", "resources.arsc", &contents));
   ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/overlay/overlay.apk", "resources.arsc",
-                                      &contents));
+                                      &overlay_contents));
 
   MockLoadedIdmap loaded_idmap;
 
   std::unique_ptr<const LoadedArsc> loaded_arsc =
-      LoadedArsc::Load(StringPiece(contents), &loaded_idmap);
-  ASSERT_THAT(loaded_arsc, NotNull());
+      LoadedArsc::Load(StringPiece(overlay_contents), &loaded_idmap);
+  ASSERT_NE(nullptr, loaded_arsc);
 
-  const LoadedPackage* package = loaded_arsc->GetPackageById(0x08u);
-  ASSERT_THAT(package, NotNull());
+  ResTable_config desired_config;
+  memset(&desired_config, 0, sizeof(desired_config));
 
-  const TypeSpec* type_spec = package->GetTypeSpecByTypeIndex(0x03u - 1);
-  ASSERT_THAT(type_spec, NotNull());
-  ASSERT_THAT(type_spec->type_count, Ge(1u));
-  ASSERT_THAT(type_spec->types[0], NotNull());
-
-  // The entry being overlaid doesn't exist at the original entry index.
-  ASSERT_THAT(LoadedPackage::GetEntry(type_spec->types[0], 0x0001u), IsNull());
-
-  // Since this is an overlay, the actual entry ID must be mapped.
-  ASSERT_THAT(type_spec->idmap_entries, NotNull());
-  uint16_t target_entry_id = 0u;
-  ASSERT_TRUE(LoadedIdmap::Lookup(type_spec->idmap_entries, 0x0001u, &target_entry_id));
-  ASSERT_THAT(target_entry_id, Eq(0x0u));
-  ASSERT_THAT(LoadedPackage::GetEntry(type_spec->types[0], 0x0000), NotNull());
+  FindEntryResult entry;
+  ASSERT_TRUE(loaded_arsc->FindEntry(0x08030001u, desired_config, &entry));
 }
 
 // structs with size fields (like Res_value, ResTable_entry) should be
diff --git a/libs/androidfw/tests/TestHelpers.h b/libs/androidfw/tests/TestHelpers.h
index df0c642..43a9955 100644
--- a/libs/androidfw/tests/TestHelpers.h
+++ b/libs/androidfw/tests/TestHelpers.h
@@ -20,7 +20,6 @@
 #include <string>
 
 #include "androidfw/ResourceTypes.h"
-#include "gmock/gmock.h"
 #include "gtest/gtest.h"
 
 #include "CommonHelpers.h"
diff --git a/libs/androidfw/tests/data/app/app.apk b/libs/androidfw/tests/data/app/app.apk
index c8ad86d..ccb0824 100644
--- a/libs/androidfw/tests/data/app/app.apk
+++ b/libs/androidfw/tests/data/app/app.apk
Binary files differ
diff --git a/libs/androidfw/tests/data/app/assets/app_file.txt b/libs/androidfw/tests/data/app/assets/app_file.txt
deleted file mode 100644
index b214e06..0000000
--- a/libs/androidfw/tests/data/app/assets/app_file.txt
+++ /dev/null
@@ -1 +0,0 @@
-app file
diff --git a/libs/androidfw/tests/data/app/assets/file.txt b/libs/androidfw/tests/data/app/assets/file.txt
deleted file mode 100644
index 0811542..0000000
--- a/libs/androidfw/tests/data/app/assets/file.txt
+++ /dev/null
@@ -1 +0,0 @@
-app override file
diff --git a/libs/androidfw/tests/data/app/build b/libs/androidfw/tests/data/app/build
index 09af842..d418158 100755
--- a/libs/androidfw/tests/data/app/build
+++ b/libs/androidfw/tests/data/app/build
@@ -17,11 +17,4 @@
 
 set -e
 
-aapt2 compile --dir res -o compiled.flata
-aapt2 link \
-    --manifest AndroidManifest.xml \
-    -I ../system/system.apk \
-    -A assets \
-    -o app.apk \
-    compiled.flata
-rm compiled.flata
+aapt package -I ../system/system.apk -M AndroidManifest.xml -S res -F app.apk -f
diff --git a/libs/androidfw/tests/data/basic/R.h b/libs/androidfw/tests/data/basic/R.h
index b7e814f..94a2a14 100644
--- a/libs/androidfw/tests/data/basic/R.h
+++ b/libs/androidfw/tests/data/basic/R.h
@@ -34,7 +34,6 @@
   struct layout {
     enum : uint32_t {
       main = 0x7f020000,
-      layoutt = 0x7f020001,
     };
   };
 
@@ -56,7 +55,6 @@
       number2 = 0x7f040001,
       ref1 = 0x7f040002,
       ref2 = 0x7f040003,
-      deep_ref = 0x7f040004,
 
       // From feature
       number3 = 0x80030000,
diff --git a/libs/androidfw/tests/data/basic/basic.apk b/libs/androidfw/tests/data/basic/basic.apk
index 1733b6a..18ef75e 100644
--- a/libs/androidfw/tests/data/basic/basic.apk
+++ b/libs/androidfw/tests/data/basic/basic.apk
Binary files differ
diff --git a/libs/androidfw/tests/data/basic/res/layout/layout.xml b/libs/androidfw/tests/data/basic/res/layout/layout.xml
deleted file mode 100644
index 045ede4..0000000
--- a/libs/androidfw/tests/data/basic/res/layout/layout.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?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.
--->
-<Button xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/ok"
-    android:layout_width="0sp"
-    android:layout_height="fill_parent"
-    android:layout_weight="1"
-    android:layout_marginStart="2dip"
-    android:layout_marginEnd="2dip"
-    android:textAppearance="?android:attr/textAppearanceMedium"
-    android:textStyle="bold"
-    android:text="@android:string/ok" />
\ No newline at end of file
diff --git a/libs/androidfw/tests/data/basic/res/values/values.xml b/libs/androidfw/tests/data/basic/res/values/values.xml
index b343562..6c47459 100644
--- a/libs/androidfw/tests/data/basic/res/values/values.xml
+++ b/libs/androidfw/tests/data/basic/res/values/values.xml
@@ -22,7 +22,6 @@
     <attr name="attr2" format="reference|integer" />
 
     <public type="layout" name="main" id="0x7f020000" />
-    <public type="layout" name="layout" id="0x7f020001" />
 
     <public type="string" name="test1" id="0x7f030000" />
     <string name="test1">test1</string>
@@ -44,18 +43,6 @@
     <public type="integer" name="ref2" id="0x7f040003" />
     <integer name="ref2">12000</integer>
 
-    <public type="integer" name="deep_ref" id="0x7f040004" />
-    <integer name="deep_ref">@integer/deep_ref_1</integer>
-    <integer name="deep_ref_1">@integer/deep_ref_2</integer>
-    <integer name="deep_ref_2">@integer/deep_ref_3</integer>
-    <integer name="deep_ref_3">@integer/deep_ref_4</integer>
-    <integer name="deep_ref_4">@integer/deep_ref_5</integer>
-    <integer name="deep_ref_5">@integer/deep_ref_6</integer>
-    <integer name="deep_ref_6">@integer/deep_ref_7</integer>
-    <integer name="deep_ref_7">@integer/deep_ref_8</integer>
-    <integer name="deep_ref_8">@integer/deep_ref_9</integer>
-    <integer name="deep_ref_9">100</integer>
-
     <public type="style" name="Theme1" id="0x7f050000" />
     <style name="Theme1">
         <item name="com.android.basic:attr1">100</item>
diff --git a/libs/androidfw/tests/data/out_of_order_types/AndroidManifest.xml b/libs/androidfw/tests/data/out_of_order_types/AndroidManifest.xml
deleted file mode 100644
index 34016db..0000000
--- a/libs/androidfw/tests/data/out_of_order_types/AndroidManifest.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<?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.
--->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="com.android.app" />
diff --git a/libs/androidfw/tests/data/out_of_order_types/build b/libs/androidfw/tests/data/out_of_order_types/build
deleted file mode 100755
index 8496f81..0000000
--- a/libs/androidfw/tests/data/out_of_order_types/build
+++ /dev/null
@@ -1,22 +0,0 @@
-#!/bin/bash
-#
-# 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.
-#
-
-set -e
-
-aapt2 compile --dir res -o compiled.flata
-aapt2 link --manifest AndroidManifest.xml -o out_of_order_types.apk compiled.flata
-rm compiled.flata
diff --git a/libs/androidfw/tests/data/out_of_order_types/edited_resources.arsc.txt b/libs/androidfw/tests/data/out_of_order_types/edited_resources.arsc.txt
deleted file mode 100644
index eca8f47..0000000
--- a/libs/androidfw/tests/data/out_of_order_types/edited_resources.arsc.txt
+++ /dev/null
@@ -1,43 +0,0 @@
-00000000: 0200 0c00 ac02 0000 0100 0000 0100 1c00  ................
-00000010: 1c00 0000 0000 0000 0000 0000 0001 0000  ................
-00000020: 1c00 0000 0000 0000 0002 2001 8402 0000  .......... .....
-00000030: 7f00 0000 6300 6f00 6d00 2e00 6100 6e00  ....c.o.m...a.n.
-00000040: 6400 7200 6f00 6900 6400 2e00 6100 7000  d.r.o.i.d...a.p.
-00000050: 7000 0000 0000 0000 0000 0000 0000 0000  p...............
-00000060: 0000 0000 0000 0000 0000 0000 0000 0000  ................
-00000070: 0000 0000 0000 0000 0000 0000 0000 0000  ................
-00000080: 0000 0000 0000 0000 0000 0000 0000 0000  ................
-00000090: 0000 0000 0000 0000 0000 0000 0000 0000  ................
-000000a0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
-000000b0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
-000000c0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
-000000d0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
-000000e0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
-000000f0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
-00000100: 0000 0000 0000 0000 0000 0000 0000 0000  ................
-00000110: 0000 0000 0000 0000 0000 0000 0000 0000  ................
-00000120: 0000 0000 0000 0000 0000 0000 0000 0000  ................
-00000130: 0000 0000 2001 0000 0000 0000 6401 0000  .... .......d...
-00000140: 0000 0000 0000 0000 0100 1c00 4400 0000  ............D...
-00000150: 0200 0000 0000 0000 0000 0000 2400 0000  ............$...
-00000160: 0000 0000 0000 0000 0c00 0000 0400 6200  ..............b.
-00000170: 6f00 6f00 6c00 0000 0700 6900 6e00 7400  o.o.l.....i.n.t.
-00000180: 6500 6700 6500 7200 0000 0000 0100 1c00  e.g.e.r.........
-00000190: 2800 0000 0100 0000 0000 0000 0001 0000  (...............
-000001a0: 2000 0000 0000 0000 0000 0000 0404 7465   .............te
-000001b0: 7374 0000 0202 1000 1400 0000 0100 0000  st..............
-000001c0: 0100 0000 0000 0000 0202 1000 1400 0000
-000001d0: 0200 0000 0100 0000 0000 0000 0102 5400
-000001e0: 6800 0000 0100 0000 0100 0000 5800 0000
-000001f0: 4000 0000 0000 0000 0000 0000 0000 0000
-00000200: 0000 0000 0000 0000 0000 0000 0000 0000
-00000210: 0000 0000 0000 0000 0000 0000 0000 0000
-00000220: 0000 0000 0000 0000 0000 0000 0000 0000
-00000230: 0000 0000 0800 0000 0000 0000 0800 0012
-00000240: ffff ffff 0102 5400 6800 0000 0200 0000  ......T.h.......
-00000250: 0100 0000 5800 0000 4000 0000 0000 0000  ....X...@.......
-00000260: 0000 0000 0000 0000 0000 0000 0000 0000  ................
-00000270: 0000 0000 0000 0000 0000 0000 0000 0000  ................
-00000280: 0000 0000 0000 0000 0000 0000 0000 0000  ................
-00000290: 0000 0000 0000 0000 0000 0000 0800 0000  ................
-000002a0: 0000 0000 0800 0010 0100 0000            ............
diff --git a/libs/androidfw/tests/data/out_of_order_types/out_of_order_types.apk b/libs/androidfw/tests/data/out_of_order_types/out_of_order_types.apk
deleted file mode 100644
index 75146e0..0000000
--- a/libs/androidfw/tests/data/out_of_order_types/out_of_order_types.apk
+++ /dev/null
Binary files differ
diff --git a/libs/androidfw/tests/data/out_of_order_types/res/values/values.xml b/libs/androidfw/tests/data/out_of_order_types/res/values/values.xml
deleted file mode 100644
index 7c54fba..0000000
--- a/libs/androidfw/tests/data/out_of_order_types/res/values/values.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?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>
-    <bool name="test">true</bool>
-    <integer name="test">1</integer>
-</resources>
diff --git a/libs/androidfw/tests/data/system/assets/file.txt b/libs/androidfw/tests/data/system/assets/file.txt
deleted file mode 100644
index f73f309..0000000
--- a/libs/androidfw/tests/data/system/assets/file.txt
+++ /dev/null
@@ -1 +0,0 @@
-file
diff --git a/libs/androidfw/tests/data/system/assets/subdir/subdir_file.txt b/libs/androidfw/tests/data/system/assets/subdir/subdir_file.txt
deleted file mode 100644
index 3f74eb6..0000000
--- a/libs/androidfw/tests/data/system/assets/subdir/subdir_file.txt
+++ /dev/null
@@ -1 +0,0 @@
-subdir file
diff --git a/libs/androidfw/tests/data/system/build b/libs/androidfw/tests/data/system/build
index b65145a..bfbdf4c 100755
--- a/libs/androidfw/tests/data/system/build
+++ b/libs/androidfw/tests/data/system/build
@@ -17,6 +17,4 @@
 
 set -e
 
-aapt2 compile --dir res -o compiled.flata
-aapt2 link --manifest AndroidManifest.xml -A assets -o system.apk compiled.flata
-rm compiled.flata
+aapt package -x -M AndroidManifest.xml -S res -F system.apk -f
diff --git a/libs/androidfw/tests/data/system/res/values-sv/values.xml b/libs/androidfw/tests/data/system/res/values-sv/values.xml
index 5f60d21..b97bdb6 100644
--- a/libs/androidfw/tests/data/system/res/values-sv/values.xml
+++ b/libs/androidfw/tests/data/system/res/values-sv/values.xml
@@ -15,5 +15,6 @@
 -->
 
 <resources>
+    <public type="integer" name="number" id="0x01030000" />
     <integer name="number">1</integer>
 </resources>
diff --git a/libs/androidfw/tests/data/system/res/values/themes.xml b/libs/androidfw/tests/data/system/res/values/themes.xml
index 7893c94..35d43c7 100644
--- a/libs/androidfw/tests/data/system/res/values/themes.xml
+++ b/libs/androidfw/tests/data/system/res/values/themes.xml
@@ -18,7 +18,6 @@
     <public name="background" type="attr" id="0x01010000"/>
     <public name="foreground" type="attr" id="0x01010001"/>
     <public name="Theme.One" type="style" id="0x01020000"/>
-    <public type="integer" name="number" id="0x01030000" />
 
     <attr name="background" format="color|reference"/>
     <attr name="foreground" format="color|reference"/>
diff --git a/libs/androidfw/tests/data/system/system.apk b/libs/androidfw/tests/data/system/system.apk
index 9045d6c..1299016 100644
--- a/libs/androidfw/tests/data/system/system.apk
+++ b/libs/androidfw/tests/data/system/system.apk
Binary files differ
diff --git a/libs/hwui/hwui/AnimatedImageDrawable.cpp b/libs/hwui/hwui/AnimatedImageDrawable.cpp
index 2bded9b..7e4f755 100644
--- a/libs/hwui/hwui/AnimatedImageDrawable.cpp
+++ b/libs/hwui/hwui/AnimatedImageDrawable.cpp
@@ -41,8 +41,7 @@
         return false;
     }
 
-    // This will trigger a reset.
-    mFinished = true;
+    mStarting = true;
 
     mRunning = true;
     return true;
@@ -125,8 +124,11 @@
 
     mDidDraw = true;
 
-    bool drewDirectly = false;
-    if (!mSnapshot.mPic) {
+    const bool starting = mStarting;
+    mStarting = false;
+
+    const bool drawDirectly = !mSnapshot.mPic;
+    if (drawDirectly) {
         // The image is not animating, and never was. Draw directly from
         // mSkAnimatedImage.
         SkAutoCanvasRestore acr(canvas, false);
@@ -136,13 +138,14 @@
 
         std::unique_lock lock{mImageLock};
         mSkAnimatedImage->draw(canvas);
-        drewDirectly = true;
-    }
-
-    if (mRunning && mFinished) {
+        if (!mRunning) {
+            return;
+        }
+    } else if (starting) {
+        // The image has animated, and now is being reset. Queue up the first
+        // frame, but keep showing the current frame until the first is ready.
         auto& thread = uirenderer::AnimatedImageThread::getInstance();
         mNextSnapshot = thread.reset(sk_ref_sp(this));
-        mFinished = false;
     }
 
     bool finalFrame = false;
@@ -154,7 +157,6 @@
             if (mSnapshot.mDuration == SkAnimatedImage::kFinished) {
                 finalFrame = true;
                 mRunning = false;
-                mFinished = true;
             } else {
                 mTimeToShowNextSnapshot += mSnapshot.mDuration;
                 if (mCurrentTime >= mTimeToShowNextSnapshot) {
@@ -173,7 +175,7 @@
         mNextSnapshot = thread.decodeNextFrame(sk_ref_sp(this));
     }
 
-    if (!drewDirectly) {
+    if (!drawDirectly) {
         // No other thread will modify mCurrentSnap so this should be safe to
         // use without locking.
         canvas->drawPicture(mSnapshot.mPic, nullptr, lazyPaint.getMaybeNull());
@@ -195,14 +197,29 @@
         canvas->saveLayer(mSkAnimatedImage->getBounds(), &paint);
     }
 
-    if (mFinished && !mRunning) {
-        // Continue drawing the last frame, and return 0 to indicate no need to
-        // redraw.
+    if (!mRunning) {
+        // Continue drawing the current frame, and return 0 to indicate no need
+        // to redraw.
         std::unique_lock lock{mImageLock};
         canvas->drawDrawable(mSkAnimatedImage.get());
         return 0.0;
     }
 
+    if (mStarting) {
+        mStarting = false;
+        double duration = 0.0;
+        {
+            std::unique_lock lock{mImageLock};
+            mSkAnimatedImage->reset();
+            duration = mSkAnimatedImage->currentFrameDuration();
+        }
+        {
+            std::unique_lock lock{mSwapLock};
+            mLastWallTime = 0.0;
+            mTimeToShowNextSnapshot = duration;
+        }
+    }
+
     bool update = false;
     {
         const double currentTime = SkTime::GetMSecs();
@@ -211,18 +228,12 @@
         // the current time and avoid updating
         if (mLastWallTime == 0.0) {
             mCurrentTime = currentTime;
-        } else if (mRunning) {
-            if (mFinished) {
-                mCurrentTime = currentTime;
-                {
-                    std::unique_lock lock{mImageLock};
-                    mSkAnimatedImage->reset();
-                }
-                mTimeToShowNextSnapshot = currentTime + mSkAnimatedImage->currentFrameDuration();
-            } else {
-                mCurrentTime += currentTime - mLastWallTime;
-                update = mCurrentTime >= mTimeToShowNextSnapshot;
-            }
+            // mTimeToShowNextSnapshot is already set to the duration of the
+            // first frame.
+            mTimeToShowNextSnapshot += currentTime;
+        } else if (mRunning && mDidDraw) {
+            mCurrentTime += currentTime - mLastWallTime;
+            update = mCurrentTime >= mTimeToShowNextSnapshot;
         }
         mLastWallTime = currentTime;
     }
@@ -237,13 +248,20 @@
         canvas->drawDrawable(mSkAnimatedImage.get());
     }
 
+    mDidDraw = true;
+
     std::unique_lock lock{mSwapLock};
     if (update) {
         if (duration == SkAnimatedImage::kFinished) {
             mRunning = false;
-            mFinished = true;
-        } else {
-            mTimeToShowNextSnapshot += duration;
+            return duration;
+        }
+
+        const double timeToShowCurrentSnapshot = mTimeToShowNextSnapshot;
+        mTimeToShowNextSnapshot += duration;
+        if (mCurrentTime >= mTimeToShowNextSnapshot) {
+            // As in onDraw, prevent speedy catch-up behavior.
+            mCurrentTime = timeToShowCurrentSnapshot;
         }
     }
     return mTimeToShowNextSnapshot;
diff --git a/libs/hwui/hwui/AnimatedImageDrawable.h b/libs/hwui/hwui/AnimatedImageDrawable.h
index 2fd6f40..07469d2 100644
--- a/libs/hwui/hwui/AnimatedImageDrawable.h
+++ b/libs/hwui/hwui/AnimatedImageDrawable.h
@@ -102,7 +102,7 @@
 private:
     sk_sp<SkAnimatedImage> mSkAnimatedImage;
     bool mRunning = false;
-    bool mFinished = false;
+    bool mStarting = false;
 
     // A snapshot of the current frame to draw.
     Snapshot mSnapshot;
diff --git a/libs/protoutil/include/android/util/EncodedBuffer.h b/libs/protoutil/include/android/util/EncodedBuffer.h
index e568e4c..0a8a5aa 100644
--- a/libs/protoutil/include/android/util/EncodedBuffer.h
+++ b/libs/protoutil/include/android/util/EncodedBuffer.h
@@ -64,6 +64,11 @@
         size_t mOffset;
     };
 
+    /**
+     * Clears the buffer by rewinding its write pointer to avoid de/allocate buffers in heap.
+     */
+    void clear();
+
     /******************************** Write APIs ************************************************/
 
     /**
diff --git a/libs/protoutil/include/android/util/ProtoOutputStream.h b/libs/protoutil/include/android/util/ProtoOutputStream.h
index faea9b2..52830d3 100644
--- a/libs/protoutil/include/android/util/ProtoOutputStream.h
+++ b/libs/protoutil/include/android/util/ProtoOutputStream.h
@@ -123,6 +123,11 @@
     EncodedBuffer::iterator data(); // Get the reader apis of the data.
     bool flush(int fd); // Flush data directly to a file descriptor.
 
+    /**
+     * Clears the ProtoOutputStream so the buffer can be reused instead of deallocation/allocation again.
+     */
+    void clear();
+
     // Please don't use the following functions to dump protos unless you are familiar with protobuf encoding.
     void writeRawVarint(uint64_t varint);
     void writeLengthDelimitedHeader(uint32_t id, size_t size);
diff --git a/libs/protoutil/src/EncodedBuffer.cpp b/libs/protoutil/src/EncodedBuffer.cpp
index 435ae88..3a5e2e9 100644
--- a/libs/protoutil/src/EncodedBuffer.cpp
+++ b/libs/protoutil/src/EncodedBuffer.cpp
@@ -106,6 +106,13 @@
     return mBuffers[p.index()] + p.offset();
 }
 
+void
+EncodedBuffer::clear()
+{
+    mWp.rewind();
+    mEp.rewind();
+}
+
 /******************************** Write APIs ************************************************/
 size_t
 EncodedBuffer::size() const
diff --git a/libs/protoutil/src/ProtoOutputStream.cpp b/libs/protoutil/src/ProtoOutputStream.cpp
index f24abae..9d9ffec 100644
--- a/libs/protoutil/src/ProtoOutputStream.cpp
+++ b/libs/protoutil/src/ProtoOutputStream.cpp
@@ -36,6 +36,18 @@
 {
 }
 
+
+void
+ProtoOutputStream::clear()
+{
+    mBuffer.clear();
+    mCopyBegin = 0;
+    mCompact = false;
+    mDepth = 0;
+    mObjectId = 0;
+    mExpectedObjectToken = 0LL;
+}
+
 bool
 ProtoOutputStream::write(uint64_t fieldId, double val)
 {
diff --git a/media/java/android/media/MediaBrowser2.java b/media/java/android/media/MediaBrowser2.java
index 5cb8313..32d3162 100644
--- a/media/java/android/media/MediaBrowser2.java
+++ b/media/java/android/media/MediaBrowser2.java
@@ -53,8 +53,32 @@
                 @Nullable Bundle rootExtra) { }
 
         /**
+         * Called when there's change in the parent's children.
+         *
+         * @param parentId parent id that you've specified with {@link #subscribe(String, Bundle)}
+         * @param extras extra bundle that you've specified with {@link #subscribe(String, Bundle)}
+         */
+        public void onChildrenChanged(@NonNull String parentId, @Nullable Bundle extras) { }
+
+        /**
+         * Called when the list of items has been returned by the library service for the previous
+         * {@link MediaBrowser2#getChildren(String, int, int, Bundle)}.
+         *
+         * @param parentId parent id
+         * @param page page number that you've specified with
+         *             {@link #getChildren(String, int, int, Bundle)}
+         * @param pageSize page size that you've specified with
+         *                 {@link #getChildren(String, int, int, Bundle)}
+         * @param extras extra bundle that you've specified with
+         *                {@link #getChildren(String, int, int, Bundle)}
+         * @param result result. Can be {@code null}
+         */
+        public void onChildrenLoaded(@NonNull String parentId, int page, int pageSize,
+                @Nullable Bundle extras, @Nullable List<MediaItem2> result) { }
+
+        /**
          * Called when the item has been returned by the library service for the previous
-         * {@link MediaBrowser2#getItem} call.
+         * {@link MediaBrowser2#getItem(String)} call.
          * <p>
          * Result can be null if there had been error.
          *
@@ -64,40 +88,33 @@
         public void onItemLoaded(@NonNull String mediaId, @Nullable MediaItem2 result) { }
 
         /**
-         * Called when the list of items has been returned by the library service for the previous
-         * {@link MediaBrowser2#getChildren(String, int, int, Bundle)}.
+         * Called when there's change in the search result.
          *
-         * @param parentId parent id
-         * @param page page number that you've specified
-         * @param pageSize page size that you've specified
-         * @param options optional bundle that you've specified
-         * @param result result. Can be {@code null}
+         * @param query search query that you've specified with {@link #search(String, Bundle)}
+         * @param extras extra bundle that you've specified with {@link #search(String, Bundle)}
+         * @param totalItemCount The total item count for the search result
          */
-        public void onChildrenLoaded(@NonNull String parentId, int page, int pageSize,
-                @Nullable Bundle options, @Nullable List<MediaItem2> result) { }
-
-        /**
-         * Called when there's change in the parent's children.
-         *
-         * @param parentId parent id that you've specified with subscribe
-         * @param options optional bundle that you've specified with subscribe
-         */
-        public void onChildrenChanged(@NonNull String parentId, @Nullable Bundle options) { }
+        public void onSearchResultChanged(@NonNull String query, @Nullable Bundle extras,
+                int totalItemCount) { }
 
         /**
          * Called when the search result has been returned by the library service for the previous
-         * {@link MediaBrowser2#search(String, int, int, Bundle)}.
+         * {@link MediaBrowser2#getSearchResult(String, int, int, Bundle)}.
          * <p>
          * Result can be null if there had been error.
          *
-         * @param query query string that you've specified
-         * @param page page number that you've specified
-         * @param pageSize page size that you've specified
-         * @param options optional bundle that you've specified
-         * @param result result. Can be {@code null}
+         * @param query search query that you've specified with
+         *              {@link #getSearchResult(String, int, int, Bundle)}
+         * @param page page number that you've specified with
+         *             {@link #getSearchResult(String, int, int, Bundle)}
+         * @param pageSize page size that you've specified with
+         *                 {@link #getSearchResult(String, int, int, Bundle)}
+         * @param extras extra bundle that you've specified with
+         *                {@link #getSearchResult(String, int, int, Bundle)}
+         * @param result result. Can be {@code null}.
          */
-        public void onSearchResult(@NonNull String query, int page, int pageSize,
-                @Nullable Bundle options, @Nullable List<MediaItem2> result) { }
+        public void onSearchResultLoaded(@NonNull String query, int page, int pageSize,
+                @Nullable Bundle extras, @Nullable List<MediaItem2> result) { }
     }
 
     public MediaBrowser2(@NonNull Context context, @NonNull SessionToken2 token,
@@ -131,10 +148,10 @@
      * the actual contents for the parent.
      *
      * @param parentId parent id
-     * @param options optional bundle
+     * @param extras extra bundle
      */
-    public void subscribe(String parentId, @Nullable Bundle options) {
-        mProvider.subscribe_impl(parentId, options);
+    public void subscribe(String parentId, @Nullable Bundle extras) {
+        mProvider.subscribe_impl(parentId, extras);
     }
 
     /**
@@ -142,43 +159,59 @@
      * {@link #subscribe(String, Bundle)}.
      *
      * @param parentId parent id
-     * @param options optional bundle
+     * @param extras extra bundle
      */
-    public void unsubscribe(String parentId, @Nullable Bundle options) {
-        mProvider.unsubscribe_impl(parentId, options);
-    }
-
-    /**
-     * Get the media item with the given media id. Result would be sent back asynchronously with the
-     * {@link BrowserCallback#onItemLoaded(String, MediaItem2)}.
-     *
-     * @param mediaId media id
-     */
-    public void getItem(String mediaId) {
-        mProvider.getItem_impl(mediaId);
+    public void unsubscribe(String parentId, @Nullable Bundle extras) {
+        mProvider.unsubscribe_impl(parentId, extras);
     }
 
     /**
      * Get list of children under the parent. Result would be sent back asynchronously with the
      * {@link BrowserCallback#onChildrenLoaded(String, int, int, Bundle, List)}.
      *
-     * @param parentId
-     * @param page
-     * @param pageSize
-     * @param options
+     * @param parentId parent id for getting the children.
+     * @param page page number to get the result. Starts from {@code 1}
+     * @param pageSize page size. Should be greater or equal to {@code 1}
+     * @param extras extra bundle
      */
-    public void getChildren(String parentId, int page, int pageSize, @Nullable Bundle options) {
-        mProvider.getChildren_impl(parentId, page, pageSize, options);
+    public void getChildren(String parentId, int page, int pageSize, @Nullable Bundle extras) {
+        mProvider.getChildren_impl(parentId, page, pageSize, extras);
     }
 
     /**
+     * Get the media item with the given media id. Result would be sent back asynchronously with the
+     * {@link BrowserCallback#onItemLoaded(String, MediaItem2)}.
      *
-     * @param query search query deliminated by string
+     * @param mediaId media id for specifying the item
+     */
+    public void getItem(String mediaId) {
+        mProvider.getItem_impl(mediaId);
+    }
+
+    /**
+     * Send a search request to the library service. When there's a change,
+     * {@link BrowserCallback#onSearchResultChanged(String, Bundle, int)} will be called with the
+     * bundle that you've specified. You should call
+     * {@link #getSearchResult(String, int, int, Bundle)} to get the actual search result.
+     *
+     * @param query search query. Should not be an empty string.
+     * @param extras extra bundle
+     */
+    public void search(@NonNull String query, @Nullable Bundle extras) {
+        mProvider.search_impl(query, extras);
+    }
+
+    /**
+     * Get the search result from lhe library service. Result would be sent back asynchronously with
+     * the {@link BrowserCallback#onSearchResultLoaded(String, int, int, Bundle, List)}.
+     *
+     * @param query search query that you've specified with {@link #search(String, Bundle)}
      * @param page page number to get search result. Starts from {@code 1}
      * @param pageSize page size. Should be greater or equal to {@code 1}
      * @param extras extra bundle
      */
-    public void search(String query, int page, int pageSize, Bundle extras) {
-        mProvider.search_impl(query, page, pageSize, extras);
+    public void getSearchResult(@NonNull String query, int page, int pageSize,
+            @Nullable Bundle extras) {
+        mProvider.getSearchResult_impl(query, page, pageSize, extras);
     }
 }
diff --git a/media/java/android/media/MediaDrm.java b/media/java/android/media/MediaDrm.java
index 90fcaab..279e05f 100644
--- a/media/java/android/media/MediaDrm.java
+++ b/media/java/android/media/MediaDrm.java
@@ -634,8 +634,39 @@
      * @throws ResourceBusyException if required resources are in use
      */
     @NonNull
-    public native byte[] openSession() throws NotProvisionedException,
-            ResourceBusyException;
+    public byte[] openSession() throws NotProvisionedException,
+            ResourceBusyException {
+        return openSession(getMaxSecurityLevel());
+    }
+
+    /**
+     * Open a new session at a requested security level. The security level
+     * represents the robustness of the device's DRM implementation. By default,
+     * sessions are opened at the native security level of the device.
+     * Overriding the security level is necessary when the decrypted frames need
+     * to be manipulated, such as for image compositing. The security level
+     * parameter must be lower than the native level. Reducing the security
+     * level will typically limit the content to lower resolutions, as
+     * determined by the license policy. If the requested level is not
+     * supported, the next lower supported security level will be set. The level
+     * can be queried using {@link #getSecurityLevel}. A session
+     * ID is returned.
+     *
+     * @param level the new security level, one of
+     * {@link #SW_SECURE_CRYPTO}, {@link #SW_SECURE_DECODE},
+     * {@link #HW_SECURE_CRYPTO}, {@link #HW_SECURE_DECODE} or
+     * {@link #HW_SECURE_ALL}.
+     *
+     * @throws NotProvisionedException if provisioning is needed
+     * @throws ResourceBusyException if required resources are in use
+     * @throws IllegalArgumentException if the requested security level is
+     * higher than the native level or lower than the lowest supported level or
+     * if the device does not support specifying the security level when opening
+     * a session
+     */
+    @NonNull
+    public native byte[] openSession(@SecurityLevel int level) throws
+            NotProvisionedException, ResourceBusyException;
 
     /**
      * Close a session on the MediaDrm object that was previously opened
@@ -1109,7 +1140,7 @@
      */
     @Retention(RetentionPolicy.SOURCE)
     @IntDef({SECURITY_LEVEL_UNKNOWN, SW_SECURE_CRYPTO, SW_SECURE_DECODE,
-                        HW_SECURE_CRYPTO, HW_SECURE_DECODE, HW_SECURE_ALL})
+            HW_SECURE_CRYPTO, HW_SECURE_DECODE, HW_SECURE_ALL})
     public @interface SecurityLevel {}
 
     /**
@@ -1119,39 +1150,55 @@
     public static final int SECURITY_LEVEL_UNKNOWN = 0;
 
     /**
-     *  Software-based whitebox crypto
+     * DRM key management uses software-based whitebox crypto.
      */
     public static final int SW_SECURE_CRYPTO = 1;
 
     /**
-     * Software-based whitebox crypto and an obfuscated decoder
+     * DRM key management and decoding use software-based whitebox crypto.
      */
-     public static final int SW_SECURE_DECODE = 2;
+    public static final int SW_SECURE_DECODE = 2;
 
     /**
-     * DRM key management and crypto operations are performed within a
-     * hardware backed trusted execution environment
+     * DRM key management and crypto operations are performed within a hardware
+     * backed trusted execution environment.
      */
     public static final int HW_SECURE_CRYPTO = 3;
 
     /**
-     * DRM key management, crypto operations and decoding of content
-     * are performed within a hardware backed trusted execution environment
+     * DRM key management, crypto operations and decoding of content are
+     * performed within a hardware backed trusted execution environment.
      */
-     public static final int HW_SECURE_DECODE = 4;
+    public static final int HW_SECURE_DECODE = 4;
 
     /**
      * DRM key management, crypto operations, decoding of content and all
-     * handling of the media (compressed and uncompressed) is handled within
-     * a hardware backed trusted execution environment.
+     * handling of the media (compressed and uncompressed) is handled within a
+     * hardware backed trusted execution environment.
      */
     public static final int HW_SECURE_ALL = 5;
 
     /**
-     * Return the current security level of a session. A session
-     * has an initial security level determined by the robustness of
-     * the DRM system's implementation on the device. The security
-     * level may be adjusted using {@link #setSecurityLevel}.
+     * The maximum security level supported by the device. This is the default
+     * security level when a session is opened.
+     * @hide
+     */
+    public static final int SECURITY_LEVEL_MAX = 6;
+
+    /**
+     * The maximum security level supported by the device. This is the default
+     * security level when a session is opened.
+     */
+    @SecurityLevel
+    public static final int getMaxSecurityLevel() {
+        return SECURITY_LEVEL_MAX;
+    }
+
+    /**
+     * Return the current security level of a session. A session has an initial
+     * security level determined by the robustness of the DRM system's
+     * implementation on the device. The security level may be changed at the
+     * time a session is opened using {@link #openSession}.
      * @param sessionId the session to query.
      * <p>
      * @return one of {@link #SECURITY_LEVEL_UNKNOWN},
@@ -1163,21 +1210,6 @@
     public native int getSecurityLevel(@NonNull byte[] sessionId);
 
     /**
-     * Set the security level of a session. This can be useful if specific
-     * attributes of a lower security level are needed by an application,
-     * such as image manipulation or compositing. Reducing the security
-     * level will typically limit decryption to lower content resolutions,
-     * depending on the license policy.
-     * @param sessionId the session to set the security level on.
-     * @param level the new security level, one of
-     * {@link #SW_SECURE_CRYPTO}, {@link #SW_SECURE_DECODE},
-     * {@link #HW_SECURE_CRYPTO}, {@link #HW_SECURE_DECODE} or
-     * {@link #HW_SECURE_ALL}.
-     */
-    public native void setSecurityLevel(@NonNull byte[] sessionId,
-            @SecurityLevel int level);
-
-    /**
      * String property name: identifies the maker of the DRM plugin
      */
     public static final String PROPERTY_VENDOR = "vendor";
diff --git a/media/java/android/media/MediaItem2.java b/media/java/android/media/MediaItem2.java
index eae4436..667aac1 100644
--- a/media/java/android/media/MediaItem2.java
+++ b/media/java/android/media/MediaItem2.java
@@ -123,27 +123,26 @@
     }
 
     /**
-     * Set a metadata. Metadata shouldn't be {@code null} and its id should be match
-     * with this instance's id.
+     * Set a metadata. If the metadata is not null, its id should be matched with this instance's
+     * media id.
      *
      * @param metadata metadata to update
      */
-    public void setMetadata(@NonNull MediaMetadata2 metadata) {
+    public void setMetadata(@Nullable MediaMetadata2 metadata) {
         mProvider.setMetadata_impl(metadata);
     }
 
     /**
      * Returns the metadata of the media.
      */
-    public @NonNull MediaMetadata2 getMetadata() {
+    public @Nullable MediaMetadata2 getMetadata() {
         return mProvider.getMetadata_impl();
     }
 
     /**
-     * Returns the media id in the {@link MediaMetadata2} for this item.
-     * @see MediaMetadata2#METADATA_KEY_MEDIA_ID
+     * Returns the media id for this item.
      */
-    public @Nullable String getMediaId() {
+    public @NonNull String getMediaId() {
         return mProvider.getMediaId_impl();
     }
 
diff --git a/media/java/android/media/MediaLibraryService2.java b/media/java/android/media/MediaLibraryService2.java
index a11768e..7a05d3c 100644
--- a/media/java/android/media/MediaLibraryService2.java
+++ b/media/java/android/media/MediaLibraryService2.java
@@ -82,22 +82,22 @@
          *
          * @param controller controller to notify
          * @param parentId
-         * @param options
+         * @param extras
          */
         public void notifyChildrenChanged(@NonNull ControllerInfo controller,
-                @NonNull String parentId, @NonNull Bundle options) {
-            mProvider.notifyChildrenChanged_impl(controller, parentId, options);
+                @NonNull String parentId, @NonNull Bundle extras) {
+            mProvider.notifyChildrenChanged_impl(controller, parentId, extras);
         }
 
         /**
          * Notify subscribed controller about change in a parent's children.
          *
          * @param parentId parent id
-         * @param options optional bundle
+         * @param extras extra bundle
          */
         // This is for the backward compatibility.
-        public void notifyChildrenChanged(@NonNull String parentId, @Nullable Bundle options) {
-            mProvider.notifyChildrenChanged_impl(parentId, options);
+        public void notifyChildrenChanged(@NonNull String parentId, @Nullable Bundle extras) {
+            mProvider.notifyChildrenChanged_impl(parentId, extras);
         }
     }
 
@@ -134,27 +134,12 @@
         }
 
         /**
-         * Called to get the search result. Return search result here for the browser.
+         * Called to get an item. Return result here for the browser.
          * <p>
-         * Return an empty list for no search result, and return {@code null} for the error.
-         *
-         * @param query The search query sent from the media browser. It contains keywords separated
-         *            by space.
-         * @param extras The bundle of service-specific arguments sent from the media browser.
-         * @return search result. {@code null} for error.
-         */
-        public @Nullable List<MediaItem2> onSearch(@NonNull ControllerInfo controllerInfo,
-                @NonNull String query, @Nullable Bundle extras) {
-            return null;
-        }
-
-        /**
-         * Called to get the search result . Return result here for the browser.
-         * <p>
-         * Return an empty list for no search result, and return {@code null} for the error.
+         * Return {@code null} for no result or error.
          *
          * @param itemId item id to get media item.
-         * @return media item2. {@code null} for error.
+         * @return a media item. {@code null} for no result or error.
          */
         public @Nullable MediaItem2 onLoadItem(@NonNull ControllerInfo controllerInfo,
                 @NonNull String itemId) {
@@ -162,18 +147,18 @@
         }
 
         /**
-         * Called to get the search result. Return search result here for the browser.
+         * Called to get children of given parent id. Return the children here for the browser.
          * <p>
-         * Return an empty list for no search result, and return {@code null} for the error.
+         * Return an empty list for no children, and return {@code null} for the error.
          *
          * @param parentId parent id to get children
          * @param page number of page
          * @param pageSize size of the page
-         * @param options
+         * @param extras extra bundle
          * @return list of children. Can be {@code null}.
          */
         public @Nullable List<MediaItem2> onLoadChildren(@NonNull ControllerInfo controller,
-                @NonNull String parentId, int page, int pageSize, @Nullable Bundle options) {
+                @NonNull String parentId, int page, int pageSize, @Nullable Bundle extras) {
             return null;
         }
 
@@ -182,10 +167,10 @@
          *
          * @param controller controller
          * @param parentId parent id
-         * @param options optional bundle
+         * @param extras extra bundle
          */
-        public void onSubscribed(@NonNull ControllerInfo controller,
-                String parentId, @Nullable Bundle options) {
+        public void onSubscribed(@NonNull ControllerInfo controller, String parentId,
+                @Nullable Bundle extras) {
         }
 
         /**
@@ -193,10 +178,41 @@
          *
          * @param controller controller
          * @param parentId parent id
-         * @param options optional bundle
+         * @param extras extra bundle
          */
-        public void onUnsubscribed(@NonNull ControllerInfo controller,
-                String parentId, @Nullable Bundle options) {
+        public void onUnsubscribed(@NonNull ControllerInfo controller, String parentId,
+                @Nullable Bundle extras) {
+        }
+
+        /**
+         * Called when a controller requests search.
+         *
+         * @param query The search query sent from the media browser. It contains keywords separated
+         *              by space.
+         * @param extras The bundle of service-specific arguments sent from the media browser.
+         */
+        public void onSearch(@NonNull ControllerInfo controllerInfo, @NonNull String query,
+                @Nullable Bundle extras) {
+
+        }
+
+        /**
+         * Called to get the search result. Return search result here for the browser which has
+         * requested search previously.
+         * <p>
+         * Return an empty list for no search result, and return {@code null} for the error.
+         *
+         * @param controllerInfo Information of the controller requesting the search result.
+         * @param query The search query which was previously sent through
+         *              {@link #onSearch(ControllerInfo, String, Bundle)} call.
+         * @param page page number. Starts from {@code 1}.
+         * @param pageSize page size. Should be greater or equal to {@code 1}.
+         * @param extras The bundle of service-specific arguments sent from the media browser.
+         * @return search result. {@code null} for error.
+         */
+        public @Nullable List<MediaItem2> onLoadSearchResult(@NonNull ControllerInfo controllerInfo,
+                @NonNull String query, int page, int pageSize, @Nullable Bundle extras) {
+            return null;
         }
     }
 
diff --git a/media/java/android/media/MediaPlayer2Impl.java b/media/java/android/media/MediaPlayer2Impl.java
index d4e9aac..b805eb44 100644
--- a/media/java/android/media/MediaPlayer2Impl.java
+++ b/media/java/android/media/MediaPlayer2Impl.java
@@ -17,7 +17,6 @@
 package android.media;
 
 import android.annotation.CallbackExecutor;
-import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.ActivityThread;
@@ -26,7 +25,6 @@
 import android.content.Context;
 import android.content.res.AssetFileDescriptor;
 import android.net.Uri;
-import android.os.Bundle;
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.Looper;
@@ -48,17 +46,8 @@
 import android.view.SurfaceHolder;
 import android.widget.VideoView;
 import android.graphics.SurfaceTexture;
-import android.media.AudioManager;
-import android.media.MediaDrm;
-import android.media.MediaFormat;
-import android.media.MediaPlayer2;
-import android.media.MediaTimeProvider;
-import android.media.PlaybackParams;
-import android.media.SubtitleController;
 import android.media.SubtitleController.Anchor;
-import android.media.SubtitleData;
 import android.media.SubtitleTrack.RenderingWidget;
-import android.media.SyncParams;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.util.Preconditions;
@@ -74,16 +63,12 @@
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
-import java.lang.AutoCloseable;
 import java.lang.Runnable;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
 import java.lang.ref.WeakReference;
 import java.net.CookieHandler;
 import java.net.CookieManager;
 import java.net.HttpCookie;
 import java.net.HttpURLConnection;
-import java.net.InetSocketAddress;
 import java.net.URL;
 import java.nio.ByteOrder;
 import java.util.ArrayList;
@@ -1212,6 +1197,7 @@
         } else if (scheme != null) {
             // handle non-file sources
             nativeSetDataSource(
+                srcId,
                 Media2HTTPService.createHTTPService(path, cookies),
                 path,
                 keys,
@@ -1231,7 +1217,7 @@
     }
 
     private native void nativeSetDataSource(
-        Media2HTTPService httpService, String path, String[] keys, String[] values)
+        long srcId, Media2HTTPService httpService, String path, String[] keys, String[] values)
         throws IOException, IllegalArgumentException, SecurityException, IllegalStateException;
 
     /**
@@ -1245,10 +1231,10 @@
      */
     private void setDataSourcePriv(long srcId, FileDescriptor fd, long offset, long length)
             throws IOException {
-        _setDataSource(fd, offset, length);
+        _setDataSource(srcId, fd, offset, length);
     }
 
-    private native void _setDataSource(FileDescriptor fd, long offset, long length)
+    private native void _setDataSource(long srcId, FileDescriptor fd, long offset, long length)
             throws IOException;
 
     /**
@@ -1256,10 +1242,10 @@
      * @throws IllegalArgumentException if dataSource is not a valid Media2DataSource
      */
     private void setDataSourcePriv(long srcId, Media2DataSource dataSource) {
-        _setDataSource(dataSource);
+        _setDataSource(srcId, dataSource);
     }
 
-    private native void _setDataSource(Media2DataSource dataSource);
+    private native void _setDataSource(long srcId, Media2DataSource dataSource);
 
     /**
      * Prepares the player for playback, synchronously.
@@ -2189,6 +2175,13 @@
     private native final void native_setup(Object mediaplayer2_this);
     private native final void native_finalize();
 
+    private static native final void native_stream_event_onTearDown(
+            long nativeCallbackPtr, long userDataPtr);
+    private static native final void native_stream_event_onStreamPresentationEnd(
+            long nativeCallbackPtr, long userDataPtr);
+    private static native final void native_stream_event_onStreamDataRequest(
+            long jAudioTrackPtr, long nativeCallbackPtr, long userDataPtr);
+
     /**
      * Class for MediaPlayer2 to return each audio/video/subtitle track's metadata.
      *
@@ -3073,6 +3066,10 @@
 
         @Override
         public void handleMessage(Message msg) {
+            handleMessage(msg, 0);
+        }
+
+        public void handleMessage(Message msg, long srcId) {
             if (mMediaPlayer.mNativeContext == 0) {
                 Log.w(TAG, "mediaplayer2 went away with unhandled events");
                 return;
@@ -3095,7 +3092,7 @@
                 synchronized (mEventCbLock) {
                     for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) {
                         cb.first.execute(() -> cb.second.onInfo(
-                                mMediaPlayer, 0, MEDIA_INFO_PREPARED, 0));
+                                mMediaPlayer, srcId, MEDIA_INFO_PREPARED, 0));
                     }
                 }
                 return;
@@ -3133,7 +3130,7 @@
                 synchronized (mEventCbLock) {
                     for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) {
                         cb.first.execute(() -> cb.second.onInfo(
-                                mMediaPlayer, 0, MEDIA_INFO_PLAYBACK_COMPLETE, 0));
+                                mMediaPlayer, srcId, MEDIA_INFO_PLAYBACK_COMPLETE, 0));
                     }
                 }
                 stayAwake(false);
@@ -3163,7 +3160,7 @@
                 synchronized (mEventCbLock) {
                     for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) {
                         cb.first.execute(() -> cb.second.onBufferingUpdate(
-                                mMediaPlayer, 0, percent));
+                                mMediaPlayer, srcId, percent));
                     }
                 }
                 return;
@@ -3172,7 +3169,7 @@
                 synchronized (mEventCbLock) {
                     for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) {
                         cb.first.execute(() -> cb.second.onInfo(
-                                mMediaPlayer, 0, MEDIA_INFO_COMPLETE_CALL_SEEK, 0));
+                                mMediaPlayer, srcId, MEDIA_INFO_COMPLETE_CALL_SEEK, 0));
                     }
                 }
                 // fall through
@@ -3192,7 +3189,7 @@
                 synchronized (mEventCbLock) {
                     for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) {
                         cb.first.execute(() -> cb.second.onVideoSizeChanged(
-                                mMediaPlayer, 0, width, height));
+                                mMediaPlayer, srcId, width, height));
                     }
                 }
                 return;
@@ -3202,9 +3199,9 @@
                 synchronized (mEventCbLock) {
                     for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) {
                         cb.first.execute(() -> cb.second.onError(
-                                mMediaPlayer, 0, what, extra));
+                                mMediaPlayer, srcId, what, extra));
                         cb.first.execute(() -> cb.second.onInfo(
-                                mMediaPlayer, 0, MEDIA_INFO_PLAYBACK_COMPLETE, 0));
+                                mMediaPlayer, srcId, MEDIA_INFO_PLAYBACK_COMPLETE, 0));
                     }
                 }
                 stayAwake(false);
@@ -3247,7 +3244,7 @@
                 synchronized (mEventCbLock) {
                     for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) {
                         cb.first.execute(() -> cb.second.onInfo(
-                                mMediaPlayer, 0, what, extra));
+                                mMediaPlayer, srcId, what, extra));
                     }
                 }
                 // No real default action so far.
@@ -3272,7 +3269,7 @@
 
                 synchronized (mEventCbLock) {
                     for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) {
-                        cb.first.execute(() -> cb.second.onTimedText(mMediaPlayer, 0, text));
+                        cb.first.execute(() -> cb.second.onTimedText(mMediaPlayer, srcId, text));
                     }
                 }
                 return;
@@ -3303,7 +3300,7 @@
                 synchronized (mEventCbLock) {
                     for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) {
                         cb.first.execute(() -> cb.second.onTimedMetaDataAvailable(
-                                mMediaPlayer, 0, data));
+                                mMediaPlayer, srcId, data));
                     }
                 }
                 return;
@@ -3335,7 +3332,7 @@
      * code is safe from the object disappearing from underneath it.  (This is
      * the cookie passed to native_setup().)
      */
-    private static void postEventFromNative(Object mediaplayer2_ref,
+    private static void postEventFromNative(Object mediaplayer2_ref, long srcId,
                                             int what, int arg1, int arg2, Object obj)
     {
         final MediaPlayer2Impl mp = (MediaPlayer2Impl)((WeakReference)mediaplayer2_ref).get();
@@ -3388,7 +3385,13 @@
 
         if (mp.mEventHandler != null) {
             Message m = mp.mEventHandler.obtainMessage(what, arg1, arg2, obj);
-            mp.mEventHandler.sendMessage(m);
+
+            mp.mEventHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    mp.mEventHandler.handleMessage(m, srcId);
+                }
+            });
         }
     }
 
@@ -4217,6 +4220,65 @@
 
     }
 
+    // Called from the native side
+    @SuppressWarnings("unused")
+    private static boolean setAudioOutputDeviceById(AudioTrack track, int deviceId) {
+        if (track == null) {
+            return false;
+        }
+
+        if (deviceId == 0) {
+            // Use default routing.
+            track.setPreferredDevice(null);
+            return true;
+        }
+
+        // TODO: Unhide AudioManager.getDevicesStatic.
+        AudioDeviceInfo[] outputDevices =
+                AudioManager.getDevicesStatic(AudioManager.GET_DEVICES_OUTPUTS);
+
+        boolean success = false;
+        for (AudioDeviceInfo device : outputDevices) {
+            if (device.getId() == deviceId) {
+                track.setPreferredDevice(device);
+                success = true;
+                break;
+            }
+        }
+        return success;
+    }
+
+    // Instantiated from the native side
+    @SuppressWarnings("unused")
+    private static class StreamEventCallback extends AudioTrack.StreamEventCallback {
+        public long mJAudioTrackPtr;
+        public long mNativeCallbackPtr;
+        public long mUserDataPtr;
+
+        public StreamEventCallback(long jAudioTrackPtr, long nativeCallbackPtr, long userDataPtr) {
+            super();
+            mJAudioTrackPtr = jAudioTrackPtr;
+            mNativeCallbackPtr = nativeCallbackPtr;
+            mUserDataPtr = userDataPtr;
+        }
+
+        @Override
+        public void onTearDown(AudioTrack track) {
+            native_stream_event_onTearDown(mNativeCallbackPtr, mUserDataPtr);
+        }
+
+        @Override
+        public void onStreamPresentationEnd(AudioTrack track) {
+            native_stream_event_onStreamPresentationEnd(mNativeCallbackPtr, mUserDataPtr);
+        }
+
+        @Override
+        public void onStreamDataRequest(AudioTrack track) {
+            native_stream_event_onStreamDataRequest(
+                    mJAudioTrackPtr, mNativeCallbackPtr, mUserDataPtr);
+        }
+    }
+
     private class ProvisioningThread extends Thread {
         public static final int TIMEOUT_MS = 60000;
 
@@ -4490,7 +4552,7 @@
         // no need for log(N) search performance
         private MediaTimeProvider.OnMediaTimeListener mListeners[];
         private long mTimes[];
-        private Handler mEventHandler;
+        private EventHandler mEventHandler;
         private boolean mRefresh = false;
         private boolean mPausing = false;
         private boolean mSeeking = false;
diff --git a/media/java/android/media/update/MediaBrowser2Provider.java b/media/java/android/media/update/MediaBrowser2Provider.java
index 17256a8..f2e7313 100644
--- a/media/java/android/media/update/MediaBrowser2Provider.java
+++ b/media/java/android/media/update/MediaBrowser2Provider.java
@@ -16,7 +16,6 @@
 
 package android.media.update;
 
-import android.annotation.SystemApi;
 import android.os.Bundle;
 
 /**
@@ -29,6 +28,7 @@
     void unsubscribe_impl(String parentId, Bundle options);
 
     void getItem_impl(String mediaId);
-    void getChildren_impl(String parentId, int page, int pageSize, Bundle options);
-    void search_impl(String query, int page, int pageSize, Bundle extras);
+    void getChildren_impl(String parentId, int page, int pageSize, Bundle extras);
+    void search_impl(String query, Bundle options);
+    void getSearchResult_impl(String query, int page, int pageSize, Bundle extras);
 }
diff --git a/media/jni/android_media_MediaDrm.cpp b/media/jni/android_media_MediaDrm.cpp
index 4f06caa..3518392 100644
--- a/media/jni/android_media_MediaDrm.cpp
+++ b/media/jni/android_media_MediaDrm.cpp
@@ -20,7 +20,7 @@
 
 #include "android_media_MediaDrm.h"
 #include "android_media_MediaMetricsJNI.h"
-
+#include "android_os_Parcel.h"
 #include "android_runtime/AndroidRuntime.h"
 #include "android_runtime/Log.h"
 #include "android_os_Parcel.h"
@@ -29,12 +29,16 @@
 
 #include <binder/IServiceManager.h>
 #include <binder/Parcel.h>
+#include <binder/PersistableBundle.h>
 #include <cutils/properties.h>
 #include <media/IDrm.h>
 #include <media/IMediaDrmService.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/MediaErrors.h>
 
+using ::android::os::PersistableBundle;
+
+
 namespace android {
 
 #define FIND_CLASS(var, className) \
@@ -57,6 +61,10 @@
     var = env->GetStaticMethodID(clazz, fieldName, fieldDescriptor); \
     LOG_FATAL_IF(! (var), "Unable to find static method " fieldName);
 
+#define GET_STATIC_OBJECT_FIELD(var, clazz, fieldName) \
+    var = env->GetStaticObjectField(clazz, fieldName); \
+    LOG_FATAL_IF(! (var), "Unable to find static object field " fieldName);
+
 
 struct RequestFields {
     jfieldID data;
@@ -145,6 +153,7 @@
 
 struct SecurityLevels {
     jint kSecurityLevelUnknown;
+    jint kSecurityLevelMax;
     jint kSecurityLevelSwSecureCrypto;
     jint kSecurityLevelSwSecureDecode;
     jint kSecurityLevelHwSecureCrypto;
@@ -169,10 +178,58 @@
     jclass hashmapClassId;
     jclass arraylistClassId;
     jclass stringClassId;
+    jobject bundleCreator;
+    jmethodID createFromParcelId;
+    jclass parcelCreatorClassId;
 };
 
 static fields_t gFields;
 
+namespace {
+
+// Helper function to convert a native PersistableBundle to a Java
+// PersistableBundle.
+jobject nativeToJavaPersistableBundle(JNIEnv *env, jobject thiz,
+                                      PersistableBundle* nativeBundle) {
+    if (env == NULL || thiz == NULL || nativeBundle == NULL) {
+        ALOGE("Unexpected NULL parmeter");
+        return NULL;
+    }
+
+    // Create a Java parcel with the native parcel data.
+    // Then create a new PersistableBundle with that parcel as a parameter.
+    jobject jParcel = android::createJavaParcelObject(env);
+    if (jParcel == NULL) {
+      ALOGE("Failed to create a Java Parcel.");
+      return NULL;
+    }
+
+    android::Parcel* nativeParcel = android::parcelForJavaObject(env, jParcel);
+    if (nativeParcel == NULL) {
+      ALOGE("Failed to get the native Parcel.");
+      return NULL;
+    }
+
+    android::status_t result = nativeBundle->writeToParcel(nativeParcel);
+    nativeParcel->setDataPosition(0);
+    if (result != android::OK) {
+      ALOGE("Failed to write nativeBundle to Parcel: %d.", result);
+      return NULL;
+    }
+
+    jobject newBundle = env->CallObjectMethod(gFields.bundleCreator,
+                                              gFields.createFromParcelId,
+                                              jParcel);
+    if (newBundle == NULL) {
+        ALOGE("Failed to create a new PersistableBundle "
+              "from the createFromParcel call.");
+    }
+
+    return newBundle;
+}
+
+}  // namespace anonymous
+
 // ----------------------------------------------------------------------------
 // ref-counted object for callbacks
 class JNIDrmListener: public DrmListener
@@ -683,6 +740,10 @@
     GET_STATIC_FIELD_ID(field, clazz, "HW_SECURE_ALL", "I");
     gSecurityLevels.kSecurityLevelHwSecureAll = env->GetStaticIntField(clazz, field);
 
+    jmethodID getMaxSecurityLevel;
+    GET_STATIC_METHOD_ID(getMaxSecurityLevel, clazz, "getMaxSecurityLevel", "()I");
+    gSecurityLevels.kSecurityLevelMax = env->CallStaticIntMethod(clazz, getMaxSecurityLevel);
+
     FIND_CLASS(clazz, "android/media/MediaDrm$KeyRequest");
     GET_FIELD_ID(gFields.keyRequest.data, clazz, "mData", "[B");
     GET_FIELD_ID(gFields.keyRequest.defaultUrl, clazz, "mDefaultUrl", "Ljava/lang/String;");
@@ -708,6 +769,19 @@
     GET_FIELD_ID(gFields.certificate.certificateData, clazz, "mCertificateData", "[B");
     gFields.certificateClassId = static_cast<jclass>(env->NewGlobalRef(clazz));
 
+    // Metrics-related fields and classes.
+    FIND_CLASS(clazz, "android/os/PersistableBundle");
+    jfieldID bundleCreatorId;
+    GET_STATIC_FIELD_ID(bundleCreatorId, clazz, "CREATOR",
+                        "Landroid/os/Parcelable$Creator;");
+    jobject bundleCreator;
+    GET_STATIC_OBJECT_FIELD(bundleCreator, clazz, bundleCreatorId);
+    gFields.bundleCreator = static_cast<jobject>(env->NewGlobalRef(bundleCreator));
+    FIND_CLASS(clazz, "android/os/Parcelable$Creator");
+    GET_METHOD_ID(gFields.createFromParcelId, clazz, "createFromParcel",
+                  "(Landroid/os/Parcel;)Ljava/lang/Object;");
+    gFields.parcelCreatorClassId = static_cast<jclass>(env->NewGlobalRef(clazz));
+
     FIND_CLASS(clazz, "java/util/ArrayList");
     GET_METHOD_ID(gFields.arraylist.init, clazz, "<init>", "()V");
     GET_METHOD_ID(gFields.arraylist.add, clazz, "add", "(Ljava/lang/Object;)Z");
@@ -813,7 +887,7 @@
 }
 
 static jbyteArray android_media_MediaDrm_openSession(
-    JNIEnv *env, jobject thiz) {
+        JNIEnv *env, jobject thiz, jint jlevel) {
     sp<IDrm> drm = GetDrm(env, thiz);
 
     if (drm == NULL) {
@@ -823,7 +897,26 @@
     }
 
     Vector<uint8_t> sessionId;
-    status_t err = drm->openSession(sessionId);
+    DrmPlugin::SecurityLevel level;
+
+    if (jlevel == gSecurityLevels.kSecurityLevelMax) {
+        level = DrmPlugin::kSecurityLevelMax;
+    }  else if (jlevel == gSecurityLevels.kSecurityLevelSwSecureCrypto) {
+        level = DrmPlugin::kSecurityLevelSwSecureCrypto;
+    } else if (jlevel == gSecurityLevels.kSecurityLevelSwSecureDecode) {
+        level = DrmPlugin::kSecurityLevelSwSecureDecode;
+    } else if (jlevel == gSecurityLevels.kSecurityLevelHwSecureCrypto) {
+        level = DrmPlugin::kSecurityLevelHwSecureCrypto;
+    } else if (jlevel == gSecurityLevels.kSecurityLevelHwSecureDecode) {
+        level = DrmPlugin::kSecurityLevelHwSecureDecode;
+    } else if (jlevel == gSecurityLevels.kSecurityLevelHwSecureAll) {
+        level = DrmPlugin::kSecurityLevelHwSecureAll;
+    } else {
+        jniThrowException(env, "java/lang/IllegalArgumentException", "Invalid security level");
+        return NULL;
+    }
+
+    status_t err = drm->openSession(level, sessionId);
 
     if (throwExceptionAsNecessary(env, err, "Failed to open session")) {
         return NULL;
@@ -1345,40 +1438,6 @@
 }
 
 
-static void android_media_MediaDrm_setSecurityLevel(JNIEnv *env,
-        jobject thiz, jbyteArray jsessionId, jint jlevel) {
-    sp<IDrm> drm = GetDrm(env, thiz);
-
-    if (!CheckSession(env, drm, jsessionId)) {
-        return;
-    }
-
-    Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
-    DrmPlugin::SecurityLevel level;
-
-    if (jlevel == gSecurityLevels.kSecurityLevelSwSecureCrypto) {
-        level = DrmPlugin::kSecurityLevelSwSecureCrypto;
-    } else if (jlevel == gSecurityLevels.kSecurityLevelSwSecureDecode) {
-        level = DrmPlugin::kSecurityLevelSwSecureDecode;
-    } else if (jlevel == gSecurityLevels.kSecurityLevelHwSecureCrypto) {
-        level = DrmPlugin::kSecurityLevelHwSecureCrypto;
-    } else if (jlevel == gSecurityLevels.kSecurityLevelHwSecureDecode) {
-        level = DrmPlugin::kSecurityLevelHwSecureDecode;
-    } else if (jlevel == gSecurityLevels.kSecurityLevelHwSecureAll) {
-        level = DrmPlugin::kSecurityLevelHwSecureAll;
-    } else {
-        jniThrowException(env, "java/lang/IllegalArgumentException", "Invalid security level");
-        return;
-    }
-
-    status_t err = drm->setSecurityLevel(sessionId, level);
-
-    if (throwExceptionAsNecessary(env, err, "Failed to set security level")) {
-        return;
-    }
-}
-
-
 static jstring android_media_MediaDrm_getPropertyString(
     JNIEnv *env, jobject thiz, jstring jname) {
     sp<IDrm> drm = GetDrm(env, thiz);
@@ -1666,19 +1725,14 @@
     }
 
     // Retrieve current metrics snapshot from drm.
-    MediaAnalyticsItem item ;
-    status_t err = drm->getMetrics(&item);
+    PersistableBundle metrics;
+    status_t err = drm->getMetrics(&metrics);
     if (err != OK) {
         ALOGE("getMetrics failed: %d", (int)err);
         return (jobject) NULL;
     }
 
-    jobject mybundle = MediaMetricsJNI::writeMetricsToBundle(env, &item, NULL);
-    if (mybundle == NULL) {
-        ALOGE("getMetrics metric conversion failed");
-    }
-
-    return mybundle;
+    return nativeToJavaPersistableBundle(env, thiz, &metrics);
 }
 
 static jbyteArray android_media_MediaDrm_signRSANative(
@@ -1724,7 +1778,7 @@
     { "isCryptoSchemeSupportedNative", "([BLjava/lang/String;)Z",
       (void *)android_media_MediaDrm_isCryptoSchemeSupportedNative },
 
-    { "openSession", "()[B",
+    { "openSession", "(I)[B",
       (void *)android_media_MediaDrm_openSession },
 
     { "closeSession", "([B)V",
@@ -1785,9 +1839,6 @@
     { "getSecurityLevel", "([B)I",
       (void *)android_media_MediaDrm_getSecurityLevel },
 
-    { "setSecurityLevel", "([BI)V",
-      (void *)android_media_MediaDrm_setSecurityLevel },
-
     { "getPropertyString", "(Ljava/lang/String;)Ljava/lang/String;",
       (void *)android_media_MediaDrm_getPropertyString },
 
diff --git a/media/jni/android_media_MediaPlayer2.cpp b/media/jni/android_media_MediaPlayer2.cpp
index 0eb98f3..51bc330 100644
--- a/media/jni/android_media_MediaPlayer2.cpp
+++ b/media/jni/android_media_MediaPlayer2.cpp
@@ -28,6 +28,7 @@
 #include <media/NdkWrapper.h>
 #include <media/stagefright/Utils.h>
 #include <media/stagefright/foundation/ByteUtils.h>  // for FOURCC definition
+#include <mediaplayer2/JAudioTrack.h>
 #include <mediaplayer2/mediaplayer2.h>
 #include <stdio.h>
 #include <assert.h>
@@ -154,7 +155,8 @@
 public:
     JNIMediaPlayer2Listener(JNIEnv* env, jobject thiz, jobject weak_thiz);
     ~JNIMediaPlayer2Listener();
-    virtual void notify(int msg, int ext1, int ext2, const Parcel *obj = NULL);
+    virtual void notify(int64_t srcId, int msg, int ext1, int ext2,
+                        const Parcel *obj = NULL) override;
 private:
     JNIMediaPlayer2Listener();
     jclass      mClass;     // Reference to MediaPlayer2 class
@@ -187,7 +189,7 @@
     env->DeleteGlobalRef(mClass);
 }
 
-void JNIMediaPlayer2Listener::notify(int msg, int ext1, int ext2, const Parcel *obj)
+void JNIMediaPlayer2Listener::notify(int64_t srcId, int msg, int ext1, int ext2, const Parcel *obj)
 {
     JNIEnv *env = AndroidRuntime::getJNIEnv();
     if (obj && obj->dataSize() > 0) {
@@ -196,12 +198,12 @@
             Parcel* nativeParcel = parcelForJavaObject(env, jParcel);
             nativeParcel->setData(obj->data(), obj->dataSize());
             env->CallStaticVoidMethod(mClass, fields.post_event, mObject,
-                    msg, ext1, ext2, jParcel);
+                    srcId, msg, ext1, ext2, jParcel);
             env->DeleteLocalRef(jParcel);
         }
     } else {
         env->CallStaticVoidMethod(mClass, fields.post_event, mObject,
-                msg, ext1, ext2, NULL);
+                srcId, msg, ext1, ext2, NULL);
     }
     if (env->ExceptionCheck()) {
         ALOGW("An exception occurred while notifying an event.");
@@ -243,7 +245,11 @@
     if (exception == NULL) {  // Don't throw exception. Instead, send an event.
         if (opStatus != (status_t) OK) {
             sp<MediaPlayer2> mp = getMediaPlayer(env, thiz);
-            if (mp != 0) mp->notify(MEDIA2_ERROR, opStatus, 0);
+            if (mp != 0) {
+                int64_t srcId = 0;
+                mp->getSrcId(&srcId);
+                mp->notify(srcId, MEDIA2_ERROR, opStatus, 0);
+            }
         }
     } else {  // Throw exception!
         if ( opStatus == (status_t) INVALID_OPERATION ) {
@@ -268,7 +274,7 @@
 
 static void
 android_media_MediaPlayer2_setDataSourceAndHeaders(
-        JNIEnv *env, jobject thiz, jobject httpServiceObj, jstring path,
+        JNIEnv *env, jobject thiz, jlong srcId, jobject httpServiceObj, jstring path,
         jobjectArray keys, jobjectArray values) {
 
     sp<MediaPlayer2> mp = getMediaPlayer(env, thiz);
@@ -286,7 +292,7 @@
     if (tmp == NULL) {  // Out of memory
         return;
     }
-    ALOGV("setDataSourceAndHeaders: path %s", tmp);
+    ALOGV("setDataSourceAndHeaders: path %s, srcId %lld", tmp, (long long)srcId);
 
     if (strncmp(tmp, "content://", 10) == 0) {
         ALOGE("setDataSourceAndHeaders: content scheme is not supported in native code");
@@ -296,6 +302,7 @@
     }
 
     sp<DataSourceDesc> dsd = new DataSourceDesc();
+    dsd->mId = srcId;
     dsd->mType = DataSourceDesc::TYPE_URL;
     dsd->mUrl = tmp;
 
@@ -321,7 +328,7 @@
 
 static void
 android_media_MediaPlayer2_setDataSourceFD(
-    JNIEnv *env, jobject thiz, jobject fileDescriptor, jlong offset, jlong length)
+    JNIEnv *env, jobject thiz, jlong srcId, jobject fileDescriptor, jlong offset, jlong length)
 {
     sp<MediaPlayer2> mp = getMediaPlayer(env, thiz);
     if (mp == NULL ) {
@@ -334,8 +341,8 @@
         return;
     }
     int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
-    ALOGV("setDataSourceFD: fd=%d (%s), offset=%lld, length=%lld",
-          fd, nameForFd(fd).c_str(), (long long)offset, (long long)length);
+    ALOGV("setDataSourceFD: srcId=%lld, fd=%d (%s), offset=%lld, length=%lld",
+          (long long)srcId, fd, nameForFd(fd).c_str(), (long long)offset, (long long)length);
 
     struct stat sb;
     int ret = fstat(fd, &sb);
@@ -363,6 +370,7 @@
     }
 
     sp<DataSourceDesc> dsd = new DataSourceDesc();
+    dsd->mId = srcId;
     dsd->mType = DataSourceDesc::TYPE_FD;
     dsd->mFD = fd;
     dsd->mFDOffset = offset;
@@ -373,7 +381,7 @@
 
 static void
 android_media_MediaPlayer2_setDataSourceCallback(
-    JNIEnv *env, jobject thiz, jobject dataSource)
+    JNIEnv *env, jobject thiz, jlong srcId, jobject dataSource)
 {
     sp<MediaPlayer2> mp = getMediaPlayer(env, thiz);
     if (mp == NULL ) {
@@ -387,6 +395,7 @@
     }
     sp<DataSource> callbackDataSource = new JMedia2DataSource(env, dataSource);
     sp<DataSourceDesc> dsd = new DataSourceDesc();
+    dsd->mId = srcId;
     dsd->mType = DataSourceDesc::TYPE_CALLBACK;
     dsd->mCallbackSource = callbackDataSource;
     process_media_player_call(env, thiz, mp->setDataSource(dsd),
@@ -1012,7 +1021,7 @@
     }
 
     fields.post_event = env->GetStaticMethodID(clazz, "postEventFromNative",
-                                               "(Ljava/lang/Object;IIILjava/lang/Object;)V");
+                                               "(Ljava/lang/Object;JIIILjava/lang/Object;)V");
     if (fields.post_event == NULL) {
         return;
     }
@@ -1379,16 +1388,75 @@
 // AudioRouting end
 // ----------------------------------------------------------------------------
 
+/////////////////////////////////////////////////////////////////////////////////////
+// AudioTrack.StreamEventCallback begin
+static void android_media_MediaPlayer2_native_on_tear_down(JNIEnv *env __unused,
+        jobject thiz __unused, jlong callbackPtr, jlong userDataPtr)
+{
+    JAudioTrack::callback_t callback = (JAudioTrack::callback_t) callbackPtr;
+    if (callback != NULL) {
+        callback(JAudioTrack::EVENT_NEW_IAUDIOTRACK, (void *) userDataPtr, NULL);
+    }
+}
+
+static void android_media_MediaPlayer2_native_on_stream_presentation_end(JNIEnv *env __unused,
+        jobject thiz __unused, jlong callbackPtr, jlong userDataPtr)
+{
+    JAudioTrack::callback_t callback = (JAudioTrack::callback_t) callbackPtr;
+    if (callback != NULL) {
+        callback(JAudioTrack::EVENT_STREAM_END, (void *) userDataPtr, NULL);
+    }
+}
+
+static void android_media_MediaPlayer2_native_on_stream_data_request(JNIEnv *env __unused,
+        jobject thiz __unused, jlong jAudioTrackPtr, jlong callbackPtr, jlong userDataPtr)
+{
+    JAudioTrack::callback_t callback = (JAudioTrack::callback_t) callbackPtr;
+    JAudioTrack* track = (JAudioTrack *) jAudioTrackPtr;
+    if (callback != NULL && track != NULL) {
+        JAudioTrack::Buffer* buffer = new JAudioTrack::Buffer();
+
+        size_t bufferSizeInFrames = track->frameCount();
+        audio_format_t format = track->format();
+
+        size_t bufferSizeInBytes;
+        if (audio_has_proportional_frames(format)) {
+            bufferSizeInBytes =
+                    bufferSizeInFrames * audio_bytes_per_sample(format) * track->channelCount();
+        } else {
+            // See Javadoc of AudioTrack::getBufferSizeInFrames().
+            bufferSizeInBytes = bufferSizeInFrames;
+        }
+
+        uint8_t* byteBuffer = new uint8_t[bufferSizeInBytes];
+        buffer->mSize = bufferSizeInBytes;
+        buffer->mData = (void *) byteBuffer;
+
+        callback(JAudioTrack::EVENT_MORE_DATA, (void *) userDataPtr, buffer);
+
+        if (buffer->mSize > 0 && buffer->mData == byteBuffer) {
+            track->write(buffer->mData, buffer->mSize, true /* Blocking */);
+        }
+
+        delete[] byteBuffer;
+        delete buffer;
+    }
+}
+
+
+// AudioTrack.StreamEventCallback end
+// ----------------------------------------------------------------------------
+
 static const JNINativeMethod gMethods[] = {
     {
         "nativeSetDataSource",
-        "(Landroid/media/Media2HTTPService;Ljava/lang/String;[Ljava/lang/String;"
+        "(JLandroid/media/Media2HTTPService;Ljava/lang/String;[Ljava/lang/String;"
         "[Ljava/lang/String;)V",
         (void *)android_media_MediaPlayer2_setDataSourceAndHeaders
     },
 
-    {"_setDataSource",      "(Ljava/io/FileDescriptor;JJ)V",    (void *)android_media_MediaPlayer2_setDataSourceFD},
-    {"_setDataSource",      "(Landroid/media/Media2DataSource;)V",(void *)android_media_MediaPlayer2_setDataSourceCallback },
+    {"_setDataSource",      "(JLjava/io/FileDescriptor;JJ)V",    (void *)android_media_MediaPlayer2_setDataSourceFD},
+    {"_setDataSource",      "(JLandroid/media/Media2DataSource;)V",(void *)android_media_MediaPlayer2_setDataSourceCallback },
     {"_setVideoSurface",    "(Landroid/view/Surface;)V",        (void *)android_media_MediaPlayer2_setVideoSurface},
     {"getBufferingParams", "()Landroid/media/BufferingParams;", (void *)android_media_MediaPlayer2_getBufferingParams},
     {"setBufferingParams", "(Landroid/media/BufferingParams;)V", (void *)android_media_MediaPlayer2_setBufferingParams},
@@ -1435,6 +1503,11 @@
     {"native_setOutputDevice", "(I)Z",                          (void *)android_media_MediaPlayer2_setOutputDevice},
     {"native_getRoutedDeviceId", "()I",                         (void *)android_media_MediaPlayer2_getRoutedDeviceId},
     {"native_enableDeviceCallback", "(Z)V",                     (void *)android_media_MediaPlayer2_enableDeviceCallback},
+
+    // StreamEventCallback for JAudioTrack
+    {"native_stream_event_onTearDown",                "(JJ)V",  (void *)android_media_MediaPlayer2_native_on_tear_down},
+    {"native_stream_event_onStreamPresentationEnd",   "(JJ)V",  (void *)android_media_MediaPlayer2_native_on_stream_presentation_end},
+    {"native_stream_event_onStreamDataRequest",       "(JJJ)V", (void *)android_media_MediaPlayer2_native_on_stream_data_request},
 };
 
 // This function only registers the native methods
diff --git a/native/android/asset_manager.cpp b/native/android/asset_manager.cpp
index e70d5ea..98e9a42 100644
--- a/native/android/asset_manager.cpp
+++ b/native/android/asset_manager.cpp
@@ -18,11 +18,9 @@
 #include <utils/Log.h>
 
 #include <android/asset_manager_jni.h>
-#include <android_runtime/android_util_AssetManager.h>
 #include <androidfw/Asset.h>
 #include <androidfw/AssetDir.h>
 #include <androidfw/AssetManager.h>
-#include <androidfw/AssetManager2.h>
 #include <utils/threads.h>
 
 #include "jni.h"
@@ -37,20 +35,21 @@
 
 // -----
 struct AAssetDir {
-    std::unique_ptr<AssetDir> mAssetDir;
+    AssetDir* mAssetDir;
     size_t mCurFileIndex;
     String8 mCachedFileName;
 
-    explicit AAssetDir(std::unique_ptr<AssetDir> dir) :
-        mAssetDir(std::move(dir)), mCurFileIndex(0) { }
+    explicit AAssetDir(AssetDir* dir) : mAssetDir(dir), mCurFileIndex(0) { }
+    ~AAssetDir() { delete mAssetDir; }
 };
 
 
 // -----
 struct AAsset {
-    std::unique_ptr<Asset> mAsset;
+    Asset* mAsset;
 
-    explicit AAsset(std::unique_ptr<Asset> asset) : mAsset(std::move(asset)) { }
+    explicit AAsset(Asset* asset) : mAsset(asset) { }
+    ~AAsset() { delete mAsset; }
 };
 
 // -------------------- Public native C API --------------------
@@ -105,18 +104,19 @@
         return NULL;
     }
 
-    ScopedLock<AssetManager2> locked_mgr(*AssetManagerForNdkAssetManager(amgr));
-    std::unique_ptr<Asset> asset = locked_mgr->Open(filename, amMode);
-    if (asset == nullptr) {
-        return nullptr;
+    AssetManager* mgr = static_cast<AssetManager*>(amgr);
+    Asset* asset = mgr->open(filename, amMode);
+    if (asset == NULL) {
+        return NULL;
     }
-    return new AAsset(std::move(asset));
+
+    return new AAsset(asset);
 }
 
 AAssetDir* AAssetManager_openDir(AAssetManager* amgr, const char* dirName)
 {
-    ScopedLock<AssetManager2> locked_mgr(*AssetManagerForNdkAssetManager(amgr));
-    return new AAssetDir(locked_mgr->OpenDir(dirName));
+    AssetManager* mgr = static_cast<AssetManager*>(amgr);
+    return new AAssetDir(mgr->openDir(dirName));
 }
 
 /**
diff --git a/native/android/configuration.cpp b/native/android/configuration.cpp
index 87fe9ed..77237ae 100644
--- a/native/android/configuration.cpp
+++ b/native/android/configuration.cpp
@@ -17,10 +17,9 @@
 #define LOG_TAG "Configuration"
 #include <utils/Log.h>
 
-#include <androidfw/AssetManager2.h>
+#include <androidfw/AssetManager.h>
 
 #include <android_runtime/android_content_res_Configuration.h>
-#include <android_runtime/android_util_AssetManager.h>
 
 using namespace android;
 
@@ -35,11 +34,7 @@
 }
 
 void AConfiguration_fromAssetManager(AConfiguration* out, AAssetManager* am) {
-    ScopedLock<AssetManager2> locked_mgr(*AssetManagerForNdkAssetManager(am));
-    ResTable_config config = locked_mgr->GetConfiguration();
-
-    // AConfiguration is not a virtual subclass, so we can memcpy.
-    memcpy(out, &config, sizeof(config));
+    ((AssetManager*)am)->getConfiguration(out);
 }
 
 void AConfiguration_copy(AConfiguration* dest, AConfiguration* src) {
diff --git a/packages/CtsShim/Android.mk b/packages/CtsShim/Android.mk
index 88b85e0..12972f1 100644
--- a/packages/CtsShim/Android.mk
+++ b/packages/CtsShim/Android.mk
@@ -32,9 +32,10 @@
 LOCAL_DEX_PREOPT := false
 LOCAL_MODULE_TARGET_ARCH := arm arm64 x86 x86_64
 
-my_archs := arm x86
-my_src_arch := $(call get-prebuilt-src-arch, $(my_archs))
-LOCAL_SRC_FILES := apk/$(my_src_arch)/CtsShimPriv.apk
+LOCAL_SRC_FILES_arm := apk/arm/CtsShimPriv.apk
+LOCAL_SRC_FILES_arm64 := apk/arm/CtsShimPriv.apk
+LOCAL_SRC_FILES_x86 := apk/x86/CtsShimPriv.apk
+LOCAL_SRC_FILES_x86_64 := apk/x86/CtsShimPriv.apk
 
 include $(BUILD_PREBUILT)
 
@@ -53,9 +54,10 @@
 LOCAL_DEX_PREOPT := false
 LOCAL_MODULE_TARGET_ARCH := arm arm64 x86 x86_64
 
-my_archs := arm x86
-my_src_arch := $(call get-prebuilt-src-arch, $(my_archs))
-LOCAL_SRC_FILES := apk/$(my_src_arch)/CtsShim.apk
+LOCAL_SRC_FILES_arm := apk/arm/CtsShim.apk
+LOCAL_SRC_FILES_arm64 := apk/arm/CtsShim.apk
+LOCAL_SRC_FILES_x86 := apk/x86/CtsShim.apk
+LOCAL_SRC_FILES_x86_64 := apk/x86/CtsShim.apk
 
 include $(BUILD_PREBUILT)
 
diff --git a/packages/MtpDocumentsProvider/AndroidManifest.xml b/packages/MtpDocumentsProvider/AndroidManifest.xml
index c0a59b3..8d79f62 100644
--- a/packages/MtpDocumentsProvider/AndroidManifest.xml
+++ b/packages/MtpDocumentsProvider/AndroidManifest.xml
@@ -3,7 +3,6 @@
           package="com.android.mtp"
           android:sharedUserId="android.media">
     <uses-feature android:name="android.hardware.usb.host" />
-    <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
     <uses-permission android:name="android.permission.MANAGE_USB" />
     <application android:label="@string/app_label">
         <provider
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index fa6006e..dda6799 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -53,16 +53,25 @@
     <string name="bluetooth_disconnected" msgid="6557104142667339895">"Déconnecté"</string>
     <string name="bluetooth_disconnecting" msgid="8913264760027764974">"Déconnexion…"</string>
     <string name="bluetooth_connecting" msgid="8555009514614320497">"Connexion en cours…"</string>
-    <string name="bluetooth_connected" msgid="6038755206916626419">"Connecté"</string>
+    <!-- no translation found for bluetooth_connected (5427152882755735944) -->
+    <skip />
     <string name="bluetooth_pairing" msgid="1426882272690346242">"Association…"</string>
-    <string name="bluetooth_connected_no_headset" msgid="2866994875046035609">"Connecté (sans audio pour appels tél.)"</string>
-    <string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Connecté (sans audio contenu mutimédia)"</string>
-    <string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Connecté (sans accès aux messages)"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Connecté (sans audio tel./multimédia)"</string>
-    <string name="bluetooth_connected_battery_level" msgid="7049181126136692368">"Connecté. Pile : <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_headset_battery_level" msgid="5504193961248406027">"Connecté (sans téléphone). Pile : <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="4751724026365870779">"Connecté (sans média). Pile : <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1549265779323455261">"Connecté (sans téléphone ni média). Pile : <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_connected_no_headset (616068069034994802) -->
+    <skip />
+    <!-- no translation found for bluetooth_connected_no_a2dp (3736431800395923868) -->
+    <skip />
+    <!-- no translation found for bluetooth_connected_no_map (3200033913678466453) -->
+    <skip />
+    <!-- no translation found for bluetooth_connected_no_headset_no_a2dp (2047403011284187056) -->
+    <skip />
+    <!-- no translation found for bluetooth_connected_battery_level (5162924691231307748) -->
+    <skip />
+    <!-- no translation found for bluetooth_connected_no_headset_battery_level (1610296229139400266) -->
+    <skip />
+    <!-- no translation found for bluetooth_connected_no_a2dp_battery_level (3908466636369853652) -->
+    <skip />
+    <!-- no translation found for bluetooth_connected_no_headset_no_a2dp_battery_level (1163440823807659316) -->
+    <skip />
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Paramètres audio du support"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"Appels téléphoniques"</string>
     <string name="bluetooth_profile_opp" msgid="9168139293654233697">"Transfert de fichier"</string>
@@ -327,9 +336,12 @@
     <item msgid="8280754435979370728">"Couleurs naturelles, comme l\'œil les voit"</item>
     <item msgid="5363960654009010371">"Couleurs optimisées pour le contenu numérique"</item>
   </string-array>
-    <string name="inactive_apps_title" msgid="1317817863508274533">"Applications inactives"</string>
+    <!-- no translation found for inactive_apps_title (9042996804461901648) -->
+    <skip />
     <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"Application inactive. Touchez ici pour l\'activer."</string>
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"Application active. Touchez ici pour la désactiver."</string>
+    <!-- no translation found for standby_bucket_summary (6567835350910684727) -->
+    <skip />
     <string name="runningservices_settings_title" msgid="8097287939865165213">"Services en cours d\'exécution"</string>
     <string name="runningservices_settings_summary" msgid="854608995821032748">"Afficher et contrôler les services en cours d\'exécution"</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"Mise en œuvre WebView"</string>
@@ -351,16 +363,34 @@
     <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Correction des couleurs"</string>
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Cette fonctionnalité est expérimentale et peut affecter les performances."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Remplacé par <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only" msgid="845431008899029842">"Il reste environ <xliff:g id="TIME">^1</xliff:g>"</string>
-    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Il reste environ <xliff:g id="TIME">^1</xliff:g> en fonction de votre usage"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">^1</xliff:g> jusqu\'à la charge complète"</string>
-    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Temps restant : <xliff:g id="TIME">^1</xliff:g>"</string>
-    <string name="power_remaining_duration_only_short_enhanced" msgid="7450425624026394823">"Il reste <xliff:g id="TIME">^1</xliff:g> en fonction de votre usage"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">^1</xliff:g> : il reste environ <xliff:g id="TIME">^2</xliff:g>"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">^1</xliff:g> : il reste environ <xliff:g id="TIME">^2</xliff:g> en fonction de votre usage"</string>
-    <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> – Temps restant : <xliff:g id="TIME">^2</xliff:g>"</string>
+    <string name="power_remaining_duration_only" msgid="845431008899029842">"Il reste environ <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Il reste environ <xliff:g id="TIME">%1$s</xliff:g> en fonction de votre usage"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> jusqu\'à la charge complète"</string>
+    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Temps restant : <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_remaining_less_than_duration_only (5996752448813295329) -->
+    <skip />
+    <!-- no translation found for power_remaining_less_than_duration (7967078125657859046) -->
+    <skip />
+    <!-- no translation found for power_remaining_more_than_subtext (6846716609975752316) -->
+    <skip />
+    <!-- no translation found for power_remaining_only_more_than_subtext (8884488700395194194) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (8168317165722752881) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (5957064378548718872) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (9055596817716471373) -->
+    <skip />
+    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> : il reste environ <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> : il reste environ <xliff:g id="TIME">%2$s</xliff:g> en fonction de votre usage"</string>
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7679005631124015335) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (261050880878965621) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (2020049829798578618) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">^1</xliff:g> : <xliff:g id="TIME">^2</xliff:g> jusqu\'à la charge complète"</string>
+    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> : <xliff:g id="TIME">%2$s</xliff:g> jusqu\'à la charge complète"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Inconnu"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Charge en cours…"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"en cours de charge"</string>
@@ -414,4 +444,12 @@
     <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"Jamais"</string>
     <string name="zen_interruption_level_priority" msgid="2078370238113347720">"Priorités seulement"</string>
     <string name="zen_mode_and_condition" msgid="4927230238450354412">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
+    <!-- no translation found for zen_alarm_warning_indef (3007988140196673193) -->
+    <skip />
+    <!-- no translation found for zen_alarm_warning (6236690803924413088) -->
+    <skip />
+    <!-- no translation found for alarm_template (4996153414057676512) -->
+    <skip />
+    <!-- no translation found for alarm_template_far (3779172822607461675) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml
index 48c7bec..a1cdb8c 100644
--- a/packages/SettingsLib/res/values-mk/strings.xml
+++ b/packages/SettingsLib/res/values-mk/strings.xml
@@ -53,16 +53,25 @@
     <string name="bluetooth_disconnected" msgid="6557104142667339895">"Исклучено"</string>
     <string name="bluetooth_disconnecting" msgid="8913264760027764974">"Се исклучува..."</string>
     <string name="bluetooth_connecting" msgid="8555009514614320497">"Се поврзува..."</string>
-    <string name="bluetooth_connected" msgid="6038755206916626419">"Поврзани"</string>
+    <!-- no translation found for bluetooth_connected (5427152882755735944) -->
+    <skip />
     <string name="bluetooth_pairing" msgid="1426882272690346242">"Поврзување..."</string>
-    <string name="bluetooth_connected_no_headset" msgid="2866994875046035609">"Поврзани (без телефон)"</string>
-    <string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Поврзани (без медиуми)"</string>
-    <string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Поврзано (без порака за пристап)"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Поврзан (без телефон или медиуми)"</string>
-    <string name="bluetooth_connected_battery_level" msgid="7049181126136692368">"Поврзан, ниво на батеријата <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_headset_battery_level" msgid="5504193961248406027">"Поврзан (освен телефонот), ниво на батеријата <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="4751724026365870779">"Поврзан (освен аудио-визуелните содржини), ниво на батеријата <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1549265779323455261">"Поврзан (освен телефонот и аудио-визуелните содржини), ниво на батеријата <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_connected_no_headset (616068069034994802) -->
+    <skip />
+    <!-- no translation found for bluetooth_connected_no_a2dp (3736431800395923868) -->
+    <skip />
+    <!-- no translation found for bluetooth_connected_no_map (3200033913678466453) -->
+    <skip />
+    <!-- no translation found for bluetooth_connected_no_headset_no_a2dp (2047403011284187056) -->
+    <skip />
+    <!-- no translation found for bluetooth_connected_battery_level (5162924691231307748) -->
+    <skip />
+    <!-- no translation found for bluetooth_connected_no_headset_battery_level (1610296229139400266) -->
+    <skip />
+    <!-- no translation found for bluetooth_connected_no_a2dp_battery_level (3908466636369853652) -->
+    <skip />
+    <!-- no translation found for bluetooth_connected_no_headset_no_a2dp_battery_level (1163440823807659316) -->
+    <skip />
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Аудио на медиуми"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"Телефонски повици"</string>
     <string name="bluetooth_profile_opp" msgid="9168139293654233697">"Пренос на датотека"</string>
@@ -327,9 +336,12 @@
     <item msgid="8280754435979370728">"Природни бои како што со гледаат со голо око"</item>
     <item msgid="5363960654009010371">"Оптимизирани бои за дигитална содржина"</item>
   </string-array>
-    <string name="inactive_apps_title" msgid="1317817863508274533">"Неактивни апликации"</string>
+    <!-- no translation found for inactive_apps_title (9042996804461901648) -->
+    <skip />
     <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"Неактивно. Допрете за да смените."</string>
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"Активно. Допрете за да смените."</string>
+    <!-- no translation found for standby_bucket_summary (6567835350910684727) -->
+    <skip />
     <string name="runningservices_settings_title" msgid="8097287939865165213">"Активни услуги"</string>
     <string name="runningservices_settings_summary" msgid="854608995821032748">"Погледнете и контролирајте услуги што се моментално активни"</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"Воведување WebView"</string>
@@ -351,16 +363,34 @@
     <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Корекција на боја"</string>
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Функцијата е експериментална и може да влијае на изведбата."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Прескокнато според <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only" msgid="845431008899029842">"Преостануваат околу <xliff:g id="TIME">^1</xliff:g>"</string>
-    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Уште околу <xliff:g id="TIME">^1</xliff:g> според користењето"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Преостануваат <xliff:g id="TIME">^1</xliff:g> дури се наполни целосно"</string>
-    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"уште <xliff:g id="TIME">^1</xliff:g>"</string>
-    <string name="power_remaining_duration_only_short_enhanced" msgid="7450425624026394823">"Уште <xliff:g id="TIME">^1</xliff:g> според користењето"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">^1</xliff:g> - уште околу <xliff:g id="TIME">^2</xliff:g>"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">^1</xliff:g> - уште околу <xliff:g id="TIME">^2</xliff:g> според користењето"</string>
-    <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> - уште <xliff:g id="TIME">^2</xliff:g>"</string>
+    <string name="power_remaining_duration_only" msgid="845431008899029842">"Преостануваат околу <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Уште околу <xliff:g id="TIME">%1$s</xliff:g> според користењето"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Преостануваат <xliff:g id="TIME">%1$s</xliff:g> дури се наполни целосно"</string>
+    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"уште <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_remaining_less_than_duration_only (5996752448813295329) -->
+    <skip />
+    <!-- no translation found for power_remaining_less_than_duration (7967078125657859046) -->
+    <skip />
+    <!-- no translation found for power_remaining_more_than_subtext (6846716609975752316) -->
+    <skip />
+    <!-- no translation found for power_remaining_only_more_than_subtext (8884488700395194194) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (8168317165722752881) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (5957064378548718872) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (9055596817716471373) -->
+    <skip />
+    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> - уште околу <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> - уште околу <xliff:g id="TIME">%2$s</xliff:g> според користењето"</string>
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7679005631124015335) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (261050880878965621) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (2020049829798578618) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g> дури се наполни целосно"</string>
+    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> дури се наполни целосно"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Непознато"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Се полни"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"се полни"</string>
@@ -414,4 +444,12 @@
     <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"Никогаш"</string>
     <string name="zen_interruption_level_priority" msgid="2078370238113347720">"Само приоритетно"</string>
     <string name="zen_mode_and_condition" msgid="4927230238450354412">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
+    <!-- no translation found for zen_alarm_warning_indef (3007988140196673193) -->
+    <skip />
+    <!-- no translation found for zen_alarm_warning (6236690803924413088) -->
+    <skip />
+    <!-- no translation found for alarm_template (4996153414057676512) -->
+    <skip />
+    <!-- no translation found for alarm_template_far (3779172822607461675) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml
index 0a65c13..ecb73f0 100644
--- a/packages/SettingsLib/res/values-uz/strings.xml
+++ b/packages/SettingsLib/res/values-uz/strings.xml
@@ -53,16 +53,25 @@
     <string name="bluetooth_disconnected" msgid="6557104142667339895">"Uzildi"</string>
     <string name="bluetooth_disconnecting" msgid="8913264760027764974">"Uzilyapti…"</string>
     <string name="bluetooth_connecting" msgid="8555009514614320497">"Ulanmoqda…"</string>
-    <string name="bluetooth_connected" msgid="6038755206916626419">"Ulandi"</string>
+    <!-- no translation found for bluetooth_connected (5427152882755735944) -->
+    <skip />
     <string name="bluetooth_pairing" msgid="1426882272690346242">"Biriktirilmoqda"</string>
-    <string name="bluetooth_connected_no_headset" msgid="2866994875046035609">"Ulandi (telefondan tashqari)"</string>
-    <string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Ulanildi (mediadan tashqari)"</string>
-    <string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Ulangan (xabarlarga kirib bo‘lmaydi)"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Ulangan (telefon yoki media qurilma emas)"</string>
-    <string name="bluetooth_connected_battery_level" msgid="7049181126136692368">"Ulangan, batareya quvvati: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_headset_battery_level" msgid="5504193961248406027">"Ulangan (HSP/HFP dan tashqari), batareya quvvati: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="4751724026365870779">"Ulangan (A2DP dan tashqari), batareya quvvati: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1549265779323455261">"Ulangan (HSP/HFP/A2DP dan tashqari), batareya quvvati: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_connected_no_headset (616068069034994802) -->
+    <skip />
+    <!-- no translation found for bluetooth_connected_no_a2dp (3736431800395923868) -->
+    <skip />
+    <!-- no translation found for bluetooth_connected_no_map (3200033913678466453) -->
+    <skip />
+    <!-- no translation found for bluetooth_connected_no_headset_no_a2dp (2047403011284187056) -->
+    <skip />
+    <!-- no translation found for bluetooth_connected_battery_level (5162924691231307748) -->
+    <skip />
+    <!-- no translation found for bluetooth_connected_no_headset_battery_level (1610296229139400266) -->
+    <skip />
+    <!-- no translation found for bluetooth_connected_no_a2dp_battery_level (3908466636369853652) -->
+    <skip />
+    <!-- no translation found for bluetooth_connected_no_headset_no_a2dp_battery_level (1163440823807659316) -->
+    <skip />
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Media audio"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"Telefon chaqiruvlari"</string>
     <string name="bluetooth_profile_opp" msgid="9168139293654233697">"Fayl uzatish"</string>
@@ -327,9 +336,12 @@
     <item msgid="8280754435979370728">"Ko‘zga ko‘rinadigan tabiiy ranglar"</item>
     <item msgid="5363960654009010371">"Raqamli kontentga moslashtirilgan ranglar"</item>
   </string-array>
-    <string name="inactive_apps_title" msgid="1317817863508274533">"Nofaol ilovalar"</string>
+    <!-- no translation found for inactive_apps_title (9042996804461901648) -->
+    <skip />
     <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"Nofaol. O‘zgartirish uchun bu yerga bosing."</string>
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"Faol. O‘zgartirish uchun bu yerga bosing."</string>
+    <!-- no translation found for standby_bucket_summary (6567835350910684727) -->
+    <skip />
     <string name="runningservices_settings_title" msgid="8097287939865165213">"Ishlab turgan ilovalar"</string>
     <string name="runningservices_settings_summary" msgid="854608995821032748">"Ishlab turgan ilovalarni ko‘rish va boshqarish"</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView ta’minotchisi"</string>
@@ -351,16 +363,34 @@
     <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Rangni tuzatish"</string>
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Bu funksiya tajribaviy bo‘lib, u qurilma unumdorligiga ta’sir qilishi mumkin."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> bilan almashtirildi"</string>
-    <string name="power_remaining_duration_only" msgid="845431008899029842">"Taxminan <xliff:g id="TIME">^1</xliff:g> qoldi"</string>
-    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Joriy holatda taxminan <xliff:g id="TIME">^1</xliff:g> qoldi"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"To‘lishiga <xliff:g id="TIME">^1</xliff:g> qoldi"</string>
-    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">^1</xliff:g> qoldi"</string>
-    <string name="power_remaining_duration_only_short_enhanced" msgid="7450425624026394823">"Joriy holatda <xliff:g id="TIME">^1</xliff:g> qoldi"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">^1</xliff:g> – taxminan <xliff:g id="TIME">^2</xliff:g> qoldi"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">^1</xliff:g> (joriy holatda taxminan <xliff:g id="TIME">^2</xliff:g> qoldi)"</string>
-    <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> – <xliff:g id="TIME">^2</xliff:g> qoldi"</string>
+    <string name="power_remaining_duration_only" msgid="845431008899029842">"Taxminan <xliff:g id="TIME">%1$s</xliff:g> qoldi"</string>
+    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Joriy holatda taxminan <xliff:g id="TIME">%1$s</xliff:g> qoldi"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"To‘lishiga <xliff:g id="TIME">%1$s</xliff:g> qoldi"</string>
+    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">%1$s</xliff:g> qoldi"</string>
+    <!-- no translation found for power_remaining_less_than_duration_only (5996752448813295329) -->
+    <skip />
+    <!-- no translation found for power_remaining_less_than_duration (7967078125657859046) -->
+    <skip />
+    <!-- no translation found for power_remaining_more_than_subtext (6846716609975752316) -->
+    <skip />
+    <!-- no translation found for power_remaining_only_more_than_subtext (8884488700395194194) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (8168317165722752881) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (5957064378548718872) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (9055596817716471373) -->
+    <skip />
+    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> – taxminan <xliff:g id="TIME">%2$s</xliff:g> qoldi"</string>
+    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> (joriy holatda taxminan <xliff:g id="TIME">%2$s</xliff:g> qoldi)"</string>
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7679005631124015335) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (261050880878965621) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (2020049829798578618) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">^1</xliff:g> – <xliff:g id="TIME">^2</xliff:g> ichida to‘ladi"</string>
+    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> ichida to‘ladi"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Noma’lum"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Quvvat olmoqda"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"quvvat olmoqda"</string>
@@ -414,4 +444,12 @@
     <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"Hech qachon"</string>
     <string name="zen_interruption_level_priority" msgid="2078370238113347720">"Faqat muhimlari"</string>
     <string name="zen_mode_and_condition" msgid="4927230238450354412">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
+    <!-- no translation found for zen_alarm_warning_indef (3007988140196673193) -->
+    <skip />
+    <!-- no translation found for zen_alarm_warning (6236690803924413088) -->
+    <skip />
+    <!-- no translation found for alarm_template (4996153414057676512) -->
+    <skip />
+    <!-- no translation found for alarm_template_far (3779172822607461675) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values/dimens.xml b/packages/SettingsLib/res/values/dimens.xml
index ddb49b6..7b09ef7 100644
--- a/packages/SettingsLib/res/values/dimens.xml
+++ b/packages/SettingsLib/res/values/dimens.xml
@@ -83,4 +83,12 @@
     <dimen name="zen_mode_condition_detail_item_interline_spacing">4dp</dimen>
     <!-- Zen mode panel: bottom padding, a bit less than qs_panel_padding -->
     <dimen name="zen_mode_condition_detail_bottom_padding">4dp</dimen>
+
+    <!-- SignalDrawable -->
+    <dimen name="signal_icon_size">17dp</dimen>
+    <!-- How far to inset the rounded edges -->
+    <dimen name="stat_sys_mobile_signal_circle_inset">0.9dp</dimen>
+
+
+
 </resources>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SignalDrawable.java b/packages/SettingsLib/src/com/android/settingslib/graph/SignalDrawable.java
similarity index 98%
rename from packages/SystemUI/src/com/android/systemui/statusbar/phone/SignalDrawable.java
rename to packages/SettingsLib/src/com/android/settingslib/graph/SignalDrawable.java
index 15ef742..846e30d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SignalDrawable.java
+++ b/packages/SettingsLib/src/com/android/settingslib/graph/SignalDrawable.java
@@ -12,7 +12,7 @@
  * permissions and limitations under the License.
  */
 
-package com.android.systemui.statusbar.phone;
+package com.android.settingslib.graph;
 
 import android.animation.ArgbEvaluator;
 import android.annotation.IntRange;
@@ -36,7 +36,6 @@
 
 import com.android.settingslib.R;
 import com.android.settingslib.Utils;
-import com.android.systemui.qs.SlashDrawable;
 
 public class SignalDrawable extends Drawable {
 
@@ -458,6 +457,7 @@
     }
 
     private final class SlashArtist {
+        private static final float CORNER_RADIUS = 1f;
         // These values are derived in un-rotated (vertical) orientation
         private static final float SLASH_WIDTH = 1.8384776f;
         private static final float SLASH_HEIGHT = 22f;
@@ -478,7 +478,7 @@
 
         void draw(int height, int width, @NonNull Canvas canvas, Paint paint) {
             Matrix m = new Matrix();
-            final float radius = scale(SlashDrawable.CORNER_RADIUS, width);
+            final float radius = scale(CORNER_RADIUS, width);
             updateRect(
                     scale(LEFT, width),
                     scale(TOP, height),
diff --git a/packages/SettingsLib/tests/robotests/Android.mk b/packages/SettingsLib/tests/robotests/Android.mk
index 7cf7163..f5c42b6 100644
--- a/packages/SettingsLib/tests/robotests/Android.mk
+++ b/packages/SettingsLib/tests/robotests/Android.mk
@@ -12,12 +12,10 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-
 ############################################################
 # SettingsLib Shell app just for Robolectric test target.  #
 ############################################################
 LOCAL_PATH := $(call my-dir)
-
 include $(CLEAR_VARS)
 
 LOCAL_PACKAGE_NAME := SettingsLibShell
@@ -25,8 +23,7 @@
 
 LOCAL_PRIVILEGED_MODULE := true
 
-LOCAL_RESOURCE_DIR := \
-    $(LOCAL_PATH)/res
+LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
 
 LOCAL_USE_AAPT2 := true
 
@@ -35,43 +32,44 @@
 include $(BUILD_PACKAGE)
 
 #############################################
-# SettingsLib Robolectric test target. #
+# SettingsLib Robolectric test target.      #
 #############################################
 include $(CLEAR_VARS)
 
+LOCAL_MODULE := SettingsLibRoboTests
+
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
-# Include the testing libraries (JUnit4 + Robolectric libs).
-LOCAL_STATIC_JAVA_LIBRARIES := \
-    mockito-robolectric-prebuilt \
-    platform-robolectric-android-all-stubs \
-    truth-prebuilt
+LOCAL_JAVA_RESOURCE_DIRS := config
 
 LOCAL_JAVA_LIBRARIES := \
-    junit \
-    platform-robolectric-3.6.1-prebuilt
+    robolectric_android-all-stub \
+    Robolectric_all-target \
+    mockito-robolectric-prebuilt \
+    truth-prebuilt
 
 LOCAL_INSTRUMENTATION_FOR := SettingsLibShell
-LOCAL_MODULE := SettingsLibRoboTests
 
 LOCAL_MODULE_TAGS := optional
 
 include $(BUILD_STATIC_JAVA_LIBRARY)
 
 #############################################################
-# SettingsLib runner target to run the previous target. #
+# SettingsLib runner target to run the previous target.     #
 #############################################################
 include $(CLEAR_VARS)
 
 LOCAL_MODULE := RunSettingsLibRoboTests
 
-LOCAL_SDK_VERSION := current
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
-    SettingsLibRoboTests
+LOCAL_JAVA_LIBRARIES := \
+    SettingsLibRoboTests \
+    robolectric_android-all-stub \
+    Robolectric_all-target \
+    mockito-robolectric-prebuilt \
+    truth-prebuilt
 
 LOCAL_TEST_PACKAGE := SettingsLibShell
 
 LOCAL_ROBOTEST_TIMEOUT := 36000
 
-include prebuilts/misc/common/robolectric/3.6.1/run_robotests.mk
+include external/robolectric-shadows/run_robotests.mk
\ No newline at end of file
diff --git a/packages/SettingsLib/tests/robotests/config/robolectric.properties b/packages/SettingsLib/tests/robotests/config/robolectric.properties
new file mode 100644
index 0000000..34a2a1a
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/config/robolectric.properties
@@ -0,0 +1,2 @@
+manifest=frameworks/base/packages/SettingsLib/tests/robotests/AndroidManifest.xml
+sdk=NEWEST_SDK
\ No newline at end of file
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/CustomEditTextPreferenceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/CustomEditTextPreferenceTest.java
index 7e37493..9d7f59a 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/CustomEditTextPreferenceTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/CustomEditTextPreferenceTest.java
@@ -31,11 +31,9 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
 import org.robolectric.util.ReflectionHelpers;
 
 @RunWith(SettingsLibRobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class CustomEditTextPreferenceTest {
 
     @Mock
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/DeviceInfoUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/DeviceInfoUtilsTest.java
index 82604f7..19a916c 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/DeviceInfoUtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/DeviceInfoUtilsTest.java
@@ -25,10 +25,8 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
 
 @RunWith(SettingsLibRobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class DeviceInfoUtilsTest {
 
     private Context mContext;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/HelpUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/HelpUtilsTest.java
index fdc42bf..e153c3e 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/HelpUtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/HelpUtilsTest.java
@@ -16,6 +16,13 @@
 
 package com.android.settingslib;
 
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
 import android.app.Activity;
 import android.content.Context;
 import android.content.Intent;
@@ -27,6 +34,7 @@
 import android.content.res.TypedArray;
 import android.provider.Settings;
 import android.view.MenuItem;
+
 import com.android.internal.R;
 
 import org.junit.Before;
@@ -37,20 +45,11 @@
 import org.mockito.MockitoAnnotations;
 import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
-
-import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
 
 /**
  * Tests for {@link HelpUtils}.
  */
 @RunWith(RobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class HelpUtilsTest {
     private static final String TEST_HELP_URL = "intent:#Intent;action=com.android.test;end";
     private static final String PACKAGE_NAME_KEY = "package-name-key";
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/RestrictedLockUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/RestrictedLockUtilsTest.java
index 64de635..5f60868 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/RestrictedLockUtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/RestrictedLockUtilsTest.java
@@ -20,11 +20,8 @@
 import static android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT;
 import static android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_REMOTE_INPUT;
 import static android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS;
-
 import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
-
 import static com.google.common.truth.Truth.assertThat;
-
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.doReturn;
@@ -43,12 +40,10 @@
 import org.mockito.Answers;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
-import org.robolectric.annotation.Config;
 
 import java.util.Arrays;
 
 @RunWith(SettingsLibRobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class RestrictedLockUtilsTest {
 
     @Mock
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/RestrictedPreferenceHelperTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/RestrictedPreferenceHelperTest.java
index 79d99f7..a8821ba 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/RestrictedPreferenceHelperTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/RestrictedPreferenceHelperTest.java
@@ -17,6 +17,12 @@
 package com.android.settingslib;
 
 
+import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
+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.content.Context;
 import android.support.v7.preference.Preference;
 import android.support.v7.preference.PreferenceViewHolder;
@@ -28,19 +34,10 @@
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
-import org.robolectric.annotation.Config;
-
-import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
 
 @RunWith(SettingsLibRobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class RestrictedPreferenceHelperTest {
 
-
     @Mock
     private Context mContext;
     @Mock
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/SettingsLibRobolectricTestRunner.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/SettingsLibRobolectricTestRunner.java
index df850be..8778ae9 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/SettingsLibRobolectricTestRunner.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/SettingsLibRobolectricTestRunner.java
@@ -15,6 +15,8 @@
  */
 package com.android.settingslib;
 
+import android.annotation.NonNull;
+
 import org.junit.runners.model.InitializationError;
 import org.robolectric.RobolectricTestRunner;
 import org.robolectric.annotation.Config;
@@ -22,6 +24,8 @@
 import org.robolectric.res.Fs;
 import org.robolectric.res.ResourcePath;
 
+import java.net.MalformedURLException;
+import java.net.URL;
 import java.util.List;
 
 public class SettingsLibRobolectricTestRunner extends RobolectricTestRunner {
@@ -30,33 +34,40 @@
         super(testClass);
     }
 
+    /**
+     * We are going to create our own custom manifest so we can add multiple resource paths to it.
+     */
     @Override
     protected AndroidManifest getAppManifest(Config config) {
-        // Using the manifest file's relative path, we can figure out the application directory.
-        final String appRoot = "frameworks/base/packages/SettingsLib";
-        final String manifestPath = appRoot + "/AndroidManifest.xml";
-        final String resDir = appRoot + "/tests/robotests/res";
-        final String assetsDir = appRoot + config.assetDir();
+        try {
+            // Using the manifest file's relative path, we can figure out the application directory.
+            final URL appRoot =
+                new URL("file:frameworks/base/packages/SettingsLib/tests/robotests");
+            final URL manifestPath = new URL(appRoot, "AndroidManifest.xml");
+            final URL resDir = new URL(appRoot, "res");
+            final URL assetsDir = new URL(appRoot, "assets");
 
-        return new AndroidManifest(Fs.fileFromPath(manifestPath), Fs.fileFromPath(resDir),
-            Fs.fileFromPath(assetsDir), "com.android.settingslib") {
-            @Override
-            public List<ResourcePath> getIncludedResourcePaths() {
-                List<ResourcePath> paths = super.getIncludedResourcePaths();
-                paths.add(new ResourcePath(
-                    null,
-                    Fs.fileFromPath("./frameworks/base/packages/SettingsLib/res"),
-                    null));
-                paths.add(new ResourcePath(
-                    null,
-                    Fs.fileFromPath("./frameworks/base/core/res/res"),
-                    null));
-                paths.add(new ResourcePath(
-                    null,
-                    Fs.fileFromPath("./frameworks/support/v7/appcompat/res"),
-                    null));
-                return paths;
-            }
-        };
+            return new AndroidManifest(Fs.fromURL(manifestPath), Fs.fromURL(resDir),
+                Fs.fromURL(assetsDir), "com.android.settingslib") {
+                @Override
+                public List<ResourcePath> getIncludedResourcePaths() {
+                    final List<ResourcePath> paths = super.getIncludedResourcePaths();
+                    paths.add(resourcePath("file:frameworks/base/packages/SettingsLib/res"));
+                    paths.add(resourcePath("file:frameworks/base/core/res/res"));
+                    paths.add(resourcePath("file:frameworks/support/v7/appcompat/res"));
+                    return paths;
+                }
+            };
+        } catch (MalformedURLException e) {
+            throw new RuntimeException("SettingsLibRobolectricTestRunner failure", e);
+        }
+    }
+
+    private static ResourcePath resourcePath(@NonNull String spec) {
+        try {
+            return new ResourcePath(null, Fs.fromURL(new URL(spec)), null);
+        } catch (MalformedURLException e) {
+            throw new RuntimeException("SettingsLibRobolectricTestRunner failure", e);
+        }
     }
 }
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/TestConfig.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/TestConfig.java
deleted file mode 100644
index 1f9070c..0000000
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/TestConfig.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settingslib;
-
-import android.os.Build;
-
-public class TestConfig {
-    public static final int SDK_VERSION = Build.VERSION_CODES.O;
-    public static final String MANIFEST_PATH =
-            "frameworks/base/packages/SettingsLib/tests/robotests/AndroidManifest.xml";
-}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/TetherUtilTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/TetherUtilTest.java
index 8bd31d4..0109f48 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/TetherUtilTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/TetherUtilTest.java
@@ -16,6 +16,8 @@
 
 package com.android.settingslib;
 
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.when;
 
 import android.content.Context;
 
@@ -24,13 +26,8 @@
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
-import org.robolectric.annotation.Config;
-
-import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.Mockito.when;
 
 @RunWith(SettingsLibRobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class TetherUtilTest {
 
     @Mock
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/TwoTargetPreferenceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/TwoTargetPreferenceTest.java
index b5ee5ad..c5e93f0 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/TwoTargetPreferenceTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/TwoTargetPreferenceTest.java
@@ -31,10 +31,8 @@
 import org.junit.runner.RunWith;
 import org.mockito.MockitoAnnotations;
 import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
 
 @RunWith(SettingsLibRobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class TwoTargetPreferenceTest {
 
     private PreferenceViewHolder mViewHolder;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/UtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/UtilsTest.java
index 5459fb7..12d3106 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/UtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/UtilsTest.java
@@ -34,9 +34,9 @@
 import android.provider.Settings;
 import android.provider.Settings.Secure;
 import android.text.TextUtils;
+
 import com.android.settingslib.wrapper.LocationManagerWrapper;
-import java.util.HashMap;
-import java.util.Map;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -50,11 +50,11 @@
 import org.robolectric.annotation.Implements;
 import org.robolectric.shadows.ShadowSettings;
 
+import java.util.HashMap;
+import java.util.Map;
+
 @RunWith(SettingsLibRobolectricTestRunner.class)
-@Config(
-        manifest = TestConfig.MANIFEST_PATH,
-        sdk = TestConfig.SDK_VERSION,
-        shadows = {
+@Config(shadows = {
             UtilsTest.ShadowSecure.class,
             UtilsTest.ShadowLocationManagerWrapper.class})
 public class UtilsTest {
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/applications/ServiceListingTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/applications/ServiceListingTest.java
index fa31a7d..060b716 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/applications/ServiceListingTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/applications/ServiceListingTest.java
@@ -17,7 +17,6 @@
 package com.android.settingslib.applications;
 
 import static com.google.common.truth.Truth.assertThat;
-
 import static org.mockito.ArgumentMatchers.anyList;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.times;
@@ -27,24 +26,17 @@
 import android.provider.Settings;
 
 import com.android.settingslib.SettingsLibRobolectricTestRunner;
-import com.android.settingslib.TestConfig;
-import com.android.settingslib.testutils.shadow.ShadowPackageManagerWrapper;
 
-import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
 
 @RunWith(SettingsLibRobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION,
-    shadows = {ShadowPackageManagerWrapper.class})
 public class ServiceListingTest {
 
     private static final String TEST_SETTING = "testSetting";
     private static final String TEST_INTENT = "com.example.intent";
-    private static final String TEST_PERMISSION = "testPermission";
 
     private ServiceListing mServiceListing;
 
@@ -59,11 +51,6 @@
                 .build();
     }
 
-    @After
-    public void tearDown() {
-        ShadowPackageManagerWrapper.reset();
-    }
-
     @Test
     public void testCallback() {
         ServiceListing.Callback callback = mock(ServiceListing.Callback.class);
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/A2dpProfileTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/A2dpProfileTest.java
index 590bc90..334ea16 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/A2dpProfileTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/A2dpProfileTest.java
@@ -15,6 +15,13 @@
  */
 package com.android.settingslib.bluetooth;
 
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
 import android.bluetooth.BluetoothA2dp;
 import android.bluetooth.BluetoothCodecConfig;
 import android.bluetooth.BluetoothCodecStatus;
@@ -24,30 +31,16 @@
 import android.content.res.Resources;
 
 import com.android.settingslib.R;
-import com.android.settingslib.TestConfig;
 import com.android.settingslib.wrapper.BluetoothA2dpWrapper;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
 import org.robolectric.RobolectricTestRunner;
-import org.robolectric.annotation.Config;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
 
 @RunWith(RobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class A2dpProfileTest {
 
     @Mock Context mContext;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java
index 1481161..92c68e6 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java
@@ -16,7 +16,6 @@
 package com.android.settingslib.bluetooth;
 
 import static com.google.common.truth.Truth.assertThat;
-
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyString;
 import static org.mockito.Mockito.doAnswer;
@@ -30,9 +29,6 @@
 import android.bluetooth.BluetoothProfile;
 import android.content.Context;
 
-import com.android.settingslib.R;
-import com.android.settingslib.TestConfig;
-
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -43,8 +39,7 @@
 import org.robolectric.annotation.Config;
 
 @RunWith(RobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION, resourceDir =
-        "../../res")
+@Config(resourceDir = "../../res")
 public class CachedBluetoothDeviceTest {
     private final static String DEVICE_NAME = "TestName";
     private final static String DEVICE_ALIAS = "TestAlias";
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/UtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/UtilsTest.java
index 5eb543b..baba267 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/UtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/UtilsTest.java
@@ -22,18 +22,13 @@
 
 import com.android.settingslib.R;
 import com.android.settingslib.SettingsLibRobolectricTestRunner;
-import com.android.settingslib.TestConfig;
 import com.android.settingslib.graph.BluetoothDeviceLayerDrawable;
-import com.android.settingslib.testutils.shadow.SettingsLibShadowResources;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
 
 @RunWith(SettingsLibRobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION,
-        shadows = SettingsLibShadowResources.class)
 public class UtilsTest {
 
     @Test
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/AbstractPreferenceControllerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/AbstractPreferenceControllerTest.java
index 26970e1..8767923 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/AbstractPreferenceControllerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/AbstractPreferenceControllerTest.java
@@ -22,8 +22,6 @@
 import android.support.v7.preference.Preference;
 import android.support.v7.preference.PreferenceScreen;
 
-import com.android.settingslib.TestConfig;
-
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -31,10 +29,8 @@
 import org.mockito.MockitoAnnotations;
 import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
 
 @RunWith(RobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class AbstractPreferenceControllerTest {
 
     @Mock
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/MetricsFeatureProviderTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/MetricsFeatureProviderTest.java
index 8bea51d..5c19e61 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/MetricsFeatureProviderTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/MetricsFeatureProviderTest.java
@@ -28,7 +28,6 @@
 import android.util.Pair;
 
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.settingslib.TestConfig;
 import com.android.settingslib.SettingsLibRobolectricTestRunner;
 
 import org.junit.Before;
@@ -39,14 +38,12 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
 import org.robolectric.util.ReflectionHelpers;
 
 import java.util.ArrayList;
 import java.util.List;
 
 @RunWith(SettingsLibRobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class MetricsFeatureProviderTest {
     private static int CATEGORY = 10;
     private static boolean SUBTYPE_BOOLEAN = true;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/SharedPreferenceLoggerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/SharedPreferenceLoggerTest.java
index d558a64..ebafc59 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/SharedPreferenceLoggerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/SharedPreferenceLoggerTest.java
@@ -30,9 +30,7 @@
 import android.content.SharedPreferences;
 import android.util.Pair;
 
-import com.android.settingslib.TestConfig;
 import com.android.settingslib.SettingsLibRobolectricTestRunner;
-
 import com.google.common.truth.Platform;
 
 import org.junit.Before;
@@ -42,10 +40,8 @@
 import org.mockito.ArgumentMatcher;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
-import org.robolectric.annotation.Config;
 
 @RunWith(SettingsLibRobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class SharedPreferenceLoggerTest {
 
     private static final String TEST_TAG = "tag";
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/VisibilityLoggerMixinTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/VisibilityLoggerMixinTest.java
index 1ab6afe..8b31450 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/VisibilityLoggerMixinTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/VisibilityLoggerMixinTest.java
@@ -16,7 +16,6 @@
 package com.android.settingslib.core.instrumentation;
 
 import static com.android.settingslib.core.instrumentation.Instrumentable.METRICS_CATEGORY_UNKNOWN;
-
 import static org.mockito.ArgumentMatchers.nullable;
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyInt;
@@ -30,12 +29,11 @@
 import android.app.Activity;
 import android.content.Context;
 import android.content.Intent;
-
 import android.os.Bundle;
 import android.support.v4.app.FragmentActivity;
+
 import com.android.internal.logging.nano.MetricsProto;
 import com.android.settingslib.SettingsLibRobolectricTestRunner;
-import com.android.settingslib.TestConfig;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -44,11 +42,9 @@
 import org.mockito.MockitoAnnotations;
 import org.robolectric.Robolectric;
 import org.robolectric.android.controller.ActivityController;
-import org.robolectric.annotation.Config;
 
 
 @RunWith(SettingsLibRobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class VisibilityLoggerMixinTest {
 
     @Mock
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/lifecycle/LifecycleTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/lifecycle/LifecycleTest.java
index ae24c07..2b2bf5b 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/lifecycle/LifecycleTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/lifecycle/LifecycleTest.java
@@ -25,7 +25,6 @@
 import android.view.MenuItem;
 
 import com.android.settingslib.SettingsLibRobolectricTestRunner;
-import com.android.settingslib.TestConfig;
 import com.android.settingslib.core.lifecycle.events.OnAttach;
 import com.android.settingslib.core.lifecycle.events.OnCreateOptionsMenu;
 import com.android.settingslib.core.lifecycle.events.OnDestroy;
@@ -42,10 +41,8 @@
 import org.robolectric.Robolectric;
 import org.robolectric.android.controller.ActivityController;
 import org.robolectric.android.controller.FragmentController;
-import org.robolectric.annotation.Config;
 
 @RunWith(SettingsLibRobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class LifecycleTest {
 
     private LifecycleOwner mLifecycleOwner;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/development/DevelopmentSettingsEnablerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/development/DevelopmentSettingsEnablerTest.java
index 708353e..a15f5fc 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/development/DevelopmentSettingsEnablerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/development/DevelopmentSettingsEnablerTest.java
@@ -22,7 +22,6 @@
 import android.provider.Settings;
 
 import com.android.settingslib.SettingsLibRobolectricTestRunner;
-import com.android.settingslib.TestConfig;
 import com.android.settingslib.testutils.shadow.ShadowUserManager;
 
 import org.junit.After;
@@ -33,9 +32,7 @@
 import org.robolectric.annotation.Config;
 
 @RunWith(SettingsLibRobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION, shadows = {
-        ShadowUserManager.class
-})
+@Config(shadows = ShadowUserManager.class)
 public class DevelopmentSettingsEnablerTest {
 
     private Context mContext;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/development/EnableAdbPreferenceControllerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/development/EnableAdbPreferenceControllerTest.java
index aac736a..475e7d8 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/development/EnableAdbPreferenceControllerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/development/EnableAdbPreferenceControllerTest.java
@@ -31,18 +31,15 @@
 import android.support.v7.preference.PreferenceScreen;
 
 import com.android.settingslib.SettingsLibRobolectricTestRunner;
-import com.android.settingslib.TestConfig;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
-import org.robolectric.annotation.Config;
 import org.robolectric.shadows.ShadowApplication;
 
 @RunWith(SettingsLibRobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class EnableAdbPreferenceControllerTest {
     @Mock(answer = RETURNS_DEEP_STUBS)
     private PreferenceScreen mScreen;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/development/LogdSizePreferenceControllerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/development/LogdSizePreferenceControllerTest.java
index 26d3570..72c8d1ad36 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/development/LogdSizePreferenceControllerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/development/LogdSizePreferenceControllerTest.java
@@ -45,20 +45,15 @@
 
 import com.android.settingslib.R;
 import com.android.settingslib.SettingsLibRobolectricTestRunner;
-import com.android.settingslib.TestConfig;
 
-import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
 
 @RunWith(SettingsLibRobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION,
-        shadows = SystemPropertiesTestImpl.class)
 public class LogdSizePreferenceControllerTest {
 
     @Mock
@@ -95,11 +90,6 @@
         mController.displayPreference(mPreferenceScreen);
     }
 
-    @After
-    public void tearDown() {
-        SystemPropertiesTestImpl.clear();
-    }
-
     @Test
     public void testUpdateLogdSizeValues_lowRamEntries() {
         SystemProperties.set(LOW_RAM_CONFIG_PROPERTY_KEY, "true");
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/development/LogpersistPreferenceControllerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/development/LogpersistPreferenceControllerTest.java
index 050877d..4b9bfc3 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/development/LogpersistPreferenceControllerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/development/LogpersistPreferenceControllerTest.java
@@ -28,7 +28,6 @@
 import android.support.v7.preference.PreferenceScreen;
 
 import com.android.settingslib.SettingsLibRobolectricTestRunner;
-import com.android.settingslib.TestConfig;
 import com.android.settingslib.core.lifecycle.Lifecycle;
 
 import org.junit.Before;
@@ -37,11 +36,8 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
 
 @RunWith(SettingsLibRobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION,
-        shadows = SystemPropertiesTestImpl.class)
 public class LogpersistPreferenceControllerTest {
 
     private LifecycleOwner mLifecycleOwner;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/development/SystemPropPokerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/development/SystemPropPokerTest.java
index fa7961b..40db478 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/development/SystemPropPokerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/development/SystemPropPokerTest.java
@@ -20,7 +20,6 @@
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.nullable;
 import static org.mockito.Mockito.atLeastOnce;
-import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
@@ -29,7 +28,6 @@
 import android.os.Parcel;
 
 import com.android.settingslib.SettingsLibRobolectricTestRunner;
-import com.android.settingslib.TestConfig;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -37,10 +35,8 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 import org.mockito.Spy;
-import org.robolectric.annotation.Config;
 
 @RunWith(SettingsLibRobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class SystemPropPokerTest {
 
     @Spy
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/development/SystemPropertiesTestImpl.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/development/SystemPropertiesTestImpl.java
deleted file mode 100644
index 6977e09..0000000
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/development/SystemPropertiesTestImpl.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settingslib.development;
-
-import android.text.TextUtils;
-import android.util.ArrayMap;
-
-import org.robolectric.annotation.Implementation;
-import org.robolectric.annotation.Implements;
-import org.robolectric.shadows.ShadowSystemProperties;
-
-import java.util.Map;
-
-@Implements(className = "android.os.SystemProperties")
-public class SystemPropertiesTestImpl extends ShadowSystemProperties {
-
-    private static Map<String, String> sProperties = new ArrayMap<>();
-
-    @Implementation
-    public static String get(String key) {
-        String value = sProperties.get(key);
-        if (!TextUtils.isEmpty(value)) {
-            return value;
-        } else {
-            return ShadowSystemProperties.get(key);
-        }
-    }
-
-    @Implementation
-    public static String get(String key, String def) {
-        String value = sProperties.get(key);
-        if (!TextUtils.isEmpty(value)) {
-            return value;
-        } else {
-            return ShadowSystemProperties.get(key, def);
-        }
-    }
-
-    @Implementation
-    public static void set(String key, String val) {
-        sProperties.put(key, val);
-    }
-
-    public static synchronized void clear() {
-        sProperties.clear();
-    }
-}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/BluetoothAddressPreferenceControllerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/BluetoothAddressPreferenceControllerTest.java
index 1de7a7a..0385f4b 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/BluetoothAddressPreferenceControllerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/BluetoothAddressPreferenceControllerTest.java
@@ -26,7 +26,6 @@
 import android.support.v7.preference.PreferenceScreen;
 
 import com.android.settingslib.SettingsLibRobolectricTestRunner;
-import com.android.settingslib.TestConfig;
 import com.android.settingslib.core.lifecycle.Lifecycle;
 
 import org.junit.Before;
@@ -39,7 +38,6 @@
 import org.robolectric.annotation.Implements;
 
 @RunWith(SettingsLibRobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class BluetoothAddressPreferenceControllerTest {
     @Mock
     private Context mContext;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/ConnectivityPreferenceControllerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/ConnectivityPreferenceControllerTest.java
index 362dbd9..7c127e5 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/ConnectivityPreferenceControllerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/ConnectivityPreferenceControllerTest.java
@@ -17,7 +17,6 @@
 package com.android.settingslib.deviceinfo;
 
 import static com.google.common.truth.Truth.assertWithMessage;
-
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.ArgumentMatchers.nullable;
 import static org.mockito.Mockito.doReturn;
@@ -31,7 +30,6 @@
 import android.os.Handler;
 
 import com.android.settingslib.SettingsLibRobolectricTestRunner;
-import com.android.settingslib.TestConfig;
 import com.android.settingslib.core.lifecycle.Lifecycle;
 
 import org.junit.Before;
@@ -40,10 +38,8 @@
 import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
-import org.robolectric.annotation.Config;
 
 @RunWith(SettingsLibRobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class ConnectivityPreferenceControllerTest {
     @Mock
     private Context mContext;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/ImsStatusPreferenceControllerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/ImsStatusPreferenceControllerTest.java
index 112ee64..d600c20 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/ImsStatusPreferenceControllerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/ImsStatusPreferenceControllerTest.java
@@ -17,7 +17,6 @@
 package com.android.settingslib.deviceinfo;
 
 import static com.google.common.truth.Truth.assertWithMessage;
-
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
@@ -30,7 +29,6 @@
 import android.telephony.SubscriptionManager;
 
 import com.android.settingslib.SettingsLibRobolectricTestRunner;
-import com.android.settingslib.TestConfig;
 import com.android.settingslib.core.lifecycle.Lifecycle;
 
 import org.junit.Before;
@@ -43,7 +41,6 @@
 import org.robolectric.annotation.Implements;
 
 @RunWith(SettingsLibRobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class ImsStatusPreferenceControllerTest {
     @Mock
     private Context mContext;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/IpAddressPreferenceControllerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/IpAddressPreferenceControllerTest.java
index d0ecae3..99e582c 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/IpAddressPreferenceControllerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/IpAddressPreferenceControllerTest.java
@@ -27,7 +27,6 @@
 import android.support.v7.preference.PreferenceScreen;
 
 import com.android.settingslib.SettingsLibRobolectricTestRunner;
-import com.android.settingslib.TestConfig;
 import com.android.settingslib.core.lifecycle.Lifecycle;
 
 import org.junit.Before;
@@ -35,13 +34,11 @@
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
-import org.robolectric.annotation.Config;
 
 import java.util.Arrays;
 import java.util.List;
 
 @RunWith(SettingsLibRobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class IpAddressPreferenceControllerTest {
     @Mock
     private Context mContext;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/SerialNumberPreferenceControllerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/SerialNumberPreferenceControllerTest.java
index 34bbf4f..a4fa7aa 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/SerialNumberPreferenceControllerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/SerialNumberPreferenceControllerTest.java
@@ -24,7 +24,6 @@
 import android.support.v7.preference.PreferenceScreen;
 
 import com.android.settingslib.SettingsLibRobolectricTestRunner;
-import com.android.settingslib.TestConfig;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -32,10 +31,8 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
 
 @RunWith(SettingsLibRobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class SerialNumberPreferenceControllerTest {
 
     @Mock
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/SimStatusImeiInfoPreferenceControllerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/SimStatusImeiInfoPreferenceControllerTest.java
index 28409fa..eaae405 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/SimStatusImeiInfoPreferenceControllerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/SimStatusImeiInfoPreferenceControllerTest.java
@@ -17,7 +17,6 @@
 package com.android.settingslib.deviceinfo;
 
 import static com.google.common.truth.Truth.assertThat;
-
 import static org.robolectric.shadow.api.Shadow.extract;
 
 import android.net.ConnectivityManager;
@@ -25,7 +24,6 @@
 import android.util.SparseBooleanArray;
 
 import com.android.settingslib.SettingsLibRobolectricTestRunner;
-import com.android.settingslib.TestConfig;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -36,8 +34,7 @@
 import org.robolectric.annotation.Implements;
 
 @RunWith(SettingsLibRobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION,
-        shadows = {SimStatusImeiInfoPreferenceControllerTest.ShadowUserManager.class,
+@Config(shadows = {SimStatusImeiInfoPreferenceControllerTest.ShadowUserManager.class,
                 SimStatusImeiInfoPreferenceControllerTest.ShadowConnectivityManager.class})
 public class SimStatusImeiInfoPreferenceControllerTest {
 
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/UptimePreferenceControllerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/UptimePreferenceControllerTest.java
index f68533b..39e05fa 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/UptimePreferenceControllerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/UptimePreferenceControllerTest.java
@@ -28,7 +28,6 @@
 import android.text.format.DateUtils;
 
 import com.android.settingslib.SettingsLibRobolectricTestRunner;
-import com.android.settingslib.TestConfig;
 import com.android.settingslib.core.lifecycle.Lifecycle;
 
 import org.junit.Before;
@@ -36,11 +35,9 @@
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
-import org.robolectric.annotation.Config;
 import org.robolectric.shadows.ShadowLooper;
 
 @RunWith(SettingsLibRobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class UptimePreferenceControllerTest {
     @Mock
     private Context mContext;
@@ -98,5 +95,4 @@
             super(context, lifecycle);
         }
     }
-
 }
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/WifiMacAddressPreferenceControllerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/WifiMacAddressPreferenceControllerTest.java
index 265a60b..d546f11 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/WifiMacAddressPreferenceControllerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/WifiMacAddressPreferenceControllerTest.java
@@ -17,7 +17,6 @@
 package com.android.settingslib.deviceinfo;
 
 import static com.google.common.truth.Truth.assertWithMessage;
-
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
@@ -32,7 +31,6 @@
 
 import com.android.settingslib.R;
 import com.android.settingslib.SettingsLibRobolectricTestRunner;
-import com.android.settingslib.TestConfig;
 import com.android.settingslib.core.lifecycle.Lifecycle;
 
 import org.junit.Before;
@@ -40,14 +38,12 @@
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
-import org.robolectric.annotation.Config;
 
 import java.util.Arrays;
 import java.util.List;
 
 @SuppressLint("HardwareIds")
 @RunWith(SettingsLibRobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class WifiMacAddressPreferenceControllerTest {
     @Mock
     private Context mContext;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/CategoryKeyTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/CategoryKeyTest.java
index 6be44cc..b90f37a 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/CategoryKeyTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/CategoryKeyTest.java
@@ -16,21 +16,17 @@
 
 package com.android.settingslib.drawer;
 
-import android.util.ArraySet;
+import static com.google.common.truth.Truth.assertThat;
 
-import com.android.settingslib.TestConfig;
+import android.util.ArraySet;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.robolectric.RobolectricTestRunner;
-import org.robolectric.annotation.Config;
 
 import java.util.Set;
 
-import static com.google.common.truth.Truth.assertThat;
-
 @RunWith(RobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class CategoryKeyTest {
 
     @Test
@@ -64,5 +60,4 @@
 
         assertThat(allKeys.size()).isEqualTo(15);
     }
-
 }
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/CategoryManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/CategoryManagerTest.java
index f099c90..4efcb7e 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/CategoryManagerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/CategoryManagerTest.java
@@ -16,27 +16,24 @@
 
 package com.android.settingslib.drawer;
 
+import static com.google.common.truth.Truth.assertThat;
+
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.util.Pair;
 
 import com.android.settingslib.SettingsLibRobolectricTestRunner;
-import com.android.settingslib.TestConfig;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.robolectric.annotation.Config;
 import org.robolectric.shadows.ShadowApplication;
 
 import java.util.HashMap;
 import java.util.Map;
 
-import static com.google.common.truth.Truth.assertThat;
-
 @RunWith(SettingsLibRobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class CategoryManagerTest {
 
     private Context mContext;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java
index a395a4a..fc1b2238 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java
@@ -17,7 +17,6 @@
 package com.android.settingslib.drawer;
 
 import static com.google.common.truth.Truth.assertThat;
-
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyString;
@@ -54,7 +53,6 @@
 import android.widget.RemoteViews;
 
 import com.android.settingslib.R;
-import com.android.settingslib.TestConfig;
 import com.android.settingslib.suggestions.SuggestionParser;
 
 import org.junit.Before;
@@ -74,9 +72,7 @@
 import java.util.Map;
 
 @RunWith(RobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH,
-        sdk = TestConfig.SDK_VERSION,
-        shadows = {TileUtilsTest.TileUtilsShadowRemoteViews.class})
+@Config(shadows = TileUtilsTest.TileUtilsShadowRemoteViews.class)
 public class TileUtilsTest {
 
     private Context mContext;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/PowerWhitelistBackendTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/PowerWhitelistBackendTest.java
index fc0019d..c6a1428 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/PowerWhitelistBackendTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/PowerWhitelistBackendTest.java
@@ -17,7 +17,6 @@
 package com.android.settingslib.fuelgauge;
 
 import static com.google.common.truth.Truth.assertThat;
-
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.Mockito.atLeastOnce;
 import static org.mockito.Mockito.doNothing;
@@ -27,17 +26,14 @@
 import android.os.IDeviceIdleController;
 
 import com.android.settingslib.SettingsLibRobolectricTestRunner;
-import com.android.settingslib.TestConfig;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
-import org.robolectric.annotation.Config;
 
 @RunWith(SettingsLibRobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class PowerWhitelistBackendTest {
 
     private static final String PACKAGE_ONE = "com.example.packageone";
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/graph/BatteryMeterDrawableBaseTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/graph/BatteryMeterDrawableBaseTest.java
index e022232..49dde0e 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/graph/BatteryMeterDrawableBaseTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/graph/BatteryMeterDrawableBaseTest.java
@@ -26,8 +26,6 @@
 import android.graphics.Paint;
 
 import com.android.settingslib.SettingsLibRobolectricTestRunner;
-import com.android.settingslib.TestConfig;
-import com.android.settingslib.testutils.shadow.SettingsLibShadowResources;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -35,12 +33,9 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
 import org.robolectric.util.ReflectionHelpers;
 
 @RunWith(SettingsLibRobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION,
-        shadows = SettingsLibShadowResources.class)
 public class BatteryMeterDrawableBaseTest {
     private static final int CRITICAL_LEVEL = 5;
     private static final int PADDING = 5;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/graph/BluetoothDeviceLayerDrawableTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/graph/BluetoothDeviceLayerDrawableTest.java
index 94f80d3..37d4d1d 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/graph/BluetoothDeviceLayerDrawableTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/graph/BluetoothDeviceLayerDrawableTest.java
@@ -19,23 +19,17 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import android.content.Context;
-import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.VectorDrawable;
 
 import com.android.settingslib.R;
 import com.android.settingslib.SettingsLibRobolectricTestRunner;
-import com.android.settingslib.TestConfig;
-import com.android.settingslib.testutils.shadow.SettingsLibShadowResources;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
 
 @RunWith(SettingsLibRobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION,
-        shadows = SettingsLibShadowResources.class)
 public class BluetoothDeviceLayerDrawableTest {
     private static final int RES_ID = R.drawable.ic_bt_cellphone;
     private static final int BATTERY_LEVEL = 15;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/license/LicenseHtmlGeneratorFromXmlTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/license/LicenseHtmlGeneratorFromXmlTest.java
index c7e9262..96b2a14 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/license/LicenseHtmlGeneratorFromXmlTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/license/LicenseHtmlGeneratorFromXmlTest.java
@@ -18,12 +18,10 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-import com.android.settingslib.TestConfig;
 import com.android.settingslib.SettingsLibRobolectricTestRunner;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.robolectric.annotation.Config;
 import org.xmlpull.v1.XmlPullParserException;
 
 import java.io.ByteArrayInputStream;
@@ -35,7 +33,6 @@
 import java.util.Map;
 
 @RunWith(SettingsLibRobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class LicenseHtmlGeneratorFromXmlTest {
     private static final String VALILD_XML_STRING =
             "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/license/LicenseHtmlLoaderTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/license/LicenseHtmlLoaderTest.java
index 1a6f30c..5095f50 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/license/LicenseHtmlLoaderTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/license/LicenseHtmlLoaderTest.java
@@ -17,7 +17,6 @@
 package com.android.settingslib.license;
 
 import static com.google.common.truth.Truth.assertThat;
-
 import static org.mockito.Matchers.any;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.never;
@@ -26,7 +25,6 @@
 
 import android.content.Context;
 
-import com.android.settingslib.TestConfig;
 import com.android.settingslib.SettingsLibRobolectricTestRunner;
 
 import org.junit.Before;
@@ -34,13 +32,11 @@
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
-import org.robolectric.annotation.Config;
 
 import java.io.File;
 import java.util.ArrayList;
 
 @RunWith(SettingsLibRobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class LicenseHtmlLoaderTest {
     @Mock
     private Context mContext;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/location/RecentLocationAppsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/location/RecentLocationAppsTest.java
index 226166b..5e0fcef 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/location/RecentLocationAppsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/location/RecentLocationAppsTest.java
@@ -1,8 +1,8 @@
 package com.android.settingslib.location;
 
+import static com.google.common.truth.Truth.assertThat;
 import static org.mockito.Matchers.isA;
 import static org.mockito.Mockito.when;
-import static com.google.common.truth.Truth.assertThat;
 
 import android.app.AppOpsManager;
 import android.app.AppOpsManager.OpEntry;
@@ -15,23 +15,21 @@
 import android.os.Process;
 import android.os.UserHandle;
 import android.os.UserManager;
+
 import com.android.settingslib.SettingsLibRobolectricTestRunner;
-import com.android.settingslib.TestConfig;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.concurrent.TimeUnit;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
-import org.robolectric.annotation.Config;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
 
 @RunWith(SettingsLibRobolectricTestRunner.class)
-@Config(
-        manifest = TestConfig.MANIFEST_PATH,
-        sdk = TestConfig.SDK_VERSION)
 public class RecentLocationAppsTest {
 
     private static final int TEST_UID = 1234;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/EnableZenModeDialogTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/EnableZenModeDialogTest.java
index 777cd98..9b5da4a 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/EnableZenModeDialogTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/EnableZenModeDialogTest.java
@@ -18,21 +18,18 @@
 
 import static junit.framework.Assert.assertFalse;
 import static junit.framework.Assert.assertTrue;
-
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.when;
 
-import android.app.Activity;
 import android.app.Fragment;
 import android.content.Context;
 import android.net.Uri;
 import android.service.notification.Condition;
 import android.view.LayoutInflater;
 
-import com.android.settingslib.TestConfig;
 import com.android.settingslib.SettingsLibRobolectricTestRunner;
 
 import org.junit.Before;
@@ -41,10 +38,8 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
 
 @RunWith(SettingsLibRobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class EnableZenModeDialogTest {
     private EnableZenModeDialog mController;
 
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/suggestions/SuggestionControllerMixinTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/suggestions/SuggestionControllerMixinTest.java
index ed1c405..cfa16b8 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/suggestions/SuggestionControllerMixinTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/suggestions/SuggestionControllerMixinTest.java
@@ -18,9 +18,7 @@
 
 import static android.arch.lifecycle.Lifecycle.Event.ON_START;
 import static android.arch.lifecycle.Lifecycle.Event.ON_STOP;
-
 import static com.google.common.truth.Truth.assertThat;
-
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
@@ -30,7 +28,6 @@
 import android.content.ComponentName;
 import android.content.Context;
 
-import com.android.settingslib.TestConfig;
 import com.android.settingslib.SettingsLibRobolectricTestRunner;
 import com.android.settingslib.core.lifecycle.Lifecycle;
 
@@ -44,10 +41,7 @@
 import org.robolectric.annotation.Config;
 
 @RunWith(SettingsLibRobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION,
-        shadows = {
-                ShadowSuggestionController.class
-        })
+@Config(shadows = ShadowSuggestionController.class)
 public class SuggestionControllerMixinTest {
 
     @Mock
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/suggestions/SuggestionParserTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/suggestions/SuggestionParserTest.java
index db599a7..d05bcfd 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/suggestions/SuggestionParserTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/suggestions/SuggestionParserTest.java
@@ -17,11 +17,9 @@
 package com.android.settingslib.suggestions;
 
 import static com.google.common.truth.Truth.assertThat;
-
 import static org.robolectric.RuntimeEnvironment.application;
 import static org.robolectric.shadow.api.Shadow.extract;
 
-import android.app.ApplicationPackageManager;
 import android.content.ComponentName;
 import android.content.Intent;
 import android.content.SharedPreferences;
@@ -30,28 +28,22 @@
 import android.preference.PreferenceManager;
 
 import com.android.settingslib.SettingsLibRobolectricTestRunner;
-import com.android.settingslib.TestConfig;
 import com.android.settingslib.drawer.Tile;
 import com.android.settingslib.drawer.TileUtilsTest;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.robolectric.annotation.Config;
-import org.robolectric.annotation.Implementation;
-import org.robolectric.annotation.Implements;
-import org.robolectric.shadows.ShadowApplicationPackageManager;
+import org.robolectric.shadows.ShadowPackageManager;
 
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 
 @RunWith(SettingsLibRobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION,
-        shadows = SuggestionParserTest.TestPackageManager.class)
 public class SuggestionParserTest {
 
-    private TestPackageManager mPackageManager;
+    private ShadowPackageManager mPackageManager;
     private SuggestionParser mSuggestionParser;
     private SuggestionCategory mMultipleCategory;
     private SuggestionCategory mExclusiveCategory;
@@ -205,13 +197,4 @@
         mSuggestionParser.readSuggestions(
                 mMultipleCategory, mSuggestionsAfterDismiss, isSmartSuggestionEnabled);
     }
-
-    @Implements(ApplicationPackageManager.class)
-    public static class TestPackageManager extends ShadowApplicationPackageManager {
-
-        @Implementation
-        public List<ResolveInfo> queryIntentActivitiesAsUser(Intent intent, int flags, int userId) {
-            return super.queryIntentActivities(intent, flags);
-        }
-    }
 }
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/testutils/shadow/SettingsLibShadowResources.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/testutils/shadow/SettingsLibShadowResources.java
deleted file mode 100644
index b53cc37..0000000
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/testutils/shadow/SettingsLibShadowResources.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settingslib.testutils.shadow;
-
-import static org.robolectric.shadow.api.Shadow.directlyOn;
-
-import android.content.res.Resources;
-import android.content.res.Resources.NotFoundException;
-import android.support.annotation.ArrayRes;
-
-import org.robolectric.annotation.Implementation;
-import org.robolectric.annotation.Implements;
-import org.robolectric.annotation.RealObject;
-import org.robolectric.shadows.ShadowResources;
-
-/**
- * Shadow Resources to handle resource references that Robolectric shadows cannot
- * handle because they are too new or private.
- */
-@Implements(Resources.class)
-public class SettingsLibShadowResources extends ShadowResources {
-
-    @RealObject
-    public Resources realResources;
-
-    @Implementation
-    public int[] getIntArray(@ArrayRes int id) throws NotFoundException {
-        // The Robolectric has resource mismatch for these values, so we need to stub it here
-        if (id == com.android.settingslib.R.array.batterymeter_bolt_points
-                || id == com.android.settingslib.R.array.batterymeter_plus_points) {
-            return new int[2];
-        }
-        return directlyOn(realResources, Resources.class).getIntArray(id);
-    }
-}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/testutils/shadow/ShadowPackageManagerWrapper.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/testutils/shadow/ShadowPackageManagerWrapper.java
deleted file mode 100644
index 1fdca27..0000000
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/testutils/shadow/ShadowPackageManagerWrapper.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settingslib.testutils.shadow;
-
-import android.content.Intent;
-import android.content.pm.ResolveInfo;
-import android.util.ArrayMap;
-
-import com.android.settingslib.wrapper.PackageManagerWrapper;
-
-import org.robolectric.annotation.Implementation;
-import org.robolectric.annotation.Implements;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-
-/**
- * Shadow for {@link PackageManagerWrapper} to allow stubbing hidden methods.
- */
-@Implements(PackageManagerWrapper.class)
-public class ShadowPackageManagerWrapper {
-    private static final Map<Intent, List<ResolveInfo>> intentServices = new ArrayMap<>();
-
-    @Implementation
-    public List<ResolveInfo> queryIntentServicesAsUser(Intent intent, int i, int user) {
-        List<ResolveInfo> list = intentServices.get(intent);
-        return list != null ? list : Collections.emptyList();
-    }
-
-    public static void addResolveInfoForIntent(Intent intent, ResolveInfo info) {
-        List<ResolveInfo> infoList = intentServices.computeIfAbsent(intent, k -> new ArrayList<>());
-        infoList.add(info);
-    }
-
-    public static void reset() {
-        intentServices.clear();
-    }
-}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/testutils/shadow/ShadowUserManager.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/testutils/shadow/ShadowUserManager.java
index c8b3269..a3e1bc8 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/testutils/shadow/ShadowUserManager.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/testutils/shadow/ShadowUserManager.java
@@ -25,7 +25,7 @@
 import org.robolectric.annotation.Resetter;
 import org.robolectric.shadow.api.Shadow;
 
-@Implements(UserManager.class)
+@Implements(value = UserManager.class, inheritImplementationMethods = true)
 public class ShadowUserManager extends org.robolectric.shadows.ShadowUserManager {
 
     private boolean mAdminUser;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/PowerUtilTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/PowerUtilTest.java
index f93210f..9285148f 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/PowerUtilTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/PowerUtilTest.java
@@ -20,20 +20,19 @@
 import static org.mockito.Mockito.spy;
 
 import android.content.Context;
+
 import com.android.settingslib.R;
 import com.android.settingslib.SettingsLibRobolectricTestRunner;
-import com.android.settingslib.TestConfig;
-import com.android.settingslib.utils.PowerUtil;
-import java.time.Duration;
+
 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;
+
+import java.time.Duration;
 
 @RunWith(SettingsLibRobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class PowerUtilTest {
     public static final String TEST_BATTERY_LEVEL_10 = "10%";
     public static final String FIFTEEN_MIN_FORMATTED = "15m";
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/StringUtilTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/StringUtilTest.java
index d5e3cdb..47dd022 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/StringUtilTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/StringUtilTest.java
@@ -23,16 +23,15 @@
 import android.text.SpannableStringBuilder;
 import android.text.format.DateUtils;
 import android.text.style.TtsSpan;
+
 import com.android.settingslib.SettingsLibRobolectricTestRunner;
-import com.android.settingslib.TestConfig;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
 
 @RunWith(SettingsLibRobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class StringUtilTest {
     private Context mContext;
 
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/ThreadUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/ThreadUtilsTest.java
index 5f6a5c8..83a9d5b 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/ThreadUtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/ThreadUtilsTest.java
@@ -19,16 +19,12 @@
 import static com.google.common.truth.Truth.assertThat;
 import static org.junit.Assert.fail;
 
-import com.android.settingslib.TestConfig;
-
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.robolectric.RobolectricTestRunner;
-import org.robolectric.annotation.Config;
 import org.robolectric.shadows.ShadowLooper;
 
 @RunWith(RobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class ThreadUtilsTest {
 
     @Test
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/AnimatedImageViewTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/AnimatedImageViewTest.java
index 2c9c868..36abd20 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/AnimatedImageViewTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/AnimatedImageViewTest.java
@@ -16,21 +16,19 @@
 
 package com.android.settingslib.widget;
 
+import static com.google.common.truth.Truth.assertThat;
+
 import android.app.Activity;
 import android.graphics.drawable.AnimatedRotateDrawable;
 import android.view.View;
-import com.android.settingslib.TestConfig;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.robolectric.Robolectric;
 import org.robolectric.RobolectricTestRunner;
-import org.robolectric.annotation.Config;
-
-import static com.google.common.truth.Truth.assertThat;
 
 @RunWith(RobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class AnimatedImageViewTest {
     private AnimatedImageView mAnimatedImageView;
 
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/FooterPreferenceMixinTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/FooterPreferenceMixinTest.java
index 88c57b5..8071c6db 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/FooterPreferenceMixinTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/FooterPreferenceMixinTest.java
@@ -29,7 +29,6 @@
 import android.support.v7.preference.PreferenceScreen;
 
 import com.android.settingslib.SettingsLibRobolectricTestRunner;
-import com.android.settingslib.TestConfig;
 import com.android.settingslib.core.lifecycle.Lifecycle;
 
 import org.junit.Before;
@@ -37,11 +36,9 @@
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
-import org.robolectric.annotation.Config;
 import org.robolectric.shadows.ShadowApplication;
 
 @RunWith(SettingsLibRobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class FooterPreferenceMixinTest {
 
     @Mock
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/FooterPreferenceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/FooterPreferenceTest.java
index 5d01027..ff11b80 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/FooterPreferenceTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/FooterPreferenceTest.java
@@ -16,6 +16,8 @@
 
 package com.android.settingslib.widget;
 
+import static com.google.common.truth.Truth.assertThat;
+
 import android.content.Context;
 import android.support.v7.preference.PreferenceViewHolder;
 import android.text.method.LinkMovementMethod;
@@ -24,18 +26,13 @@
 
 import com.android.settingslib.R;
 import com.android.settingslib.SettingsLibRobolectricTestRunner;
-import com.android.settingslib.TestConfig;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.robolectric.annotation.Config;
 import org.robolectric.shadows.ShadowApplication;
 
-import static com.google.common.truth.Truth.assertThat;
-
 @RunWith(SettingsLibRobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class FooterPreferenceTest {
 
     private Context mContext;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/AccessPointPreferenceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/AccessPointPreferenceTest.java
index 3fee16b..ee2c2ff 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/AccessPointPreferenceTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/AccessPointPreferenceTest.java
@@ -25,7 +25,6 @@
 import android.graphics.drawable.ColorDrawable;
 
 import com.android.settingslib.SettingsLibRobolectricTestRunner;
-import com.android.settingslib.TestConfig;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -33,10 +32,8 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
 
 @RunWith(SettingsLibRobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class AccessPointPreferenceTest {
 
     private Context mContext = RuntimeEnvironment.application;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/TimestampedScoredNetworkTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/TimestampedScoredNetworkTest.java
index b2d9d67b..f0e8c66 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/TimestampedScoredNetworkTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/TimestampedScoredNetworkTest.java
@@ -23,16 +23,14 @@
 import android.os.Parcel;
 
 import com.android.settingslib.SettingsLibRobolectricTestRunner;
-import com.android.settingslib.TestConfig;
-import java.util.Date;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
+
+import java.util.Date;
 
 @RunWith(SettingsLibRobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class TimestampedScoredNetworkTest {
   private TimestampedScoredNetwork impl;
 
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/WifiUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/WifiUtilsTest.java
index 9310b73..ea8ecba 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/WifiUtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/WifiUtilsTest.java
@@ -16,7 +16,6 @@
 package com.android.settingslib.wifi;
 
 import static com.google.common.truth.Truth.assertThat;
-
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.when;
@@ -35,7 +34,6 @@
 
 import com.android.settingslib.R;
 import com.android.settingslib.SettingsLibRobolectricTestRunner;
-import com.android.settingslib.TestConfig;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -43,12 +41,10 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
 
 import java.util.ArrayList;
 
 @RunWith(SettingsLibRobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class WifiUtilsTest {
     private static final String TEST_SSID = "\"test_ssid\"";
     private static final String TEST_BSSID = "00:00:00:00:00:00";
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index 39f2b52..1551b8e 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -1112,8 +1112,8 @@
                 Settings.Global.ZRAM_ENABLED,
                 GlobalSettingsProto.ZRAM_ENABLED);
         dumpSetting(s, p,
-                Settings.Global.ENABLE_SMART_REPLIES_IN_NOTIFICATIONS,
-                GlobalSettingsProto.ENABLE_SMART_REPLIES_IN_NOTIFICATIONS);
+                Settings.Global.SMART_REPLIES_IN_NOTIFICATIONS_FLAGS,
+                GlobalSettingsProto.SMART_REPLIES_IN_NOTIFICATIONS_FLAGS);
         dumpSetting(s, p,
                 Settings.Global.SHOW_FIRST_CRASH_DIALOG,
                 GlobalSettingsProto.SHOW_FIRST_CRASH_DIALOG);
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 79299aa..5c8d745 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -44,7 +44,6 @@
     <uses-permission android:name="android.permission.MANAGE_NETWORK_POLICY" />
     <uses-permission android:name="android.permission.MANAGE_USB" />
     <uses-permission android:name="android.permission.USE_RESERVED_DISK" />
-    <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
     <!-- System tool permissions granted to the shell. -->
     <uses-permission android:name="android.permission.REAL_GET_TASKS" />
     <uses-permission android:name="android.permission.CHANGE_CONFIGURATION" />
@@ -139,6 +138,11 @@
     <uses-permission android:name="android.permission.MANAGE_SENSORS" />
     <uses-permission android:name="android.permission.MANAGE_AUDIO_POLICY" />
     <uses-permission android:name="android.permission.MANAGE_CAMERA" />
+    <!-- Permission needed to enable/disable Bluetooth/Wifi when on permission review mode -->
+    <uses-permission
+        android:name="android.permission.MANAGE_BLUETOOTH_WHEN_PERMISSION_REVIEW_REQUIRED" />
+    <uses-permission
+        android:name="android.permission.MANAGE_WIFI_WHEN_PERMISSION_REVIEW_REQUIRED" />
 
     <application android:label="@string/app_label"
                  android:defaultToDeviceProtectedStorage="true"
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index cbb3e8f..35c4d59 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -110,7 +110,7 @@
     <uses-permission android:name="com.android.alarm.permission.SET_ALARM" />
 
     <!-- Keyguard -->
-    <uses-permission android:name="com.android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS" />
+    <uses-permission android:name="android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS" />
     <uses-permission android:name="android.permission.CONTROL_KEYGUARD" />
     <uses-permission android:name="android.permission.MODIFY_PHONE_STATE" />
     <uses-permission android:name="android.permission.GET_ACCOUNTS" />
@@ -381,6 +381,12 @@
             android:finishOnCloseSystemDialogs="true"
             android:excludeFromRecents="true">
         </activity>
+        <activity-alias
+            android:name=".UsbDebuggingActivityAlias"
+            android:permission="android.permission.DUMP"
+            android:targetActivity=".usb.UsbDebuggingActivity"
+            android:exported="true">
+        </activity-alias>
         <activity android:name=".usb.UsbDebuggingSecondaryUserActivity"
             android:theme="@style/Theme.SystemUI.Dialog.Alert"
             android:finishOnCloseSystemDialogs="true"
diff --git a/packages/SystemUI/res-keyguard/values-da/strings.xml b/packages/SystemUI/res-keyguard/values-da/strings.xml
index 156da2e..d9075aa 100644
--- a/packages/SystemUI/res-keyguard/values-da/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-da/strings.xml
@@ -53,6 +53,8 @@
     <string name="keyguard_accessibility_next_alarm" msgid="5835196989158584991">"Næste alarm er indstillet til <xliff:g id="ALARM">%1$s</xliff:g>"</string>
     <string name="keyboardview_keycode_delete" msgid="6883116827512721630">"Slet"</string>
     <string name="disable_carrier_button_text" msgid="6914341927421916114">"Deaktiver eSIM"</string>
+    <string name="error_disable_esim_title" msgid="4852978431156228006">"eSIM kan ikke deaktiveres"</string>
+    <string name="error_disable_esim_msg" msgid="676694908770135639">"eSIM kan ikke deaktiveres på grund af en fejl."</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"Enter"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"Har du glemt mønsteret?"</string>
     <string name="kg_wrong_pattern" msgid="7620081431514773802">"Forkert mønster"</string>
@@ -65,7 +67,7 @@
     <string name="kg_pattern_instructions" msgid="5547646893001491340">"Tegn dit mønster"</string>
     <string name="kg_sim_pin_instructions" msgid="6389000973113699187">"Angiv pinkoden til SIM-kortet."</string>
     <string name="kg_sim_pin_instructions_multi" msgid="1643757228644271861">"Angiv pinkoden til SIM-kortet fra \"<xliff:g id="CARRIER">%1$s</xliff:g>\"."</string>
-    <string name="kg_sim_lock_instructions_esim" msgid="4957650659201013804">"Deaktiver eSIM for at bruge enheden uden mobiltjeneste."</string>
+    <string name="kg_sim_lock_esim_instructions" msgid="4416732549172148542">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> Deaktiver eSIM for at bruge enheden uden mobiltjeneste."</string>
     <string name="kg_pin_instructions" msgid="4069609316644030034">"Indtast pinkode"</string>
     <string name="kg_password_instructions" msgid="136952397352976538">"Angiv adgangskode"</string>
     <string name="kg_puk_enter_puk_hint" msgid="2288964170039899277">"SIM-kortet er nu deaktiveret. Indtast PUK-koden for at fortsætte. Kontakt mobilselskabet for at få flere oplysninger."</string>
diff --git a/packages/SystemUI/res-keyguard/values-eu/strings.xml b/packages/SystemUI/res-keyguard/values-eu/strings.xml
index 3d79ae2..a5aa06e 100644
--- a/packages/SystemUI/res-keyguard/values-eu/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-eu/strings.xml
@@ -53,6 +53,8 @@
     <string name="keyguard_accessibility_next_alarm" msgid="5835196989158584991">"Hurrengo alarmak ordu honetan joko du: <xliff:g id="ALARM">%1$s</xliff:g>"</string>
     <string name="keyboardview_keycode_delete" msgid="6883116827512721630">"Ezabatu"</string>
     <string name="disable_carrier_button_text" msgid="6914341927421916114">"Desgaitu eSIM txartela"</string>
+    <string name="error_disable_esim_title" msgid="4852978431156228006">"Ezin da desgaitu eSIM txartela"</string>
+    <string name="error_disable_esim_msg" msgid="676694908770135639">"Errore bat gertatu da eta ezin da desgaitu eSIM txartela."</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"Sartu"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"Eredua ahaztu zaizu"</string>
     <string name="kg_wrong_pattern" msgid="7620081431514773802">"Eredu hori ez da zuzena"</string>
@@ -65,7 +67,7 @@
     <string name="kg_pattern_instructions" msgid="5547646893001491340">"Marraztu eredua"</string>
     <string name="kg_sim_pin_instructions" msgid="6389000973113699187">"Idatzi SIM txartelaren PIN kodea."</string>
     <string name="kg_sim_pin_instructions_multi" msgid="1643757228644271861">"Idatzi \"<xliff:g id="CARRIER">%1$s</xliff:g>\" operadorearen SIM txartelaren PIN kodea."</string>
-    <string name="kg_sim_lock_instructions_esim" msgid="4957650659201013804">"Desgaitu eSIM txartela gailua zerbitzu mugikorrik gabe erabiltzeko."</string>
+    <string name="kg_sim_lock_esim_instructions" msgid="4416732549172148542">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> Desgaitu eSIM txartela gailua zerbitzu mugikorrik gabe erabiltzeko."</string>
     <string name="kg_pin_instructions" msgid="4069609316644030034">"Idatzi PIN kodea"</string>
     <string name="kg_password_instructions" msgid="136952397352976538">"Idatzi pasahitza"</string>
     <string name="kg_puk_enter_puk_hint" msgid="2288964170039899277">"Desgaitu egin da SIM txartela. Aurrera egiteko, idatzi PUK kodea. Xehetasunak lortzeko, jarri operadorearekin harremanetan."</string>
diff --git a/packages/SystemUI/res-keyguard/values-hy/strings.xml b/packages/SystemUI/res-keyguard/values-hy/strings.xml
index 2936935..fec903e 100644
--- a/packages/SystemUI/res-keyguard/values-hy/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-hy/strings.xml
@@ -53,6 +53,8 @@
     <string name="keyguard_accessibility_next_alarm" msgid="5835196989158584991">"Հաջորդ զարթուցիչը դրված է <xliff:g id="ALARM">%1$s</xliff:g>-ի վրա"</string>
     <string name="keyboardview_keycode_delete" msgid="6883116827512721630">"Ջնջել"</string>
     <string name="disable_carrier_button_text" msgid="6914341927421916114">"Անջատել էլեկտրոնային SIM քարտը"</string>
+    <string name="error_disable_esim_title" msgid="4852978431156228006">"Չհաջողվեց անջատել eSIM-ը"</string>
+    <string name="error_disable_esim_msg" msgid="676694908770135639">"Սխալի պատճառով չհաջողվեց անջատել eSIM-ը։"</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"Մուտքի ստեղն"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"Մոռացել եմ նախշը"</string>
     <string name="kg_wrong_pattern" msgid="7620081431514773802">"Նախշը սխալ է"</string>
@@ -65,7 +67,7 @@
     <string name="kg_pattern_instructions" msgid="5547646893001491340">"Մուտքագրեք նախշը"</string>
     <string name="kg_sim_pin_instructions" msgid="6389000973113699187">"Մուտքագրեք SIM քարտի PIN կոդը։"</string>
     <string name="kg_sim_pin_instructions_multi" msgid="1643757228644271861">"Մուտքագրեք SIM քարտի PIN կոդը «<xliff:g id="CARRIER">%1$s</xliff:g>»-ի համար:"</string>
-    <string name="kg_sim_lock_instructions_esim" msgid="4957650659201013804">"Անջատել էլեկտրոնային SIM քարտը՝ սարքն առանց բջջային ծառայությունների օգտագործելու համար:"</string>
+    <string name="kg_sim_lock_esim_instructions" msgid="4416732549172148542">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> Անջատեք eSIM-ը՝ սարքն առանց բջջային կապի օգտագործելու համար։"</string>
     <string name="kg_pin_instructions" msgid="4069609316644030034">"Մուտքագրեք PIN-ը"</string>
     <string name="kg_password_instructions" msgid="136952397352976538">"Մուտքագրեք գաղտնաբառը"</string>
     <string name="kg_puk_enter_puk_hint" msgid="2288964170039899277">"SIM քարտն այժմ անջատված է: Շարունակելու համար մուտքագրեք PUK կոդը: Մանրամասն տեղեկություններ ստանալու համար դիմեք օպերատորին:"</string>
diff --git a/packages/SystemUI/res-keyguard/values-uz/strings.xml b/packages/SystemUI/res-keyguard/values-uz/strings.xml
index 3272cb2..07198c7c 100644
--- a/packages/SystemUI/res-keyguard/values-uz/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-uz/strings.xml
@@ -53,10 +53,8 @@
     <string name="keyguard_accessibility_next_alarm" msgid="5835196989158584991">"Signal <xliff:g id="ALARM">%1$s</xliff:g> da chalinadi."</string>
     <string name="keyboardview_keycode_delete" msgid="6883116827512721630">"O‘chirib tashlash"</string>
     <string name="disable_carrier_button_text" msgid="6914341927421916114">"eSIMni faolsizlantirish"</string>
-    <!-- no translation found for error_disable_esim_title (4852978431156228006) -->
-    <skip />
-    <!-- no translation found for error_disable_esim_msg (676694908770135639) -->
-    <skip />
+    <string name="error_disable_esim_title" msgid="4852978431156228006">"eSIM faolsizlantirilmadi"</string>
+    <string name="error_disable_esim_msg" msgid="676694908770135639">"Xatolik tufayli eSIM faolsizlantirilmadi."</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"Enter tugmasi"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"Grafik kalit esimdan chiqdi"</string>
     <string name="kg_wrong_pattern" msgid="7620081431514773802">"Grafik kalit xato"</string>
@@ -69,8 +67,7 @@
     <string name="kg_pattern_instructions" msgid="5547646893001491340">"Grafik kalit chizing"</string>
     <string name="kg_sim_pin_instructions" msgid="6389000973113699187">"SIM karta PIN kodini kiriting."</string>
     <string name="kg_sim_pin_instructions_multi" msgid="1643757228644271861">"“<xliff:g id="CARRIER">%1$s</xliff:g>” SIM kartasi PIN kodini kiriting."</string>
-    <!-- no translation found for kg_sim_lock_esim_instructions (4416732549172148542) -->
-    <skip />
+    <string name="kg_sim_lock_esim_instructions" msgid="4416732549172148542">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> Qurilmadan mobil xizmatlarsiz foydalanish uchun eSIMni faolsizlantiring."</string>
     <string name="kg_pin_instructions" msgid="4069609316644030034">"PIN kodni kiriting"</string>
     <string name="kg_password_instructions" msgid="136952397352976538">"Parol kiriting"</string>
     <string name="kg_puk_enter_puk_hint" msgid="2288964170039899277">"SIM karta hozir o‘chirilgan. Davom etish uchun PUK kodni kiriting. Batafsil axborot olish uchun tarmoq operatori bilan bog‘laning."</string>
diff --git a/packages/SystemUI/res-keyguard/values/dimens.xml b/packages/SystemUI/res-keyguard/values/dimens.xml
index 28a0935..4934e14 100644
--- a/packages/SystemUI/res-keyguard/values/dimens.xml
+++ b/packages/SystemUI/res-keyguard/values/dimens.xml
@@ -44,13 +44,13 @@
     <!-- Default clock parameters -->
     <dimen name="bottom_text_spacing_digital">-24dp</dimen>
     <!-- Slice header -->
-    <dimen name="widget_title_font_size">28sp</dimen>
+    <dimen name="widget_title_font_size">24sp</dimen>
     <!-- Slice subtitle  -->
     <dimen name="widget_label_font_size">16sp</dimen>
     <!-- Clock without header -->
     <dimen name="widget_big_font_size">64dp</dimen>
     <!-- Clock with header -->
-    <dimen name="widget_small_font_size">22dp</dimen>
+    <dimen name="widget_small_font_size">24dp</dimen>
     <!-- Dash between clock and header -->
     <dimen name="widget_separator_width">16dp</dimen>
     <dimen name="widget_separator_thickness">1dp</dimen>
diff --git a/core/res/res/color/watch_switch_track_color_material.xml b/packages/SystemUI/res/color/accent_tint_color_selector.xml
similarity index 77%
copy from core/res/res/color/watch_switch_track_color_material.xml
copy to packages/SystemUI/res/color/accent_tint_color_selector.xml
index c7dc5d3..85af186 100644
--- a/core/res/res/color/watch_switch_track_color_material.xml
+++ b/packages/SystemUI/res/color/accent_tint_color_selector.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2016 The Android Open Source Project
+<!-- 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.
@@ -13,10 +13,9 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
     <item android:state_enabled="false"
-          android:alpha="?attr/disabledAlpha"
-          android:color="?android:colorPrimary" />
-    <item android:color="?android:colorPrimary" />
+          android:color="?android:attr/colorButtonNormal"/>
+
+    <item android:color="?android:attr/colorAccent"/>
 </selector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_sysbar_back_quick_step.png b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_sysbar_back_quick_step.png
new file mode 100644
index 0000000..2d62a80
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_sysbar_back_quick_step.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_sysbar_back_quick_step_dark.png b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_sysbar_back_quick_step_dark.png
new file mode 100644
index 0000000..a52e5b1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_sysbar_back_quick_step_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back_ime_quick_step.png b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back_ime_quick_step.png
new file mode 100644
index 0000000..d13c730
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back_ime_quick_step.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back_ime_quick_step_dark.png b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back_ime_quick_step_dark.png
new file mode 100644
index 0000000..31c602e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back_ime_quick_step_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back_quick_step.png b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back_quick_step.png
new file mode 100644
index 0000000..ddbcb07
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back_quick_step.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back_quick_step_dark.png b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back_quick_step_dark.png
new file mode 100644
index 0000000..ce91fcbb
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back_quick_step_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_home_quick_step.png b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_home_quick_step.png
new file mode 100644
index 0000000..c606a58
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_home_quick_step.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_home_quick_step_dark.png b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_home_quick_step_dark.png
new file mode 100644
index 0000000..c2a5fef
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_home_quick_step_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/layout/volume_dialog.xml b/packages/SystemUI/res/layout/volume_dialog.xml
index bab4eba7..803659f 100644
--- a/packages/SystemUI/res/layout/volume_dialog.xml
+++ b/packages/SystemUI/res/layout/volume_dialog.xml
@@ -38,59 +38,64 @@
             android:layout_height="wrap_content"
             android:clipChildren="false"
             android:clipToPadding="false"
-            android:paddingTop="10dp"
-            android:paddingBottom="10dp"
             android:background="@drawable/rounded_bg_full"
             android:translationZ="@dimen/volume_panel_elevation"
             android:orientation="horizontal" >
                 <!-- volume rows added and removed here! :-) -->
         </LinearLayout>
 
-        <LinearLayout
+        <FrameLayout
             android:id="@+id/footer"
             android:layout_width="@dimen/volume_dialog_panel_width"
             android:layout_height="@dimen/volume_dialog_panel_width"
-            android:clipChildren="false"
-            android:clipToPadding="false"
             android:layout_marginTop="6dp"
             android:layout_marginBottom="6dp"
             android:layout_below="@id/volume_dialog_rows"
-            android:background="@drawable/rounded_bg_full"
-            android:gravity="center"
-            android:layout_gravity="end"
-            android:translationZ="@dimen/volume_panel_elevation"
-            android:clickable="true"
-            android:orientation="vertical" >
+            android:background="@drawable/rounded_bg_full">
 
-            <TextView
-                android:id="@+id/ringer_title"
-                android:text="@string/ring_toggle_title"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:ellipsize="end"
-                android:maxLines="1"
-                android:layout_centerVertical="true"
-                android:textColor="?android:attr/colorControlNormal"
-                android:textAppearance="@style/TextAppearance.Volume.Header" />
+            <LinearLayout
+                android:id="@+id/footer_linear_layout"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:clipChildren="false"
+                android:clipToPadding="false"
+                android:gravity="center"
+                android:layout_gravity="end"
+                android:translationZ="@dimen/volume_panel_elevation"
+                android:clickable="true"
+                android:orientation="vertical" >
 
-            <com.android.keyguard.AlphaOptimizedImageButton
-                android:id="@+id/ringer_icon"
-                style="@style/VolumeButtons"
-                android:background="?android:selectableItemBackgroundBorderless"
-                android:layout_width="@dimen/volume_dialog_panel_width"
-                android:layout_height="@dimen/volume_button_size"
-                android:tint="?android:attr/colorAccent"
-                android:soundEffectsEnabled="false" />
+                <TextView
+                    android:id="@+id/ringer_title"
+                    android:text="@string/ring_toggle_title"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:ellipsize="end"
+                    android:maxLines="1"
+                    android:layout_centerVertical="true"
+                    android:textColor="?android:attr/colorControlNormal"
+                    android:textAppearance="@style/TextAppearance.Volume.Header" />
 
-            <TextView
-                android:id="@+id/ringer_status"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:ellipsize="end"
-                android:maxLines="1"
-                android:textColor="?android:attr/colorControlNormal"
-                android:textAppearance="@style/TextAppearance.Volume.Header.Secondary" />
+                <com.android.keyguard.AlphaOptimizedImageButton
+                    android:id="@+id/ringer_icon"
+                    style="@style/VolumeButtons"
+                    android:background="?android:selectableItemBackgroundBorderless"
+                    android:layout_width="@dimen/volume_dialog_panel_width"
+                    android:layout_height="@dimen/volume_button_size"
+                    android:tint="@color/accent_tint_color_selector"
+                    android:soundEffectsEnabled="false" />
 
-        </LinearLayout>
+                <TextView
+                    android:id="@+id/ringer_status"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:ellipsize="end"
+                    android:maxLines="1"
+                    android:textColor="?android:attr/colorControlNormal"
+                    android:textAppearance="@style/TextAppearance.Volume.Header.Secondary" />
+            </LinearLayout>
+
+            <include layout="@layout/volume_dnd_icon"/>
+        </FrameLayout>
     </LinearLayout>
 </com.android.systemui.volume.VolumeUiLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/volume_dialog_row.xml b/packages/SystemUI/res/layout/volume_dialog_row.xml
index 70654a8..fb9355a 100644
--- a/packages/SystemUI/res/layout/volume_dialog_row.xml
+++ b/packages/SystemUI/res/layout/volume_dialog_row.xml
@@ -13,89 +13,98 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<LinearLayout
+<FrameLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:tag="row"
     android:layout_height="wrap_content"
     android:layout_width="@dimen/volume_dialog_panel_width"
     android:clipChildren="true"
     android:clipToPadding="true"
-    android:theme="@style/qs_theme"
-    android:gravity="center"
-    android:orientation="vertical" >
+    android:theme="@style/qs_theme">
 
     <LinearLayout
-        android:orientation="vertical"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
+        android:layout_height="match_parent"
+        android:layout_width="match_parent"
+        android:layout_marginTop="10dp"
+        android:layout_marginBottom="10dp"
         android:gravity="center"
-        android:padding="5dp">
-        <TextView
-            android:id="@+id/volume_row_header"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:ellipsize="end"
-            android:maxLength="10"
-            android:maxLines="1"
-            android:textColor="?android:attr/colorControlNormal"
-            android:textAppearance="@style/TextAppearance.Volume.Header" />
+        android:orientation="vertical" >
+
         <LinearLayout
-            android:id="@+id/output_chooser"
             android:orientation="vertical"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:minWidth="48dp"
-            android:minHeight="48dp"
-            android:paddingTop="10dp"
-            android:background="?android:selectableItemBackgroundBorderless"
-            android:gravity="center">
+            android:gravity="center"
+            android:padding="5dp">
             <TextView
-                android:id="@+id/volume_row_connected_device"
-                android:visibility="gone"
+                android:id="@+id/volume_row_header"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:maxLength="10"
                 android:ellipsize="end"
+                android:maxLength="10"
                 android:maxLines="1"
-                android:textAppearance="@style/TextAppearance.Volume.Header.Secondary" />
-            <com.android.keyguard.AlphaOptimizedImageButton
-                android:id="@+id/output_chooser_button"
-                android:layout_width="24dp"
-                android:layout_height="24dp"
+                android:textColor="?android:attr/colorControlNormal"
+                android:textAppearance="@style/TextAppearance.Volume.Header" />
+            <LinearLayout
+                android:id="@+id/output_chooser"
+                android:orientation="vertical"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:minWidth="48dp"
+                android:minHeight="48dp"
+                android:paddingTop="10dp"
                 android:background="?android:selectableItemBackgroundBorderless"
-                android:contentDescription="@string/accessibility_output_chooser"
-                style="@style/VolumeButtons"
-                android:clickable="false"
-                android:layout_centerVertical="true"
-                android:src="@drawable/ic_swap"
-                android:soundEffectsEnabled="false" />
+                android:gravity="center">
+                <TextView
+                    android:id="@+id/volume_row_connected_device"
+                    android:visibility="gone"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:maxLength="10"
+                    android:ellipsize="end"
+                    android:maxLines="1"
+                    android:textAppearance="@style/TextAppearance.Volume.Header.Secondary" />
+                <com.android.keyguard.AlphaOptimizedImageButton
+                    android:id="@+id/output_chooser_button"
+                    android:layout_width="24dp"
+                    android:layout_height="24dp"
+                    android:background="?android:selectableItemBackgroundBorderless"
+                    android:contentDescription="@string/accessibility_output_chooser"
+                    style="@style/VolumeButtons"
+                    android:clickable="false"
+                    android:layout_centerVertical="true"
+                    android:src="@drawable/ic_swap"
+                    android:soundEffectsEnabled="false"/>
+            </LinearLayout>
         </LinearLayout>
-    </LinearLayout>
-    <FrameLayout
-        android:id="@+id/volume_row_slider_frame"
-        android:padding="0dp"
-        android:layout_width="@dimen/volume_dialog_panel_width"
-        android:layoutDirection="rtl"
-        android:layout_height="@dimen/volume_dialog_panel_width">
-        <SeekBar
-            android:id="@+id/volume_row_slider"
-            android:clickable="true"
+        <FrameLayout
+            android:id="@+id/volume_row_slider_frame"
             android:padding="0dp"
-            android:layout_margin="0dp"
             android:layout_width="@dimen/volume_dialog_panel_width"
-            android:layout_height="@dimen/volume_dialog_panel_width"
             android:layoutDirection="rtl"
-            android:layout_gravity="center"
-            android:rotation="90" />
-    </FrameLayout>
+            android:layout_height="@dimen/volume_dialog_panel_width">
+            <SeekBar
+                android:id="@+id/volume_row_slider"
+                android:clickable="true"
+                android:padding="0dp"
+                android:layout_margin="0dp"
+                android:layout_width="@dimen/volume_dialog_panel_width"
+                android:layout_height="@dimen/volume_dialog_panel_width"
+                android:layoutDirection="rtl"
+                android:layout_gravity="center"
+                android:rotation="90" />
+        </FrameLayout>
 
-    <com.android.keyguard.AlphaOptimizedImageButton
-        android:id="@+id/volume_row_icon"
-        style="@style/VolumeButtons"
-        android:padding="10dp"
-        android:layout_width="@dimen/volume_button_size"
-        android:layout_height="@dimen/volume_button_size"
-        android:background="?android:selectableItemBackgroundBorderless"
-        android:soundEffectsEnabled="false" />
+        <com.android.keyguard.AlphaOptimizedImageButton
+            android:id="@+id/volume_row_icon"
+            style="@style/VolumeButtons"
+            android:padding="10dp"
+            android:layout_width="@dimen/volume_button_size"
+            android:layout_height="@dimen/volume_button_size"
+            android:background="?android:selectableItemBackgroundBorderless"
+            android:soundEffectsEnabled="false" />
+    </LinearLayout>
 
-</LinearLayout>
\ No newline at end of file
+    <include layout="@layout/volume_dnd_icon"/>
+
+</FrameLayout>
diff --git a/packages/SystemUI/res/layout/volume_dnd_icon.xml b/packages/SystemUI/res/layout/volume_dnd_icon.xml
new file mode 100644
index 0000000..215b230
--- /dev/null
+++ b/packages/SystemUI/res/layout/volume_dnd_icon.xml
@@ -0,0 +1,30 @@
+<!--
+     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.
+-->
+<FrameLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="14dp"
+    android:layout_height="14dp"
+    android:layout_marginTop="6dp"
+    android:layout_marginRight="6dp"
+    android:layout_gravity="right|top">
+
+    <ImageView
+        android:id="@+id/dnd_icon"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:src="@drawable/ic_dnd"
+        android:tint="?android:attr/textColorTertiary"/>
+</FrameLayout>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 39895acb..9ebd492 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -103,12 +103,9 @@
     <string name="camera_label" msgid="7261107956054836961">"åbn kamera"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"Vælg nyt opgavelayout"</string>
     <string name="cancel" msgid="6442560571259935130">"Annuller"</string>
-    <!-- no translation found for accessibility_fingerprint_dialog_fingerprint_icon (3125122495414253226) -->
-    <skip />
-    <!-- no translation found for accessibility_fingerprint_dialog_app_icon (3228052542929174609) -->
-    <skip />
-    <!-- no translation found for accessibility_fingerprint_dialog_help_area (5730471601819225159) -->
-    <skip />
+    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Ikon for fingeraftryk"</string>
+    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"Appens ikon"</string>
+    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"Område med hjælpemeddelelse"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Knap for kompatibilitetszoom."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoom mindre til større skærm."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth tilsluttet."</string>
@@ -311,6 +308,7 @@
     <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi slået fra"</string>
     <string name="quick_settings_wifi_on_label" msgid="7607810331387031235">"Wi-Fi er slået til"</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="269990350383909226">"Der er ingen tilgængelige Wi-Fi-netværk"</string>
+    <string name="quick_settings_alarm_title" msgid="2416759007342260676">"Alarm"</string>
     <string name="quick_settings_cast_title" msgid="7709016546426454729">"Cast"</string>
     <string name="quick_settings_casting" msgid="6601710681033353316">"Caster"</string>
     <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"Enhed uden navn"</string>
@@ -327,9 +325,11 @@
     <string name="quick_settings_connecting" msgid="47623027419264404">"Opretter forbindelse…"</string>
     <string name="quick_settings_tethering_label" msgid="7153452060448575549">"Netdeling"</string>
     <string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Hotspot"</string>
-    <!-- no translation found for quick_settings_hotspot_secondary_label_transient (7161046712706277215) -->
-    <skip />
-    <!-- no translation found for quick_settings_hotspot_secondary_label_num_devices (2324635800672199428) -->
+    <string name="quick_settings_hotspot_secondary_label_transient" msgid="7161046712706277215">"Aktiverer…"</string>
+    <plurals name="quick_settings_hotspot_secondary_label_num_devices" formatted="false" msgid="2324635800672199428">
+      <item quantity="one">%d enhed</item>
+      <item quantity="other">%d enheder</item>
+    </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Underretninger"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Lommelygte"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Mobildata"</string>
@@ -339,10 +339,8 @@
     <string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> brugt"</string>
     <string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"Grænse: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Advarsel ved <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
-    <!-- no translation found for quick_settings_work_mode_on_label (3421274215098764735) -->
-    <skip />
-    <!-- no translation found for quick_settings_work_mode_off_label (8856918707867192186) -->
-    <skip />
+    <string name="quick_settings_work_mode_on_label" msgid="3421274215098764735">"Arbejdsprofil"</string>
+    <string name="quick_settings_work_mode_off_label" msgid="8856918707867192186">"Underretninger og apps er slået fra"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Nattelys"</string>
     <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"Tænd ved solnedgang"</string>
     <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"Indtil solopgang"</string>
@@ -360,8 +358,6 @@
     <string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> er deaktiveret i sikker tilstand."</string>
     <string name="recents_stack_action_button_label" msgid="6593727103310426253">"Ryd alle"</string>
     <string name="recents_drag_hint_message" msgid="2649739267073203985">"Træk hertil for at bruge delt skærm"</string>
-    <!-- no translation found for recents_swipe_up_onboarding (3824607135920170001) -->
-    <skip />
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Opdel vandret"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Opdel lodret"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Opdel brugerdefineret"</string>
@@ -502,11 +498,18 @@
     <string name="volume_zen_end_now" msgid="6930243045593601084">"Deaktiver nu"</string>
     <string name="accessibility_volume_expand" msgid="5946812790999244205">"Udvid"</string>
     <string name="accessibility_volume_collapse" msgid="3609549593031810875">"Skjul"</string>
+    <string name="accessibility_output_chooser" msgid="8185317493017988680">"Skift enhed til lydudgang"</string>
     <string name="screen_pinning_title" msgid="3273740381976175811">"Skærmen er fastgjort"</string>
     <string name="screen_pinning_description" msgid="8909878447196419623">"Dette fastholder skærmen i visningen, indtil du frigør den. Tryk på Tilbage og Overblik, og hold fingeren nede for at frigøre skærmen."</string>
+    <string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"Dette fastholder skærmen i visningen, indtil du frigør den. Hold Tilbage og Startskærm nede for at frigøre skærmen."</string>
     <string name="screen_pinning_description_accessible" msgid="426190689254018656">"Dette fastholder skærmen i visningen, indtil du frigør den. Tryk på Tilbage, og hold fingeren nede for at frigøre skærmen."</string>
+    <string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"Dette fastholder skærmen i visningen, indtil du frigør den. Hold Startskærm nede for at frigøre skærmen."</string>
+    <string name="screen_pinning_toast" msgid="2266705122951934150">"Hold knapperne Tilbage og Oversigt nede for at frigøre skærmen"</string>
+    <string name="screen_pinning_toast_recents_invisible" msgid="8252402309499161281">"Hold knapperne Tilbage og Startskærm nede for at frigøre skærmen"</string>
     <string name="screen_pinning_positive" msgid="3783985798366751226">"OK, det er forstået"</string>
     <string name="screen_pinning_negative" msgid="3741602308343880268">"Nej tak"</string>
+    <string name="screen_pinning_start" msgid="1022122128489278317">"Skærmen blev fastgjort"</string>
+    <string name="screen_pinning_exit" msgid="5187339744262325372">"Skærmen blev frigjort"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Vil du skjule <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
     <string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Den vises igen, næste gang du aktiverer den i indstillingerne."</string>
     <string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Skjul"</string>
@@ -586,8 +589,7 @@
     <string name="power_notification_controls_description" msgid="4372459941671353358">"Med kontrolelementer til underretninger om strøm kan du konfigurere et vigtighedsniveau fra 0 til 5 for en apps underretninger. \n\n"<b>"Niveau 5"</b>\n"- Vis øverst på listen over underretninger \n- Tillad afbrydelse af fuld skærm \n- Se altid smugkig \n\n"<b>"Niveau 4"</b>\n"- Ingen afbrydelse af fuld skærm \n- Se altid smugkig \n\n"<b>"Niveau 3"</b>\n"- Ingen afbrydelse af fuld skærm \n- Se aldrig smugkig \n\n"<b>"Niveau 2"</b>\n"- Ingen afbrydelse af fuld skærm \n Se aldrig smugkig \n- Ingen lyd og vibration \n\n"<b>"Niveau 1"</b>\n"- Ingen afbrydelse af fuld skærm \n- Se aldrig smugkig \n- Ingen lyd eller vibration \n- Skjul fra låseskærm og statusbjælke \n- Vis nederst på listen over underretninger \n\n"<b>"Niveau 0"</b>\n"- Bloker alle underretninger fra appen."</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Underretninger"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"Du får ikke længere vist disse underretninger"</string>
-    <!-- no translation found for inline_blocking_helper (3055064577771478591) -->
-    <skip />
+    <string name="inline_blocking_helper" msgid="3055064577771478591">"Du afviser som regel disse underretninger. \nVil du blive ved med at se dem?"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"Vil du fortsætte med at se disse underretninger?"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"Stop underretninger"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"Fortsæt med at vise underretninger"</string>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index 1c46eba..9b52656 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -103,12 +103,9 @@
     <string name="camera_label" msgid="7261107956054836961">"ireki kamera"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"Hautatu zereginen diseinua"</string>
     <string name="cancel" msgid="6442560571259935130">"Utzi"</string>
-    <!-- no translation found for accessibility_fingerprint_dialog_fingerprint_icon (3125122495414253226) -->
-    <skip />
-    <!-- no translation found for accessibility_fingerprint_dialog_app_icon (3228052542929174609) -->
-    <skip />
-    <!-- no translation found for accessibility_fingerprint_dialog_help_area (5730471601819225159) -->
-    <skip />
+    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Hatz-markaren ikonoa"</string>
+    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"Aplikazioaren ikonoa"</string>
+    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"Laguntza-mezuaren eremua"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Zoom-bateragarritasunaren botoia."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Handiagotu pantaila txikia."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetootha konektatuta."</string>
@@ -313,6 +310,7 @@
     <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi konexioa desaktibatuta"</string>
     <string name="quick_settings_wifi_on_label" msgid="7607810331387031235">"Aktibatuta dago Wi-Fi konexioa"</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="269990350383909226">"Ez dago Wi-Fi sarerik erabilgarri"</string>
+    <string name="quick_settings_alarm_title" msgid="2416759007342260676">"Alarma"</string>
     <string name="quick_settings_cast_title" msgid="7709016546426454729">"Cast"</string>
     <string name="quick_settings_casting" msgid="6601710681033353316">"Igortzen"</string>
     <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"Izenik gabeko gailua"</string>
@@ -329,9 +327,11 @@
     <string name="quick_settings_connecting" msgid="47623027419264404">"Konektatzen…"</string>
     <string name="quick_settings_tethering_label" msgid="7153452060448575549">"Konexioa partekatzea"</string>
     <string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Sare publikoa"</string>
-    <!-- no translation found for quick_settings_hotspot_secondary_label_transient (7161046712706277215) -->
-    <skip />
-    <!-- no translation found for quick_settings_hotspot_secondary_label_num_devices (2324635800672199428) -->
+    <string name="quick_settings_hotspot_secondary_label_transient" msgid="7161046712706277215">"Aktibatzen…"</string>
+    <plurals name="quick_settings_hotspot_secondary_label_num_devices" formatted="false" msgid="2324635800672199428">
+      <item quantity="other">%d gailu</item>
+      <item quantity="one">%d gailu</item>
+    </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Jakinarazpenak"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Linterna"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Datu mugikorrak"</string>
@@ -341,10 +341,8 @@
     <string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> erabilita"</string>
     <string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"Muga: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Abisua: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
-    <!-- no translation found for quick_settings_work_mode_on_label (3421274215098764735) -->
-    <skip />
-    <!-- no translation found for quick_settings_work_mode_off_label (8856918707867192186) -->
-    <skip />
+    <string name="quick_settings_work_mode_on_label" msgid="3421274215098764735">"Laneko profila"</string>
+    <string name="quick_settings_work_mode_off_label" msgid="8856918707867192186">"Jakinarazpenak eta aplikazioak desaktibatuta daude"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Gaueko argia"</string>
     <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"Ilunabarrean"</string>
     <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"Ilunabarrera arte"</string>
@@ -362,8 +360,6 @@
     <string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> desgaituta dago modu seguruan."</string>
     <string name="recents_stack_action_button_label" msgid="6593727103310426253">"Garbitu guztiak"</string>
     <string name="recents_drag_hint_message" msgid="2649739267073203985">"Arrastatu hau pantaila zatitzeko"</string>
-    <!-- no translation found for recents_swipe_up_onboarding (3824607135920170001) -->
-    <skip />
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Zatitze horizontala"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Zatitze bertikala"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Zatitze pertsonalizatua"</string>
@@ -504,11 +500,18 @@
     <string name="volume_zen_end_now" msgid="6930243045593601084">"Desaktibatu"</string>
     <string name="accessibility_volume_expand" msgid="5946812790999244205">"Zabaldu"</string>
     <string name="accessibility_volume_collapse" msgid="3609549593031810875">"Tolestu"</string>
+    <string name="accessibility_output_chooser" msgid="8185317493017988680">"Aldatu irteerako gailua"</string>
     <string name="screen_pinning_title" msgid="3273740381976175811">"Pantaila ainguratuta dago"</string>
     <string name="screen_pinning_description" msgid="8909878447196419623">"Horrela, ikusgai egongo da aingura kendu arte. Aingura kentzeko, eduki sakatuta \"Atzera\" eta \"Ikuspegi orokorra\" botoiak."</string>
+    <string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"Horrela, ikusgai egongo da aingura kendu arte. Aingura kentzeko, eduki sakatuta Atzera eta Hasiera botoiak."</string>
     <string name="screen_pinning_description_accessible" msgid="426190689254018656">"Horrela, ikusgai egongo da aingura kendu arte. Aingura kentzeko, eduki sakatuta \"Ikuspegi orokorra\" botoia."</string>
+    <string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"Horrela, ikusgai egongo da aingura kendu arte. Aingura kentzeko, eduki sakatuta Hasiera botoia."</string>
+    <string name="screen_pinning_toast" msgid="2266705122951934150">"Pantailari aingura kentzeko, eduki sakatuta Atzera eta Ikuspegi orokorra botoiak"</string>
+    <string name="screen_pinning_toast_recents_invisible" msgid="8252402309499161281">"Pantailari aingura kentzeko, eduki sakatuta Atzera eta Hasiera botoiak"</string>
     <string name="screen_pinning_positive" msgid="3783985798366751226">"Ados"</string>
     <string name="screen_pinning_negative" msgid="3741602308343880268">"Ez, eskerrik asko"</string>
+    <string name="screen_pinning_start" msgid="1022122128489278317">"Ainguratu da pantaila"</string>
+    <string name="screen_pinning_exit" msgid="5187339744262325372">"Kendu zaio aingura pantailari"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g> ezkutatu nahi duzu?"</string>
     <string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Ezarpenetan aktibatzen duzun hurrengoan agertuko da berriro."</string>
     <string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Ezkutatu"</string>
@@ -588,8 +591,7 @@
     <string name="power_notification_controls_description" msgid="4372459941671353358">"Bateria-mailaren arabera jakinarazpenak kontrolatzeko aukerekin, 0 eta 5 bitarteko garrantzi-mailetan sailka ditzakezu aplikazioen jakinarazpenak. \n\n"<b>"5. maila"</b>" \n- Erakutsi jakinarazpenen zerrendaren goialdean. \n- Baimendu etetea pantaila osoko moduan zaudenean. \n- Agerrarazi beti jakinarazpenak. \n\n"<b>"4. maila"</b>" \n- Galarazi etetea pantaila osoko moduan zaudenean. \n- Agerrarazi beti jakinarazpenak. \n\n"<b>"3. maila"</b>" \n- Galarazi etetea pantaila osoko moduan zaudenean. \n- Ez agerrarazi jakinarazpenik inoiz. \n\n"<b>"2. maila"</b>" \n- Galarazi etetea pantaila osoko moduan zaudenean. \n- Ez agerrarazi jakinarazpenik inoiz. \n- Ez egin soinurik edo dardararik inoiz. \n\n"<b>"1. maila"</b>" \n- Galarazi etetea pantaila osoko moduan zaudenean. \n- Ez agerrarazi jakinarazpenik inoiz. \n- Ez egin soinurik edo dardararik inoiz. \n- Ezkutatu pantaila blokeatutik eta egoera-barratik. \n- Erakutsi jakinarazpenen zerrendaren behealdean. \n\n"<b>"0. maila"</b>" \n- Blokeatu aplikazioaren jakinarazpen guztiak."</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Jakinarazpenak"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"Aurrerantzean ez duzu ikusiko horrelako jakinarazpenik"</string>
-    <!-- no translation found for inline_blocking_helper (3055064577771478591) -->
-    <skip />
+    <string name="inline_blocking_helper" msgid="3055064577771478591">"Baztertu egin ohi dituzu jakinarazpen hauek. \nHaiek erakusten jarraitzea nahi duzu?"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"Jakinarazpenak erakusten jarraitzea nahi duzu?"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"Blokeatu jakinarazpenak"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"Jarraitu erakusten"</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 56ca97c..fe8f6d5 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -310,8 +310,7 @@
     <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi désactivé"</string>
     <string name="quick_settings_wifi_on_label" msgid="7607810331387031235">"Wi-Fi activé"</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="269990350383909226">"Aucun réseau Wi-Fi à proximité"</string>
-    <!-- no translation found for quick_settings_alarm_title (2416759007342260676) -->
-    <skip />
+    <string name="quick_settings_alarm_title" msgid="2416759007342260676">"Alarme"</string>
     <string name="quick_settings_cast_title" msgid="7709016546426454729">"Diffuser"</string>
     <string name="quick_settings_casting" msgid="6601710681033353316">"Diffusion"</string>
     <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"Appareil sans nom"</string>
@@ -361,7 +360,6 @@
     <string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> est désactivée en mode sans échec."</string>
     <string name="recents_stack_action_button_label" msgid="6593727103310426253">"Effacer tout"</string>
     <string name="recents_drag_hint_message" msgid="2649739267073203985">"Glissez l\'élément ici pour utiliser l\'écran partagé"</string>
-    <string name="recents_swipe_up_onboarding" msgid="3824607135920170001">"Balayez vers le haut pour changer d\'application"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Séparation horizontale"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Séparation verticale"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Séparation personnalisée"</string>
@@ -505,21 +503,15 @@
     <string name="accessibility_output_chooser" msgid="8185317493017988680">"Changer d\'appareil de sortie"</string>
     <string name="screen_pinning_title" msgid="3273740381976175811">"L\'écran est épinglé"</string>
     <string name="screen_pinning_description" msgid="8909878447196419623">"Cet écran est épinglé jusqu\'à ce que vous annuliez l\'opération. Pour annuler l\'épinglage, maintenez le doigt sur « Retour » et « Aperçu »."</string>
-    <!-- no translation found for screen_pinning_description_recents_invisible (8281145542163727971) -->
-    <skip />
+    <string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"Cet écran est épinglé jusqu\'à ce que vous annuliez l\'opération. Pour annuler l\'épinglage, maintenez le doigt sur les touches Retour et Accueil."</string>
     <string name="screen_pinning_description_accessible" msgid="426190689254018656">"Cet écran est épinglé jusqu\'à ce que vous annuliez l\'opération. Pour annuler l\'épinglage, maintenez le doigt sur « Aperçu »."</string>
-    <!-- no translation found for screen_pinning_description_recents_invisible_accessible (6134833683151189507) -->
-    <skip />
-    <!-- no translation found for screen_pinning_toast (2266705122951934150) -->
-    <skip />
-    <!-- no translation found for screen_pinning_toast_recents_invisible (8252402309499161281) -->
-    <skip />
+    <string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"Cet écran est épinglé jusqu\'à ce que vous annuliez l\'opération. Pour annuler l\'épinglage, maintenez le doigt sur la touche Accueil."</string>
+    <string name="screen_pinning_toast" msgid="2266705122951934150">"Pour annuler l\'épinglage de cet écran, maintenez le doigt sur les touches Retour et Aperçu."</string>
+    <string name="screen_pinning_toast_recents_invisible" msgid="8252402309499161281">"Pour annuler l\'épinglage de cet écran, maintenez le doigt sur les touches Retour et Accueil."</string>
     <string name="screen_pinning_positive" msgid="3783985798366751226">"OK"</string>
     <string name="screen_pinning_negative" msgid="3741602308343880268">"Non, merci"</string>
-    <!-- no translation found for screen_pinning_start (1022122128489278317) -->
-    <skip />
-    <!-- no translation found for screen_pinning_exit (5187339744262325372) -->
-    <skip />
+    <string name="screen_pinning_start" msgid="1022122128489278317">"Écran épinglé"</string>
+    <string name="screen_pinning_exit" msgid="5187339744262325372">"Épinglage d\'écran annulé"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Masquer <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
     <string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Cet élément réapparaîtra la prochaine fois que vous l\'activerez dans les paramètres."</string>
     <string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Masquer"</string>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index 33d8821..5dc1dfa 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -103,12 +103,9 @@
     <string name="camera_label" msgid="7261107956054836961">"բացել ֆոտոխցիկը"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"Ընտրել առաջադրանքի նոր դասավորություն"</string>
     <string name="cancel" msgid="6442560571259935130">"Չեղարկել"</string>
-    <!-- no translation found for accessibility_fingerprint_dialog_fingerprint_icon (3125122495414253226) -->
-    <skip />
-    <!-- no translation found for accessibility_fingerprint_dialog_app_icon (3228052542929174609) -->
-    <skip />
-    <!-- no translation found for accessibility_fingerprint_dialog_help_area (5730471601819225159) -->
-    <skip />
+    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Մատնահետքի պատկերակ"</string>
+    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"Հավելվածի պատկերակ"</string>
+    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"Օգնության հաղորդագրության դաշտ"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Համատեղելիության խոշորացման կոճակը:"</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Դիտափոխել փոքրից ավելի մեծ էկրան:"</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth-ը միացված է:"</string>
@@ -311,6 +308,7 @@
     <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi-ը անջատված է"</string>
     <string name="quick_settings_wifi_on_label" msgid="7607810331387031235">"Wi-Fi-ը միացված է"</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="269990350383909226">"Հասանելի Wi-Fi ցանցեր չկան"</string>
+    <string name="quick_settings_alarm_title" msgid="2416759007342260676">"Զարթուցիչ"</string>
     <string name="quick_settings_cast_title" msgid="7709016546426454729">"Հեռարձակում"</string>
     <string name="quick_settings_casting" msgid="6601710681033353316">"Հեռարձակում"</string>
     <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"Անանուն սարք"</string>
@@ -327,9 +325,11 @@
     <string name="quick_settings_connecting" msgid="47623027419264404">"Միանում է..."</string>
     <string name="quick_settings_tethering_label" msgid="7153452060448575549">"Մոդեմի ռեժիմ"</string>
     <string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Թեժ կետ"</string>
-    <!-- no translation found for quick_settings_hotspot_secondary_label_transient (7161046712706277215) -->
-    <skip />
-    <!-- no translation found for quick_settings_hotspot_secondary_label_num_devices (2324635800672199428) -->
+    <string name="quick_settings_hotspot_secondary_label_transient" msgid="7161046712706277215">"Միանում է..."</string>
+    <plurals name="quick_settings_hotspot_secondary_label_num_devices" formatted="false" msgid="2324635800672199428">
+      <item quantity="one">%d սարք</item>
+      <item quantity="other">%d սարք</item>
+    </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Ծանուցումներ"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Լապտեր"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Բջջային ինտերնետ"</string>
@@ -339,10 +339,8 @@
     <string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"Օգտագործված է՝ <xliff:g id="DATA_USED">%s</xliff:g>"</string>
     <string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"Սահմանաչափ՝ <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> զգուշացում"</string>
-    <!-- no translation found for quick_settings_work_mode_on_label (3421274215098764735) -->
-    <skip />
-    <!-- no translation found for quick_settings_work_mode_off_label (8856918707867192186) -->
-    <skip />
+    <string name="quick_settings_work_mode_on_label" msgid="3421274215098764735">"Աշխատանքային պրոֆիլ"</string>
+    <string name="quick_settings_work_mode_off_label" msgid="8856918707867192186">"Ծանուցումներն ու հավելվածներն անջատված են"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Գիշերային լույս"</string>
     <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"Կմիացվի մայրամուտին"</string>
     <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"Մինչև լուսաբաց"</string>
@@ -360,8 +358,6 @@
     <string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> հավելվածը անվտանգ ռեժիմում անջատված է:"</string>
     <string name="recents_stack_action_button_label" msgid="6593727103310426253">"Մաքրել բոլորը"</string>
     <string name="recents_drag_hint_message" msgid="2649739267073203985">"Քաշեք այստեղ՝ էկրանի տրոհումն օգտագործելու համար"</string>
-    <!-- no translation found for recents_swipe_up_onboarding (3824607135920170001) -->
-    <skip />
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Հորիզոնական տրոհում"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Ուղղահայաց տրոհում"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Հատուկ տրոհում"</string>
@@ -502,11 +498,18 @@
     <string name="volume_zen_end_now" msgid="6930243045593601084">"Անջատել հիմա"</string>
     <string name="accessibility_volume_expand" msgid="5946812790999244205">"Ընդարձակել"</string>
     <string name="accessibility_volume_collapse" msgid="3609549593031810875">"Կոծկել"</string>
+    <string name="accessibility_output_chooser" msgid="8185317493017988680">"Փոխել արտածման սարքը"</string>
     <string name="screen_pinning_title" msgid="3273740381976175811">"Էկրանն ամրացված է"</string>
     <string name="screen_pinning_description" msgid="8909878447196419623">"Էկրանը կմնա տեսադաշտում, մինչև այն ապամրացնեք: Ապամրացնելու համար հպեք և պահեք Հետ և Համատեսք կոճակները:"</string>
+    <string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"Էկրանը կցուցադրվի այնքան ժամանակ, մինչև որ չապամրացնեք այն: Ապամրացնելու համար հպեք և պահեք Հետ և գլխավոր էկրանի կոճակները:"</string>
     <string name="screen_pinning_description_accessible" msgid="426190689254018656">"Էկրանը կմնա տեսադաշտում, մինչև այն ապամրացնեք: Ապամրացնելու համար հպեք և պահեք Համատեսք կոճակը:"</string>
+    <string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"Էկրանը կցուցադրվի այնքան ժամանակ, մինչև որ չապամրացնեք այն: Ապամրացնելու համար հպեք և պահեք գլխավոր էկրանի կոճակը:"</string>
+    <string name="screen_pinning_toast" msgid="2266705122951934150">"Էկրանն ապամրացնելու համար հպեք և պահեք Հետ և Համատեսք կոճակները"</string>
+    <string name="screen_pinning_toast_recents_invisible" msgid="8252402309499161281">"Էկրանն ապամրացնելու համար հպեք և պահեք Հետ և գլխավոր էկրանի կոճակները"</string>
     <string name="screen_pinning_positive" msgid="3783985798366751226">"Եղավ"</string>
     <string name="screen_pinning_negative" msgid="3741602308343880268">"Ոչ"</string>
+    <string name="screen_pinning_start" msgid="1022122128489278317">"Էկրանն ամրացված է"</string>
+    <string name="screen_pinning_exit" msgid="5187339744262325372">"Էկրանն ապամրացված է"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Թաքցնե՞լ <xliff:g id="TILE_LABEL">%1$s</xliff:g>-ը:"</string>
     <string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Այն դարձյալ կհայտնվի, երբ նորից միացնեք կարգավորումներում:"</string>
     <string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Թաքցնել"</string>
@@ -586,8 +589,7 @@
     <string name="power_notification_controls_description" msgid="4372459941671353358">"Ծանուցումների ընդլայնված կառավարման օգնությամբ կարող եք յուրաքանչյուր հավելվածի ծանուցումների համար նշանակել կարևորության աստիճան՝ 0-5 սահմաններում: \n\n"<b>"5-րդ աստիճան"</b>" \n- Ցուցադրել ծանուցումների ցանկի վերևում \n- Թույլատրել լիաէկրան ընդհատումները \n- Միշտ ցուցադրել կարճ ծանուցումները \n\n"<b>"4-րդ աստիճան"</b>" \n- Արգելել լիաէկրան ընդհատումները \n- Միշտ ցուցադրել կարճ ծանուցումները \n\n"<b>"3-րդ աստիճան"</b>" \n- Արգելել լիաէկրան ընդհատումները \n- Արգելել կարճ ծանուցումների ցուցադրումը \n\n"<b>"2-րդ աստիճան"</b>" \n- Արգելել լիաէկրան ընդհատումները \n- Արգելել կարճ ծանուցումների ցուցադրումը \n- Անջատել ձայնը և թրթռումը \n\n"<b>"1-ին աստիճան"</b>" \n- Արգելել լիաէկրան ընդհատումները \n- Արգելել կարճ ծանուցումների ցուցադրումը \n- Անջատել ձայնը և թրթռումը \n- Չցուցադրել կողպէկրանում և կարգավիճակի գոտում \n- Ցուցադրել ծանուցումների ցանկի ներքևում \n\n"<b>"0-րդ աստիճան"</b>\n"- Արգելափակել հավելվածի բոլոր ծանուցումները"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Ծանուցումներ"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"Դուք այլևս չեք ստանա այս ծանուցումները"</string>
-    <!-- no translation found for inline_blocking_helper (3055064577771478591) -->
-    <skip />
+    <string name="inline_blocking_helper" msgid="3055064577771478591">"Դուք սովորաբար փակում եք այս ծանուցումները: \nՇարունակե՞լ ցուցադրել դրանք:"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"Ցուցադրե՞լ այս ծանուցումները։"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"Չցուցադրել ծանուցումներ"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"Ցուցադրել"</string>
@@ -766,7 +768,7 @@
     <string name="pip_skip_to_prev" msgid="1955311326688637914">"Վերադառնալ նախորդին"</string>
     <string name="thermal_shutdown_title" msgid="4458304833443861111">"Հեռախոսն անջատվել է տաքանալու պատճառով"</string>
     <string name="thermal_shutdown_message" msgid="9006456746902370523">"Հեռախոսն այժմ նորմալ աշխատում է"</string>
-    <string name="thermal_shutdown_dialog_message" msgid="566347880005304139">"Ձեր հեռախոսը չափազանց տաք էր, այդ պատճառով այն անջատվել է՝ սառելու համար: Հեռախոսն այժմ նորմալ աշխատում է:\n\nՀեռախոսը կարող է տաքանալ, եթե՝\n	• Օգտագործում եք ռեսուրսատար հավելվածներ (օրինակ՝ խաղեր, տեսանյութեր կամ նավարկման հավելվածներ)\n	• Ներբեռնում կամ վերբեռնում եք ծանր ֆայլեր\n	• Օգտագործում եք ձեր հեռախոսը բարձր ջերմային պայմաններում"</string>
+    <string name="thermal_shutdown_dialog_message" msgid="566347880005304139">"Ձեր հեռախոսը չափազանց տաք էր, այդ պատճառով այն անջատվել է՝ հովանալու համար: Հեռախոսն այժմ նորմալ աշխատում է:\n\nՀեռախոսը կարող է տաքանալ, եթե՝\n	• Օգտագործում եք ռեսուրսատար հավելվածներ (օրինակ՝ խաղեր, տեսանյութեր կամ նավարկման հավելվածներ)\n	• Ներբեռնում կամ վերբեռնում եք ծանր ֆայլեր\n	• Օգտագործում եք ձեր հեռախոսը բարձր ջերմային պայմաններում"</string>
     <string name="high_temp_title" msgid="4589508026407318374">"Հեռախոսը տաքանում է"</string>
     <string name="high_temp_notif_message" msgid="5642466103153429279">"Հովանալու ընթացքում հեռախոսի որոշ գործառույթներ սահմանափակ են"</string>
     <string name="high_temp_dialog_message" msgid="6840700639374113553">"Ձեր հեռախոսն ավտոմատ կերպով կփորձի hովանալ: Կարող եք շարունակել օգտագործել հեռախոսը, սակայն հնարավոր է, որ այն ավելի դանդաղ աշխատի:\n\nՀովանալուց հետո հեռախոսը կաշխատի կանոնավոր կերպով:"</string>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index 37d8118..0279d16 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -310,8 +310,7 @@
     <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi o‘chiq"</string>
     <string name="quick_settings_wifi_on_label" msgid="7607810331387031235">"Wi-Fi yoqilgan"</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="269990350383909226">"Hech qanday Wi-Fi tarmog‘i mavjud emas"</string>
-    <!-- no translation found for quick_settings_alarm_title (2416759007342260676) -->
-    <skip />
+    <string name="quick_settings_alarm_title" msgid="2416759007342260676">"Signal"</string>
     <string name="quick_settings_cast_title" msgid="7709016546426454729">"Translatsiya"</string>
     <string name="quick_settings_casting" msgid="6601710681033353316">"Translatsiya qilinmoqda"</string>
     <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"Nomsiz qurilma"</string>
@@ -361,7 +360,6 @@
     <string name="recents_launch_disabled_message" msgid="1624523193008871793">"Xavfsiz rejimda <xliff:g id="APP">%s</xliff:g> ilovasi o‘chirib qo‘yildi."</string>
     <string name="recents_stack_action_button_label" msgid="6593727103310426253">"Hammasini tozalash"</string>
     <string name="recents_drag_hint_message" msgid="2649739267073203985">"Ekranni bo‘lish xususiyatidan foydalanish uchun bu yerga torting"</string>
-    <string name="recents_swipe_up_onboarding" msgid="3824607135920170001">"Ilovalarni almashtirish uchun ekranni tepaga suring"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Gorizontal yo‘nalishda bo‘lish"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Vertikal yo‘nalishda bo‘lish"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Boshqa usulda bo‘lish"</string>
@@ -502,25 +500,18 @@
     <string name="volume_zen_end_now" msgid="6930243045593601084">"O‘chiring"</string>
     <string name="accessibility_volume_expand" msgid="5946812790999244205">"Yoyish"</string>
     <string name="accessibility_volume_collapse" msgid="3609549593031810875">"Yig‘ish"</string>
-    <!-- no translation found for accessibility_output_chooser (8185317493017988680) -->
-    <skip />
+    <string name="accessibility_output_chooser" msgid="8185317493017988680">"Audiochiqish qurilmasini almashtirish"</string>
     <string name="screen_pinning_title" msgid="3273740381976175811">"Ekran qadaldi"</string>
     <string name="screen_pinning_description" msgid="8909878447196419623">"Ekran yechilmaguncha u o‘zgarmas holatda qoladi. Uni yechish uchun “Orqaga” va “Umumiy ma’lumot” tugmalarini bosib turing."</string>
-    <!-- no translation found for screen_pinning_description_recents_invisible (8281145542163727971) -->
-    <skip />
+    <string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"Ekran yechilmaguncha u o‘zgarmas holatda qoladi. Uni yechish uchun Orqaga va Boshi tugmalarini bosib turing."</string>
     <string name="screen_pinning_description_accessible" msgid="426190689254018656">"Ekran yechilmaguncha u o‘zgarmas holatda qoladi. Uni yechish uchun “Umumiy ma’lumot” tugmasini bosib turing."</string>
-    <!-- no translation found for screen_pinning_description_recents_invisible_accessible (6134833683151189507) -->
-    <skip />
-    <!-- no translation found for screen_pinning_toast (2266705122951934150) -->
-    <skip />
-    <!-- no translation found for screen_pinning_toast_recents_invisible (8252402309499161281) -->
-    <skip />
+    <string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"Ekran yechilmaguncha u o‘zgarmas holatda qoladi. Uni yechish uchun Orqaga va Boshi tugmlarini bosib turing."</string>
+    <string name="screen_pinning_toast" msgid="2266705122951934150">"Bu ekrandan chiqish uchun Orqaga va Menyu tugmalarini bosib turing"</string>
+    <string name="screen_pinning_toast_recents_invisible" msgid="8252402309499161281">"Bu ekrandan chiqish uchun Orqaga va Boshi tugmalarini bosib turing"</string>
     <string name="screen_pinning_positive" msgid="3783985798366751226">"OK"</string>
     <string name="screen_pinning_negative" msgid="3741602308343880268">"Yo‘q, kerakmas"</string>
-    <!-- no translation found for screen_pinning_start (1022122128489278317) -->
-    <skip />
-    <!-- no translation found for screen_pinning_exit (5187339744262325372) -->
-    <skip />
+    <string name="screen_pinning_start" msgid="1022122128489278317">"Ekran mahkamlandi"</string>
+    <string name="screen_pinning_exit" msgid="5187339744262325372">"Ekran olib tashlandi"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g> berkitilsinmi?"</string>
     <string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Keyingi safar sozlamalardan yoqilgan paydo bo‘ladi."</string>
     <string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Berkitish"</string>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index f2e5d3b..cf0659a 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -475,4 +475,11 @@
         <item>60</item>
         <item>120</item>
     </integer-array>
+
+    <!-- Smart replies in notifications: Whether smart replies in notifications are enabled. -->
+    <bool name="config_smart_replies_in_notifications_enabled">true</bool>
+
+    <!-- Smart replies in notifications: Maximum number of times SmartReplyView will try to find a
+         better (narrower) line-break for a double-line smart reply button. -->
+    <integer name="config_smart_replies_in_notifications_max_squeeze_remeasure_attempts">3</integer>
 </resources>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index c351b94..d4eba45 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -855,8 +855,6 @@
     <dimen name="default_gear_space">18dp</dimen>
     <dimen name="cell_overlay_padding">18dp</dimen>
 
-    <dimen name="signal_icon_size">17dp</dimen>
-
     <dimen name="hwui_edge_margin">16dp</dimen>
 
     <dimen name="global_actions_panel_width">120dp</dimen>
@@ -885,13 +883,8 @@
     <dimen name="nav_quick_scrub_track_edge_padding">42dp</dimen>
     <dimen name="nav_quick_scrub_track_thickness">2dp</dimen>
 
-    <!-- Intended corner radius when drawing the mobile signal -->
-    <dimen name="stat_sys_mobile_signal_corner_radius">0.75dp</dimen>
-    <!-- How far to inset the rounded edges -->
-    <dimen name="stat_sys_mobile_signal_circle_inset">0.9dp</dimen>
-
     <!-- Home button padding for sizing -->
-    <dimen name="home_padding">15dp</dimen>
+    <dimen name="home_padding">16dp</dimen>
 
     <!-- Smart reply button -->
     <dimen name="smart_reply_button_corner_radius">24dip</dimen>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index fc5ea458..dc082a9 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1340,8 +1340,7 @@
     <string name="volume_stream_content_description_vibrate_a11y">%1$s. Tap to set to vibrate.</string>
     <string name="volume_stream_content_description_mute_a11y">%1$s. Tap to mute.</string>
 
-    <string name="volume_dialog_accessibility_shown_message">%s volume controls shown. Swipe up to dismiss.</string>
-    <string name="volume_dialog_accessibility_dismissed_message">Volume controls hidden</string>
+    <string name="volume_dialog_title">%s volume controls</string>
 
     <string name="output_title">Media output</string>
     <string name="output_calls_title">Phone call output</string>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java
index 62bd72f..138910c 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java
@@ -316,6 +316,17 @@
     }
 
     /**
+     * Cancels the remote recents animation started from {@link #startRecentsActivity}.
+     */
+    public void cancelRecentsAnimation() {
+        try {
+            ActivityManager.getService().cancelRecentsAnimation();
+        } catch (RemoteException e) {
+            Log.e(TAG, "Failed to cancel recents animation", e);
+        }
+    }
+
+    /**
      * Starts a task from Recents.
      *
      * @see {@link #startActivityFromRecentsAsync(TaskKey, ActivityOptions, int, int, Consumer, Handler)}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/PackageManagerWrapper.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/PackageManagerWrapper.java
index d5e6e6e..6fa7db3 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/PackageManagerWrapper.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/PackageManagerWrapper.java
@@ -21,8 +21,12 @@
 import android.content.pm.ActivityInfo;
 import android.content.pm.IPackageManager;
 import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
 import android.os.RemoteException;
 
+import java.util.ArrayList;
+import java.util.List;
+
 public class PackageManagerWrapper {
 
     private static final String TAG = "PackageManagerWrapper";
@@ -47,4 +51,42 @@
             return null;
         }
     }
+
+    /**
+     * @return true if the packageName belongs to the current preferred home app on the device.
+     *
+     * If will also return false if there are multiple home apps and the user has not picked any
+     * preferred home, in which case the user would see a disambiguation screen on going to home.
+     */
+    public boolean isDefaultHomeActivity(String packageName) {
+        List<ResolveInfo> allHomeCandidates = new ArrayList<>();
+        ComponentName home;
+        try {
+            home = mIPackageManager.getHomeActivities(allHomeCandidates);
+        } catch (RemoteException e) {
+            e.printStackTrace();
+            return false;
+        }
+
+        if (home != null && packageName.equals(home.getPackageName())) {
+            return true;
+        }
+
+        // Find the launcher with the highest priority and return that component if there are no
+        // other home activity with the same priority.
+        int lastPriority = Integer.MIN_VALUE;
+        ComponentName lastComponent = null;
+        final int size = allHomeCandidates.size();
+        for (int i = 0; i < size; i++) {
+            final ResolveInfo ri = allHomeCandidates.get(i);
+            if (ri.priority > lastPriority) {
+                lastComponent = ri.activityInfo.getComponentName();
+                lastPriority = ri.priority;
+            } else if (ri.priority == lastPriority) {
+                // Two components found with same priority.
+                lastComponent = null;
+            }
+        }
+        return lastComponent != null && packageName.equals(lastComponent.getPackageName());
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
index 0f3daf5..d1834e9 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
@@ -52,6 +52,7 @@
 import com.android.systemui.statusbar.phone.StatusBarIconController;
 import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
 import com.android.systemui.statusbar.policy.DeviceProvisionedController;
+import com.android.systemui.statusbar.policy.SmartReplyConstants;
 
 import java.util.function.Consumer;
 
@@ -130,6 +131,8 @@
         providers.put(NotificationGutsManager.class, () -> new NotificationGutsManager(context));
         providers.put(NotificationRemoteInputManager.class,
                 () -> new NotificationRemoteInputManager(context));
+        providers.put(SmartReplyConstants.class,
+                () -> new SmartReplyConstants(Dependency.get(Dependency.MAIN_HANDLER), context));
         providers.put(NotificationListener.class, () -> new NotificationListener(context));
         providers.put(NotificationLogger.class, NotificationLogger::new);
         providers.put(NotificationViewHierarchyManager.class,
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
index c28b7ee..1aea5e7 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
@@ -1369,6 +1369,7 @@
             mListView = findViewById(android.R.id.list);
             mHardwareLayout = HardwareUiLayout.get(mListView);
             mHardwareLayout.setOutsideTouchListener(view -> dismiss());
+            setTitle(R.string.global_actions);
         }
 
         private void updateList() {
@@ -1464,20 +1465,6 @@
         }
 
         @Override
-        public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
-            if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
-                for (int i = 0; i < mAdapter.getCount(); ++i) {
-                    CharSequence label =
-                            mAdapter.getItem(i).getLabelForAccessibility(getContext());
-                    if (label != null) {
-                        event.getText().add(label);
-                    }
-                }
-            }
-            return super.dispatchPopulateAccessibilityEvent(event);
-        }
-
-        @Override
         public void onColorsChanged(ColorExtractor extractor, int which) {
             if (mKeyguardShowing) {
                 if ((WallpaperManager.FLAG_LOCK & which) != 0) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/CellTileView.java b/packages/SystemUI/src/com/android/systemui/qs/CellTileView.java
index 5f260938..e7eefe8 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/CellTileView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/CellTileView.java
@@ -19,12 +19,12 @@
 import android.service.quicksettings.Tile;
 import android.widget.ImageView;
 
+import com.android.settingslib.graph.SignalDrawable;
 import com.android.settingslib.Utils;
 import com.android.systemui.R;
 import com.android.systemui.plugins.qs.QSTile.Icon;
 import com.android.systemui.plugins.qs.QSTile.State;
 import com.android.systemui.qs.tileimpl.QSTileImpl;
-import com.android.systemui.statusbar.phone.SignalDrawable;
 
 import java.util.Objects;
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
index 5a3081c..3847040 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
@@ -171,8 +171,6 @@
             queryTiles();
             mNotifQsContainer.setCustomizerAnimating(true);
             mNotifQsContainer.setCustomizerShowing(true);
-            announceForAccessibility(mContext.getString(
-                    R.string.accessibility_desc_quick_settings_edit));
             Dependency.get(KeyguardMonitor.class).addCallback(mKeyguardCallback);
             updateNavColors();
         }
@@ -213,8 +211,6 @@
             mClipper.animateCircularClip(mX, mY, false, mCollapseAnimationListener);
             mNotifQsContainer.setCustomizerAnimating(true);
             mNotifQsContainer.setCustomizerShowing(false);
-            announceForAccessibility(mContext.getString(
-                    R.string.accessibility_desc_quick_settings));
             Dependency.get(KeyguardMonitor.class).removeCallback(mKeyguardCallback);
             updateNavColors();
         }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
index 2607ebb..7fe9e35 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
@@ -131,21 +131,10 @@
 
         if (enabled) {
             if (connected) {
-                state.icon = ResourceIcon.get(R.drawable.ic_qs_bluetooth_connected);
+                state.icon = new BluetoothConnectedTileIcon();
                 state.contentDescription = mContext.getString(
                         R.string.accessibility_bluetooth_name, state.label);
 
-                final CachedBluetoothDevice lastDevice = mController.getLastDevice();
-                if (lastDevice != null) {
-                    final int batteryLevel = lastDevice.getBatteryLevel();
-                    if (batteryLevel != BluetoothDevice.BATTERY_LEVEL_UNKNOWN) {
-                        state.icon = new BluetoothBatteryTileIcon(
-                                batteryLevel,
-                                mContext.getResources().getFraction(
-                                        R.fraction.bt_battery_scale_fraction, 1, 1));
-                    }
-                }
-
                 state.label = mController.getLastDeviceName();
             } else if (state.isTransient) {
                 state.icon = ResourceIcon.get(R.drawable.ic_bluetooth_transient_animation);
@@ -281,6 +270,25 @@
         }
     }
 
+
+    /**
+     * Bluetooth icon wrapper (when connected with no battery indicator) for Quick Settings. This is
+     * used instead of {@link com.android.systemui.qs.tileimpl.QSTileImpl.DrawableIcon} in order to
+     * use a context that reflects dark/light theme attributes.
+     */
+    private class BluetoothConnectedTileIcon extends Icon {
+
+        BluetoothConnectedTileIcon() {
+            // Do nothing. Default constructor to limit visibility.
+        }
+
+        @Override
+        public Drawable getDrawable(Context context) {
+            // This method returns Pair<Drawable, String> - the first value is the drawable.
+            return context.getDrawable(R.drawable.ic_qs_bluetooth_connected);
+        }
+    }
+
     protected class BluetoothDetailAdapter implements DetailAdapter, QSDetailItems.Callback {
         // We probably won't ever have space in the UI for more than 20 devices, so don't
         // get info for them.
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
index bf4a225..2acb1bb 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
@@ -38,10 +38,12 @@
 import android.content.Intent;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
+import android.graphics.Canvas;
 import android.graphics.ColorMatrix;
 import android.graphics.ColorMatrixColorFilter;
 import android.graphics.Matrix;
 import android.graphics.Paint;
+import android.graphics.Picture;
 import android.graphics.PixelFormat;
 import android.graphics.PointF;
 import android.graphics.Rect;
@@ -57,13 +59,10 @@
 import android.util.DisplayMetrics;
 import android.util.Slog;
 import android.view.Display;
-import android.view.DisplayListCanvas;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
-import android.view.RenderNode;
 import android.view.Surface;
 import android.view.SurfaceControl;
-import android.view.ThreadedRenderer;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.WindowManager;
@@ -233,14 +232,12 @@
      */
     private Bitmap generateAdjustedHwBitmap(Bitmap bitmap, int width, int height, Matrix matrix,
             Paint paint, int color) {
-        RenderNode node = RenderNode.create("ScreenshotCanvas", null);
-        node.setLeftTopRightBottom(0, 0, width, height);
-        node.setClipToBounds(false);
-        DisplayListCanvas canvas = node.start(width, height);
+        Picture picture = new Picture();
+        Canvas canvas = picture.beginRecording(width, height);
         canvas.drawColor(color);
         canvas.drawBitmap(bitmap, matrix, paint);
-        node.end(canvas);
-        return ThreadedRenderer.createHardwareBitmap(node, width, height);
+        picture.endRecording();
+        return Bitmap.createBitmap(picture);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
index e811ed3..c4d0b79 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
@@ -22,7 +22,6 @@
 import android.content.Context;
 import android.graphics.Rect;
 import android.os.Build;
-import android.provider.Settings;
 import android.service.notification.StatusBarNotification;
 import android.util.AttributeSet;
 import android.util.Log;
@@ -36,6 +35,7 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.NotificationColorUtil;
+import com.android.systemui.Dependency;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.notification.HybridGroupManager;
 import com.android.systemui.statusbar.notification.HybridNotificationView;
@@ -44,6 +44,7 @@
 import com.android.systemui.statusbar.notification.NotificationViewWrapper;
 import com.android.systemui.statusbar.phone.NotificationGroupManager;
 import com.android.systemui.statusbar.policy.RemoteInputView;
+import com.android.systemui.statusbar.policy.SmartReplyConstants;
 import com.android.systemui.statusbar.policy.SmartReplyView;
 
 /**
@@ -75,6 +76,8 @@
 
     private RemoteInputView mExpandedRemoteInput;
     private RemoteInputView mHeadsUpRemoteInput;
+
+    private SmartReplyConstants mSmartReplyConstants;
     private SmartReplyView mExpandedSmartReplyView;
 
     private NotificationViewWrapper mContractedWrapper;
@@ -145,6 +148,7 @@
     public NotificationContentView(Context context, AttributeSet attrs) {
         super(context, attrs);
         mHybridGroupManager = new HybridGroupManager(getContext(), this);
+        mSmartReplyConstants = Dependency.get(SmartReplyConstants.class);
         initView();
     }
 
@@ -1166,8 +1170,7 @@
             return;
         }
 
-        boolean enableSmartReplies = Settings.Global.getInt(mContext.getContentResolver(),
-                Settings.Global.ENABLE_SMART_REPLIES_IN_NOTIFICATIONS, 0) != 0;
+        boolean enableSmartReplies = mSmartReplyConstants.isEnabled();
 
         boolean hasRemoteInput = false;
         RemoteInput remoteInputWithChoices = null;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
index 735f4fd..afe906c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
@@ -50,7 +50,6 @@
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
 
-import java.lang.IllegalArgumentException;
 import java.util.List;
 import java.util.Set;
 
@@ -274,7 +273,7 @@
     }
 
     private void saveImportance() {
-        if (mNonblockable || !hasImportanceChanged()) {
+        if (mNonblockable) {
             return;
         }
         MetricsLogger.action(mContext, MetricsEvent.ACTION_SAVE_IMPORTANCE,
@@ -409,7 +408,7 @@
         final int centerY = v.getHeight() / 2;
         final int x = targetLoc[0] - parentLoc[0] + centerX;
         final int y = targetLoc[1] - parentLoc[1] + centerY;
-        mGutsContainer.closeControls(x, y, false /* save */, false /* force */);
+        mGutsContainer.closeControls(x, y, true /* save */, false /* force */);
     }
 
     @Override
@@ -429,7 +428,9 @@
 
     @Override
     public boolean handleCloseControls(boolean save, boolean force) {
-        if (save && hasImportanceChanged()) {
+        // Save regardless of the importance so we can lock the importance field if the user wants
+        // to keep getting notifications
+        if (save) {
             if (mCheckSaveListener != null) {
                 mCheckSaveListener.checkSave(this::saveImportance, mSbn);
             } else {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
index a7fb61a..cb6e5a6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
@@ -38,9 +38,9 @@
 import android.widget.ImageView;
 import android.widget.LinearLayout;
 
+import com.android.settingslib.graph.SignalDrawable;
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
-import com.android.systemui.statusbar.phone.SignalDrawable;
 import com.android.systemui.statusbar.phone.StatusBarIconController;
 import com.android.systemui.statusbar.policy.DarkIconDispatcher;
 import com.android.systemui.statusbar.policy.DarkIconDispatcher.DarkReceiver;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/ConnectedDeviceSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/ConnectedDeviceSignalController.java
index 677fa81..0304086 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/ConnectedDeviceSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/ConnectedDeviceSignalController.java
@@ -16,10 +16,10 @@
 import android.util.TypedValue;
 import android.view.View;
 import android.widget.ImageView;
+import com.android.settingslib.graph.SignalDrawable;
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.ScalingDrawableWrapper;
-import com.android.systemui.statusbar.phone.SignalDrawable;
 import com.android.systemui.statusbar.policy.BluetoothController;
 
 import static com.android.systemui.statusbar.phone.StatusBar.DEBUG;
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 1239a9e..2a0cb21 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
@@ -960,6 +960,7 @@
                 PixelFormat.TRANSLUCENT);
         lp.token = new Binder();
         lp.setTitle("NavigationBar");
+        lp.accessibilityTitle = context.getString(R.string.nav_bar);
         lp.windowAnimations = 0;
 
         View navigationBarView = LayoutInflater.from(context).inflate(
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 af0afbd..a8cd0c3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -217,6 +217,9 @@
         mShowAccessibilityButton = false;
         mLongClickableAccessibilityButton = false;
 
+        mOverviewProxyService = Dependency.get(OverviewProxyService.class);
+        mRecentsOnboarding = new RecentsOnboarding(context, mOverviewProxyService);
+
         mConfiguration = new Configuration();
         mConfiguration.updateFrom(context.getResources().getConfiguration());
         updateIcons(context, Configuration.EMPTY, mConfiguration);
@@ -232,9 +235,6 @@
                 new ButtonDispatcher(R.id.accessibility_button));
         mButtonDispatchers.put(R.id.rotate_suggestion,
                 new ButtonDispatcher(R.id.rotate_suggestion));
-
-        mOverviewProxyService = Dependency.get(OverviewProxyService.class);
-        mRecentsOnboarding = new RecentsOnboarding(context, mOverviewProxyService);
     }
 
     public BarTransitions getBarTransitions() {
@@ -355,14 +355,23 @@
         }
         if (oldConfig.densityDpi != newConfig.densityDpi
                 || oldConfig.getLayoutDirection() != newConfig.getLayoutDirection()) {
-            mBackIcon = getDrawable(ctx, R.drawable.ic_sysbar_back, R.drawable.ic_sysbar_back_dark);
+            final boolean proxyAvailable = mOverviewProxyService.getProxy() != null;
+            mBackIcon = proxyAvailable
+                    ? getDrawable(ctx, R.drawable.ic_sysbar_back_quick_step,
+                            R.drawable.ic_sysbar_back_quick_step_dark)
+                    : getDrawable(ctx, R.drawable.ic_sysbar_back, R.drawable.ic_sysbar_back_dark);
             mBackLandIcon = mBackIcon;
-            mBackAltIcon = getDrawable(ctx,
-                    R.drawable.ic_sysbar_back_ime, R.drawable.ic_sysbar_back_ime_dark);
+            mBackAltIcon = proxyAvailable
+                    ? getDrawable(ctx, R.drawable.ic_sysbar_back_ime_quick_step,
+                            R.drawable.ic_sysbar_back_ime_quick_step_dark)
+                    : getDrawable(ctx, R.drawable.ic_sysbar_back_ime,
+                            R.drawable.ic_sysbar_back_ime_dark);
             mBackAltLandIcon = mBackAltIcon;
 
-            mHomeDefaultIcon = getDrawable(ctx,
-                    R.drawable.ic_sysbar_home, R.drawable.ic_sysbar_home_dark);
+            mHomeDefaultIcon = proxyAvailable
+                    ? getDrawable(ctx, R.drawable.ic_sysbar_home_quick_step,
+                            R.drawable.ic_sysbar_home_quick_step_dark)
+                    : getDrawable(ctx, R.drawable.ic_sysbar_home, R.drawable.ic_sysbar_home_dark);
             mRecentIcon = getDrawable(ctx,
                     R.drawable.ic_sysbar_recent, R.drawable.ic_sysbar_recent_dark);
             mMenuIcon = getDrawable(ctx, R.drawable.ic_sysbar_menu, R.drawable.ic_sysbar_menu_dark);
@@ -666,6 +675,8 @@
         setSlippery(!isConnected);
         setDisabledFlags(mDisabledFlags, true);
         setUpSwipeUpOnboarding(isConnected);
+        updateIcons(getContext(), Configuration.EMPTY, mConfiguration);
+        setNavigationIconHints(mNavigationIconHints, true);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index 52d005c..0e8fcba 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -45,7 +45,7 @@
 import android.view.ViewGroup;
 import android.view.ViewTreeObserver;
 import android.view.WindowInsets;
-import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityManager;
 import android.widget.FrameLayout;
 
 import com.android.internal.logging.MetricsLogger;
@@ -111,6 +111,7 @@
                 }
             };
     private final PowerManager mPowerManager;
+    private final AccessibilityManager mAccessibilityManager;
 
     private KeyguardAffordanceHelper mAffordanceHelper;
     private KeyguardUserSwitcher mKeyguardUserSwitcher;
@@ -249,6 +250,8 @@
         setWillNotDraw(!DEBUG);
         mFalsingManager = FalsingManager.getInstance(context);
         mPowerManager = context.getSystemService(PowerManager.class);
+        mAccessibilityManager = context.getSystemService(AccessibilityManager.class);
+        setAccessibilityPaneTitle(determineAccessibilityPaneTitle());
     }
 
     public void setStatusBar(StatusBar bar) {
@@ -661,16 +664,6 @@
     }
 
     @Override
-    public boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
-        if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
-            event.getText().add(getKeyguardOrLockScreenString());
-            mLastAnnouncementWasQuickSettings = false;
-            return true;
-        }
-        return super.dispatchPopulateAccessibilityEventInternal(event);
-    }
-
-    @Override
     public boolean onInterceptTouchEvent(MotionEvent event) {
         if (mBlockTouches || mQsFullyExpanded && mQs.onInterceptTouchEvent(event)) {
             return false;
@@ -1300,10 +1293,6 @@
             setQsExpanded(true);
         } else if (height <= mQsMinExpansionHeight && mQsExpanded) {
             setQsExpanded(false);
-            if (mLastAnnouncementWasQuickSettings && !mTracking && !isCollapsing()) {
-                announceForAccessibility(getKeyguardOrLockScreenString());
-                mLastAnnouncementWasQuickSettings = false;
-            }
         }
         mQsExpansionHeight = height;
         updateQsExpansion();
@@ -1329,13 +1318,10 @@
             updateClock(mClockPositionResult.clockAlpha, mClockPositionResult.clockScale);
         }
 
-        // Upon initialisation when we are not layouted yet we don't want to announce that we are
-        // fully expanded, hence the != 0.0f check.
-        if (height != 0.0f && mQsFullyExpanded && !mLastAnnouncementWasQuickSettings) {
-            announceForAccessibility(getContext().getString(
-                    R.string.accessibility_desc_quick_settings));
-            mLastAnnouncementWasQuickSettings = true;
+        if (mAccessibilityManager.isEnabled()) {
+            setAccessibilityPaneTitle(determineAccessibilityPaneTitle());
         }
+
         if (mQsFullyExpanded && mFalsingManager.shouldEnforceBouncer()) {
             mStatusBar.executeRunnableDismissingKeyguard(null, null /* cancelAction */,
                     false /* dismissShade */, true /* afterKeyguardGone */, false /* deferred */);
@@ -1350,9 +1336,13 @@
         mQs.setQsExpansion(getQsExpansionFraction(), getHeaderTranslation());
     }
 
-    private String getKeyguardOrLockScreenString() {
+    private String determineAccessibilityPaneTitle() {
         if (mQs != null && mQs.isCustomizing()) {
             return getContext().getString(R.string.accessibility_desc_quick_settings_edit);
+        } else if (mQsExpansionHeight != 0.0f && mQsFullyExpanded) {
+            // Upon initialisation when we are not layouted yet we don't want to announce that we
+            // are fully expanded, hence the != 0.0f check.
+            return getContext().getString(R.string.accessibility_desc_quick_settings);
         } else if (mStatusBarState == StatusBarState.KEYGUARD) {
             return getContext().getString(R.string.accessibility_desc_lock_screen);
         } else {
@@ -1880,6 +1870,9 @@
             requestScrollerTopPaddingUpdate(false /* animate */);
             requestPanelHeightUpdate();
         }
+        if (mAccessibilityManager.isEnabled()) {
+            setAccessibilityPaneTitle(determineAccessibilityPaneTitle());
+        }
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index 1438763..e7a2c0b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -138,7 +138,8 @@
     protected float mScrimBehindAlphaKeyguard = SCRIM_BEHIND_ALPHA_KEYGUARD;
     protected float mScrimBehindAlphaUnlocking = SCRIM_BEHIND_ALPHA_UNLOCKING;
 
-    private float mFraction;
+    // Assuming the shade is expanded during initialization
+    private float mExpansionFraction = 1f;
 
     private boolean mDarkenWhileDragging;
     protected boolean mAnimateChange;
@@ -251,6 +252,7 @@
         mCurrentBehindTint = state.getBehindTint();
         mCurrentInFrontAlpha = state.getFrontAlpha();
         mCurrentBehindAlpha = state.getBehindAlpha();
+        applyExpansionToAlpha();
 
         // Cancel blanking transitions that were pending before we requested a new state
         if (mPendingFrameCallback != null) {
@@ -362,45 +364,50 @@
      * @param fraction From 0 to 1 where 0 means collapse and 1 expanded.
      */
     public void setPanelExpansion(float fraction) {
-        if (mFraction != fraction) {
-            mFraction = fraction;
+        if (mExpansionFraction != fraction) {
+            mExpansionFraction = fraction;
 
-            if (mState == ScrimState.UNLOCKED) {
-                // Darken scrim as you pull down the shade when unlocked
-                float behindFraction = getInterpolatedFraction();
-                behindFraction = (float) Math.pow(behindFraction, 0.8f);
-                mCurrentBehindAlpha = behindFraction * mScrimBehindAlphaKeyguard;
-                mCurrentInFrontAlpha = 0;
-            } else if (mState == ScrimState.KEYGUARD) {
-                if (mUpdatePending) {
-                    return;
-                }
+            if (!(mState == ScrimState.UNLOCKED || mState == ScrimState.KEYGUARD)) {
+                return;
+            }
 
-                // Either darken of make the scrim transparent when you
-                // pull down the shade
-                float interpolatedFract = getInterpolatedFraction();
-                if (mDarkenWhileDragging) {
-                    mCurrentBehindAlpha = MathUtils.lerp(mScrimBehindAlphaUnlocking,
-                            mScrimBehindAlphaKeyguard, interpolatedFract);
-                    mCurrentInFrontAlpha = (1f - interpolatedFract) * SCRIM_IN_FRONT_ALPHA_LOCKED;
-                } else {
-                    mCurrentBehindAlpha = MathUtils.lerp(0 /* start */, mScrimBehindAlphaKeyguard,
-                            interpolatedFract);
-                    mCurrentInFrontAlpha = 0;
-                }
-            } else {
+            applyExpansionToAlpha();
+
+            if (mUpdatePending) {
                 return;
             }
 
             if (mPinnedHeadsUpCount != 0) {
                 updateHeadsUpScrim(false);
             }
-
             updateScrim(false /* animate */, mScrimInFront, mCurrentInFrontAlpha);
             updateScrim(false /* animate */, mScrimBehind, mCurrentBehindAlpha);
         }
     }
 
+    private void applyExpansionToAlpha() {
+        if (mState == ScrimState.UNLOCKED) {
+            // Darken scrim as you pull down the shade when unlocked
+            float behindFraction = getInterpolatedFraction();
+            behindFraction = (float) Math.pow(behindFraction, 0.8f);
+            mCurrentBehindAlpha = behindFraction * mScrimBehindAlphaKeyguard;
+            mCurrentInFrontAlpha = 0;
+        } else if (mState == ScrimState.KEYGUARD) {
+            // Either darken of make the scrim transparent when you
+            // pull down the shade
+            float interpolatedFract = getInterpolatedFraction();
+            if (mDarkenWhileDragging) {
+                mCurrentBehindAlpha = MathUtils.lerp(mScrimBehindAlphaUnlocking,
+                        mScrimBehindAlphaKeyguard, interpolatedFract);
+                mCurrentInFrontAlpha = (1f - interpolatedFract) * SCRIM_IN_FRONT_ALPHA_LOCKED;
+            } else {
+                mCurrentBehindAlpha = MathUtils.lerp(0 /* start */, mScrimBehindAlphaKeyguard,
+                        interpolatedFract);
+                mCurrentInFrontAlpha = 0;
+            }
+        }
+    }
+
     /**
      * Keyguard and shade scrim opacity varies according to how many notifications are visible.
      * @param notificationCount Number of visible notifications.
@@ -496,7 +503,7 @@
     }
 
     private float getInterpolatedFraction() {
-        float frac = mFraction;
+        float frac = mExpansionFraction;
         // let's start this 20% of the way down the screen
         frac = frac * 1.2f - 0.2f;
         if (frac <= 0) {
@@ -825,7 +832,7 @@
         } else {
             alpha = 1.0f - mTopHeadsUpDragAmount;
         }
-        float expandFactor = (1.0f - mFraction);
+        float expandFactor = (1.0f - mExpansionFraction);
         expandFactor = Math.max(expandFactor, 0.0f);
         return alpha * expandFactor;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
index c30f633..948f524 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
@@ -106,6 +106,7 @@
         mLp.gravity = Gravity.TOP;
         mLp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
         mLp.setTitle("StatusBar");
+        mLp.accessibilityTitle = mContext.getString(R.string.status_bar);
         mLp.packageName = mContext.getPackageName();
         mStatusBarView = statusBarView;
         mBarHeight = barHeight;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusIconContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusIconContainer.java
index 1da50ad..503a1b4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusIconContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusIconContainer.java
@@ -36,6 +36,7 @@
 public class StatusIconContainer extends AlphaOptimizedLinearLayout {
 
     private static final String TAG = "StatusIconContainer";
+    private static final boolean DEBUG = false;
     private static final int MAX_ICONS = 5;
     private static final int MAX_DOTS = 3;
 
@@ -94,7 +95,7 @@
         int childCount = getChildCount();
         // Underflow === don't show content until that index
         int firstUnderflowIndex = -1;
-        android.util.Log.d(TAG, "calculateIconTransitions: start=" + translationX);
+        if (DEBUG) android.util.Log.d(TAG, "calculateIconTransitions: start=" + translationX);
 
         //TODO: Dots
         for (int i = childCount - 1; i >= 0; i--) {
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 9d1c1e8..98bebec 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
@@ -52,6 +52,7 @@
 import com.android.systemui.OverviewProxyService;
 import com.android.systemui.R;
 import com.android.systemui.plugins.statusbar.phone.NavBarButtonProvider.ButtonInterface;
+import com.android.systemui.shared.system.ActivityManagerWrapper;
 
 import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLICK;
 import static android.view.accessibility.AccessibilityNodeInfo.ACTION_LONG_CLICK;
@@ -269,11 +270,7 @@
                     if (doIt) {
                         // If there was a pending remote recents animation, then we need to
                         // cancel the animation now before we handle the button itself
-                        try {
-                            ActivityManager.getService().cancelRecentsAnimation();
-                        } catch (RemoteException e) {
-                            Log.e(TAG, "Could not cancel recents animation", e);
-                        }
+                        ActivityManagerWrapper.getInstance().cancelRecentsAnimation();
                         sendEvent(KeyEvent.ACTION_UP, 0);
                         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
                     } else {
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 8516278..f0854ed 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
@@ -35,8 +35,8 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.telephony.TelephonyIntents;
 import com.android.internal.telephony.cdma.EriInfo;
+import com.android.settingslib.graph.SignalDrawable;
 import com.android.systemui.R;
-import com.android.systemui.statusbar.phone.SignalDrawable;
 import com.android.systemui.statusbar.policy.NetworkController.IconState;
 import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
 import com.android.systemui.statusbar.policy.NetworkControllerImpl.Config;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyConstants.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyConstants.java
new file mode 100644
index 0000000..c5067a6
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyConstants.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.policy;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.res.Resources;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Handler;
+import android.provider.Settings;
+import android.util.KeyValueListParser;
+import android.util.Log;
+
+import com.android.systemui.R;
+
+public final class SmartReplyConstants extends ContentObserver {
+
+    private static final String TAG = "SmartReplyConstants";
+
+    private static final String KEY_ENABLED = "enabled";
+    private static final String KEY_MAX_SQUEEZE_REMEASURE_ATTEMPTS =
+            "max_squeeze_remeasure_attempts";
+
+    private final boolean mDefaultEnabled;
+    private final int mDefaultMaxSqueezeRemeasureAttempts;
+
+    private boolean mEnabled;
+    private int mMaxSqueezeRemeasureAttempts;
+
+    private final Context mContext;
+    private final KeyValueListParser mParser = new KeyValueListParser(',');
+
+    public SmartReplyConstants(Handler handler, Context context) {
+        super(handler);
+
+        mContext = context;
+        final Resources resources = mContext.getResources();
+        mDefaultEnabled = resources.getBoolean(
+                R.bool.config_smart_replies_in_notifications_enabled);
+        mDefaultMaxSqueezeRemeasureAttempts = resources.getInteger(
+                R.integer.config_smart_replies_in_notifications_max_squeeze_remeasure_attempts);
+
+        mContext.getContentResolver().registerContentObserver(
+                Settings.Global.getUriFor(Settings.Global.SMART_REPLIES_IN_NOTIFICATIONS_FLAGS),
+                false, this);
+        updateConstants();
+    }
+
+    @Override
+    public void onChange(boolean selfChange, Uri uri) {
+        updateConstants();
+    }
+
+    private void updateConstants() {
+        synchronized (SmartReplyConstants.this) {
+            try {
+                mParser.setString(Settings.Global.getString(mContext.getContentResolver(),
+                        Settings.Global.SMART_REPLIES_IN_NOTIFICATIONS_FLAGS));
+            } catch (IllegalArgumentException e) {
+                Log.e(TAG, "Bad smart reply constants", e);
+            }
+            mEnabled = mParser.getBoolean(KEY_ENABLED, mDefaultEnabled);
+            mMaxSqueezeRemeasureAttempts = mParser.getInt(
+                    KEY_MAX_SQUEEZE_REMEASURE_ATTEMPTS, mDefaultMaxSqueezeRemeasureAttempts);
+        }
+    }
+
+    /** Returns whether smart replies in notifications are enabled. */
+    public boolean isEnabled() {
+        return mEnabled;
+    }
+
+    /**
+     * Returns the maximum number of times {@link SmartReplyView#onMeasure(int, int)} will try to
+     * find a better (narrower) line-break for a double-line smart reply button.
+     */
+    public int getMaxSqueezeRemeasureAttempts() {
+        return mMaxSqueezeRemeasureAttempts;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java
index 2d829af..57fc03c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java
@@ -12,6 +12,7 @@
 import android.widget.Button;
 import android.widget.LinearLayout;
 
+import com.android.systemui.Dependency;
 import com.android.systemui.R;
 
 /** View which displays smart reply buttons in notifications. */
@@ -19,8 +20,11 @@
 
     private static final String TAG = "SmartReplyView";
 
+    private final SmartReplyConstants mConstants;
+
     public SmartReplyView(Context context, AttributeSet attrs) {
         super(context, attrs);
+        mConstants = Dependency.get(SmartReplyConstants.class);
     }
 
     public void setRepliesFromRemoteInput(RemoteInput remoteInput, PendingIntent pendingIntent) {
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
index fb5c447..1e8e98c 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
@@ -68,6 +68,7 @@
 import android.view.accessibility.AccessibilityManager.AccessibilityStateChangeListener;
 import android.view.animation.DecelerateInterpolator;
 import android.widget.ImageButton;
+import android.widget.ImageView;
 import android.widget.SeekBar;
 import android.widget.SeekBar.OnSeekBarChangeListener;
 import android.widget.TextView;
@@ -109,7 +110,9 @@
     private ViewGroup mDialogRowsView;
     private ViewGroup mFooter;
     private ImageButton mRingerIcon;
+    private ImageView mZenIcon;
     private TextView mRingerStatus;
+    private TextView mRingerTitle;
     private final List<VolumeRow> mRows = new ArrayList<>();
     private ConfigurableTexts mConfigurableTexts;
     private final SparseBooleanArray mDynamic = new SparseBooleanArray();
@@ -175,7 +178,6 @@
                 | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
                 | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
                 | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
-        mWindow.setTitle(VolumeDialogImpl.class.getSimpleName());
         mWindow.setType(WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY);
         mWindow.setWindowAnimations(com.android.internal.R.style.Animation_Toast);
         final WindowManager.LayoutParams lp = mWindow.getAttributes();
@@ -216,6 +218,8 @@
         mFooter = mDialog.findViewById(R.id.footer);
         mRingerIcon = mFooter.findViewById(R.id.ringer_icon);
         mRingerStatus = mFooter.findViewById(R.id.ringer_status);
+        mRingerTitle = mFooter.findViewById(R.id.ringer_title);
+        mZenIcon = mFooter.findViewById(R.id.dnd_icon);
 
         if (mRows.isEmpty()) {
             addRow(AudioManager.STREAM_MUSIC,
@@ -349,6 +353,7 @@
         if (stream == STREAM_ACCESSIBILITY) {
             row.header.setFilters(new InputFilter[] {new InputFilter.LengthFilter(13)});
         }
+        row.dndIcon = row.view.findViewById(R.id.dnd_icon);
         row.slider =  row.view.findViewById(R.id.volume_row_slider);
         row.slider.setOnSeekBarChangeListener(new VolumeSeekBarChangeListener(row));
         row.anim = null;
@@ -404,6 +409,7 @@
             final boolean hasVibrator = mController.hasVibrator();
             if (mState.ringerModeInternal == AudioManager.RINGER_MODE_NORMAL) {
                 if (hasVibrator) {
+                    mController.vibrate();
                     mController.setRingerMode(AudioManager.RINGER_MODE_VIBRATE, false);
                 } else {
                     mController.setRingerMode(AudioManager.RINGER_MODE_SILENT, false);
@@ -485,15 +491,6 @@
                 }, 50))
                 .start();
 
-        if (mAccessibilityMgr.isEnabled()) {
-            AccessibilityEvent event =
-                    AccessibilityEvent.obtain(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
-            event.setPackageName(mContext.getPackageName());
-            event.setClassName(CustomDialog.class.getSuperclass().getName());
-            event.getText().add(mContext.getString(
-                    R.string.volume_dialog_accessibility_dismissed_message));
-            mAccessibilityMgr.sendAccessibilityEvent(event);
-        }
         Events.writeEvent(mContext, Events.EVENT_DISMISS_DIALOG, reason);
         mController.notifyVisible(false);
         synchronized (mSafetyWarningLock) {
@@ -559,6 +556,8 @@
             if (ss == null) {
                 return;
             }
+
+            enableRingerViewsH(mState.zenMode == Global.ZEN_MODE_OFF || !mState.disallowRinger);
             switch (mState.ringerModeInternal) {
                 case AudioManager.RINGER_MODE_VIBRATE:
                     mRingerStatus.setText(R.string.volume_ringer_status_vibrate);
@@ -603,6 +602,28 @@
         }
     }
 
+    /**
+     * Toggles enable state of views in a VolumeRow (not including seekbar, outputChooser or icon)
+     * Hides/shows zen icon
+     * @param enable whether to enable volume row views and hide dnd icon
+     */
+    private void enableVolumeRowViewsH(VolumeRow row, boolean enable) {
+        row.header.setEnabled(enable);
+        row.dndIcon.setVisibility(enable ? View.GONE : View.VISIBLE);
+    }
+
+    /**
+     * Toggles enable state of footer/ringer views
+     * Hides/shows zen icon
+     * @param enable whether to enable ringer views and hide dnd icon
+     */
+    private void enableRingerViewsH(boolean enable) {
+        mRingerTitle.setEnabled(enable);
+        mRingerStatus.setEnabled(enable);
+        mRingerIcon.setEnabled(enable);
+        mZenIcon.setVisibility(enable ? View.GONE : View.VISIBLE);
+    }
+
     private void trimObsoleteH() {
         if (D.BUG) Log.d(TAG, "trimObsoleteH");
         for (int i = mRows.size() - 1; i >= 0; i--) {
@@ -640,6 +661,8 @@
             updateVolumeRowH(row);
         }
         updateRingerH();
+        mWindow.setTitle(mContext.getString(R.string.volume_dialog_title,
+                getStreamLabelH(getActiveRow().ss)));
     }
 
     private void updateVolumeRowH(VolumeRow row) {
@@ -748,6 +771,7 @@
         if (zenMuted) {
             row.tracking = false;
         }
+        enableVolumeRowViewsH(row, !zenMuted);
 
         // update slider
         final boolean enableSlider = !zenMuted;
@@ -1034,22 +1058,6 @@
             }
             return false;
         }
-
-        @Override
-        public boolean dispatchPopulateAccessibilityEvent(@NonNull AccessibilityEvent event) {
-            event.setClassName(getClass().getSuperclass().getName());
-            event.setPackageName(mContext.getPackageName());
-
-            if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
-                if (mShowing) {
-                    event.getText().add(mContext.getString(
-                            R.string.volume_dialog_accessibility_shown_message,
-                            getStreamLabelH(getActiveRow().ss)));
-                    return true;
-                }
-            }
-            return false;
-        }
     }
 
     private final class VolumeSeekBarChangeListener implements OnSeekBarChangeListener {
@@ -1178,5 +1186,6 @@
         private int lastAudibleLevel = 1;
         private View outputChooser;
         private TextView connectedDevice;
+        private ImageView dndIcon;
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java
index 8e8b3e0..b8d9b19 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java
@@ -16,7 +16,9 @@
 
 package com.android.systemui.statusbar;
 
+import static android.app.NotificationChannel.USER_LOCKED_IMPORTANCE;
 import static android.app.NotificationManager.IMPORTANCE_LOW;
+import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
 import static android.print.PrintManager.PRINT_SPOOLER_PACKAGE_NAME;
 import static android.view.View.GONE;
 import static android.view.View.VISIBLE;
@@ -95,6 +97,7 @@
         final LayoutInflater layoutInflater = LayoutInflater.from(mContext);
         mNotificationInfo = (NotificationInfo) layoutInflater.inflate(R.layout.notification_info,
                 null);
+        mNotificationInfo.setGutsParent(mock(NotificationGuts.class));
 
         // PackageManager must return a packageInfo and applicationInfo.
         final PackageInfo packageInfo = new PackageInfo();
@@ -323,24 +326,27 @@
     @Test
     public void testHandleCloseControls_DoesNotUpdateNotificationChannelIfUnchanged()
             throws Exception {
+        int originalImportance = mNotificationChannel.getImportance();
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                 TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, null);
 
         mNotificationInfo.handleCloseControls(true, false);
-        verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
+        verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
                 anyString(), eq(TEST_UID), any());
+        assertEquals(originalImportance, mNotificationChannel.getImportance());
     }
 
     @Test
     public void testHandleCloseControls_DoesNotUpdateNotificationChannelIfUnspecified()
             throws Exception {
-        mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_UNSPECIFIED);
+        mNotificationChannel.setImportance(IMPORTANCE_UNSPECIFIED);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                 TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, null);
 
         mNotificationInfo.handleCloseControls(true, false);
-        verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
+        verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
                 anyString(), eq(TEST_UID), any());
+        assertEquals(IMPORTANCE_UNSPECIFIED, mNotificationChannel.getImportance());
     }
 
     @Test
@@ -370,16 +376,30 @@
         verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
                 anyString(), eq(TEST_UID), updated.capture());
         assertTrue((updated.getValue().getUserLockedFields()
-                & NotificationChannel.USER_LOCKED_IMPORTANCE) != 0);
+                & USER_LOCKED_IMPORTANCE) != 0);
     }
 
     @Test
-    public void testBlockUndoDoesNotCallUpdateNotificationChannel() throws Exception {
+    public void testKeepUpdatesNotificationChannel() throws Exception {
         mNotificationChannel.setImportance(IMPORTANCE_LOW);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null,
-                Collections.singleton(TEST_PACKAGE_NAME));
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, null);
 
+        mNotificationInfo.handleCloseControls(true, false);
+
+        ArgumentCaptor<NotificationChannel> updated =
+                ArgumentCaptor.forClass(NotificationChannel.class);
+        verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
+                anyString(), eq(TEST_UID), updated.capture());
+        assertTrue(0 != (mNotificationChannel.getUserLockedFields() & USER_LOCKED_IMPORTANCE));
+        assertEquals(IMPORTANCE_LOW, mNotificationChannel.getImportance());
+    }
+
+    @Test
+    public void testBlockUndoDoesNotBlockNotificationChannel() throws Exception {
+        mNotificationChannel.setImportance(IMPORTANCE_LOW);
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, null);
 
         mNotificationInfo.findViewById(R.id.block).performClick();
         waitForUndoButton();
@@ -389,8 +409,9 @@
 
         ArgumentCaptor<NotificationChannel> updated =
                 ArgumentCaptor.forClass(NotificationChannel.class);
-        verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
+        verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
                 anyString(), eq(TEST_UID), updated.capture());
+        assertTrue(0 != (mNotificationChannel.getUserLockedFields() & USER_LOCKED_IMPORTANCE));
         assertEquals(IMPORTANCE_LOW, mNotificationChannel.getImportance());
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
index 43e16db..4702793 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
@@ -180,6 +180,7 @@
 
     @Test
     public void transitionToUnlocked() {
+        mScrimController.setPanelExpansion(0f);
         mScrimController.transitionTo(ScrimState.UNLOCKED);
         mScrimController.finishAnimationsImmediately();
         // Front scrim should be transparent
@@ -197,6 +198,7 @@
     public void transitionToUnlockedFromAod() {
         // Simulate unlock with fingerprint
         mScrimController.transitionTo(ScrimState.AOD);
+        mScrimController.setPanelExpansion(0f);
         mScrimController.finishAnimationsImmediately();
         mScrimController.transitionTo(ScrimState.UNLOCKED);
         // Immediately tinted after the transition starts
@@ -324,6 +326,23 @@
         verify(mAlarmManager).cancel(any(AlarmManager.OnAlarmListener.class));
     }
 
+    @Test
+    public void testConservesExpansionOpacityAfterTransition() {
+        mScrimController.transitionTo(ScrimState.UNLOCKED);
+        mScrimController.setPanelExpansion(0.5f);
+        mScrimController.finishAnimationsImmediately();
+
+        final float expandedAlpha = mScrimBehind.getViewAlpha();
+
+        mScrimController.transitionTo(ScrimState.BRIGHTNESS_MIRROR);
+        mScrimController.finishAnimationsImmediately();
+        mScrimController.transitionTo(ScrimState.UNLOCKED);
+        mScrimController.finishAnimationsImmediately();
+
+        Assert.assertEquals("Scrim expansion opacity wasn't conserved when transitioning back",
+                expandedAlpha, mScrimBehind.getViewAlpha(), 0.01f);
+    }
+
     private void assertScrimTint(ScrimView scrimView, boolean tinted) {
         final boolean viewIsTinted = scrimView.getTint() != Color.TRANSPARENT;
         final String name = scrimView == mScrimInFront ? "front" : "back";
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
index f685b1f..8aab837 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
@@ -43,9 +43,9 @@
 import android.util.Log;
 
 import com.android.internal.telephony.cdma.EriInfo;
+import com.android.settingslib.graph.SignalDrawable;
 import com.android.settingslib.net.DataUsageController;
 import com.android.systemui.SysuiTestCase;
-import com.android.systemui.statusbar.phone.SignalDrawable;
 import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
 import com.android.systemui.statusbar.policy.NetworkController.IconState;
 import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
index 3ad107c..550f4a7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
@@ -30,9 +30,9 @@
 
 import com.android.internal.telephony.PhoneConstants;
 import com.android.internal.telephony.TelephonyIntents;
+import com.android.settingslib.graph.SignalDrawable;
 import com.android.settingslib.net.DataUsageController;
 import com.android.systemui.R;
-import com.android.systemui.statusbar.phone.SignalDrawable;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyConstantsTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyConstantsTest.java
new file mode 100644
index 0000000..32a7cb9
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyConstantsTest.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.policy;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertTrue;
+
+import android.os.Handler;
+import android.os.Looper;
+import android.provider.Settings;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+import android.testing.TestableResources;
+
+import com.android.systemui.R;
+import com.android.systemui.SysuiTestCase;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
+@SmallTest
+public class SmartReplyConstantsTest extends SysuiTestCase {
+
+    private static final int CONTENT_OBSERVER_TIMEOUT_SECONDS = 10;
+
+    private SmartReplyConstants mConstants;
+
+    @Before
+    public void setUp() {
+        overrideSetting(null); // No config.
+        TestableResources resources = mContext.getOrCreateTestableResources();
+        resources.addOverride(R.bool.config_smart_replies_in_notifications_enabled, true);
+        resources.addOverride(
+                R.integer.config_smart_replies_in_notifications_max_squeeze_remeasure_attempts, 7);
+        mConstants = new SmartReplyConstants(new Handler(Looper.getMainLooper()), mContext);
+    }
+
+    @Test
+    public void testIsEnabledWithNoConfig() {
+        assertTrue(mConstants.isEnabled());
+    }
+
+    @Test
+    public void testIsEnabledWithInvalidConfig() {
+        overrideSetting("invalid config");
+        triggerConstantsOnChange();
+        assertTrue(mConstants.isEnabled());
+    }
+
+    @Test
+    public void testIsEnabledWithValidConfig() {
+        overrideSetting("enabled=false,max_squeeze_remeasure_attempts=5");
+        triggerConstantsOnChange();
+        assertFalse(mConstants.isEnabled());
+    }
+
+    @Test
+    public void testGetMaxSqueezeRemeasureAttemptsWithNoConfig() {
+        assertTrue(mConstants.isEnabled());
+        assertEquals(7, mConstants.getMaxSqueezeRemeasureAttempts());
+    }
+
+    @Test
+    public void testGetMaxSqueezeRemeasureAttemptsWithInvalidConfig() {
+        overrideSetting("invalid config");
+        triggerConstantsOnChange();
+        assertEquals(7, mConstants.getMaxSqueezeRemeasureAttempts());
+    }
+
+    @Test
+    public void testGetMaxSqueezeRemeasureAttemptsWithValidConfig() {
+        overrideSetting("enabled=false,max_squeeze_remeasure_attempts=5");
+        triggerConstantsOnChange();
+        assertEquals(5, mConstants.getMaxSqueezeRemeasureAttempts());
+    }
+
+    private void overrideSetting(String flags) {
+        Settings.Global.putString(mContext.getContentResolver(),
+                Settings.Global.SMART_REPLIES_IN_NOTIFICATIONS_FLAGS, flags);
+    }
+
+    private void triggerConstantsOnChange() {
+        // Since Settings.Global is mocked in TestableContext, we need to manually trigger the
+        // content observer.
+        mConstants.onChange(false,
+                Settings.Global.getUriFor(Settings.Global.SMART_REPLIES_IN_NOTIFICATIONS_FLAGS));
+    }
+}
diff --git a/packages/WallpaperCropper/Android.mk b/packages/WallpaperCropper/Android.mk
index 0254673..7efe8ab 100644
--- a/packages/WallpaperCropper/Android.mk
+++ b/packages/WallpaperCropper/Android.mk
@@ -5,8 +5,6 @@
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
-LOCAL_JAVA_LIBRARIES := telephony-common
-
 LOCAL_PACKAGE_NAME := WallpaperCropper
 LOCAL_CERTIFICATE := platform
 LOCAL_PRIVILEGED_MODULE := true
diff --git a/rs/jni/android_renderscript_RenderScript.cpp b/rs/jni/android_renderscript_RenderScript.cpp
index 52d0e08e..b32be73 100644
--- a/rs/jni/android_renderscript_RenderScript.cpp
+++ b/rs/jni/android_renderscript_RenderScript.cpp
@@ -24,9 +24,8 @@
 #include <utils/misc.h>
 #include <inttypes.h>
 
-#include <android-base/macros.h>
 #include <androidfw/Asset.h>
-#include <androidfw/AssetManager2.h>
+#include <androidfw/AssetManager.h>
 #include <androidfw/ResourceTypes.h>
 #include <android-base/macros.h>
 
@@ -1665,22 +1664,18 @@
 static jlong
 nFileA3DCreateFromAsset(JNIEnv *_env, jobject _this, jlong con, jobject _assetMgr, jstring _path)
 {
-    Guarded<AssetManager2>* mgr = AssetManagerForJavaObject(_env, _assetMgr);
+    AssetManager* mgr = assetManagerForJavaObject(_env, _assetMgr);
     if (mgr == nullptr) {
         return 0;
     }
 
     AutoJavaStringToUTF8 str(_env, _path);
-    std::unique_ptr<Asset> asset;
-    {
-        ScopedLock<AssetManager2> locked_mgr(*mgr);
-        asset = locked_mgr->Open(str.c_str(), Asset::ACCESS_BUFFER);
-        if (asset == nullptr) {
-            return 0;
-        }
+    Asset* asset = mgr->open(str.c_str(), Asset::ACCESS_BUFFER);
+    if (asset == nullptr) {
+        return 0;
     }
 
-    jlong id = (jlong)(uintptr_t)rsaFileA3DCreateFromAsset((RsContext)con, asset.release());
+    jlong id = (jlong)(uintptr_t)rsaFileA3DCreateFromAsset((RsContext)con, asset);
     return id;
 }
 
@@ -1757,25 +1752,22 @@
 nFontCreateFromAsset(JNIEnv *_env, jobject _this, jlong con, jobject _assetMgr, jstring _path,
                      jfloat fontSize, jint dpi)
 {
-    Guarded<AssetManager2>* mgr = AssetManagerForJavaObject(_env, _assetMgr);
+    AssetManager* mgr = assetManagerForJavaObject(_env, _assetMgr);
     if (mgr == nullptr) {
         return 0;
     }
 
     AutoJavaStringToUTF8 str(_env, _path);
-    std::unique_ptr<Asset> asset;
-    {
-        ScopedLock<AssetManager2> locked_mgr(*mgr);
-        asset = locked_mgr->Open(str.c_str(), Asset::ACCESS_BUFFER);
-        if (asset == nullptr) {
-            return 0;
-        }
+    Asset* asset = mgr->open(str.c_str(), Asset::ACCESS_BUFFER);
+    if (asset == nullptr) {
+        return 0;
     }
 
     jlong id = (jlong)(uintptr_t)rsFontCreateFromMemory((RsContext)con,
                                            str.c_str(), str.length(),
                                            fontSize, dpi,
                                            asset->getBuffer(false), asset->getLength());
+    delete asset;
     return id;
 }
 
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index 978ba0f..a422b7c 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -1841,16 +1841,16 @@
                 pw.print("  Time since non-interactive: ");
                 TimeUtils.formatDuration(nowELAPSED - mNonInteractiveStartTime, pw);
                 pw.println();
-                pw.print("  Max wakeup delay: ");
-                TimeUtils.formatDuration(currentNonWakeupFuzzLocked(nowELAPSED), pw);
-                pw.println();
-                pw.print("  Time since last dispatch: ");
-                TimeUtils.formatDuration(nowELAPSED - mLastAlarmDeliveryTime, pw);
-                pw.println();
-                pw.print("  Next non-wakeup delivery time: ");
-                TimeUtils.formatDuration(nowELAPSED - mNextNonWakeupDeliveryTime, pw);
-                pw.println();
             }
+            pw.print("  Max wakeup delay: ");
+            TimeUtils.formatDuration(currentNonWakeupFuzzLocked(nowELAPSED), pw);
+            pw.println();
+            pw.print("  Time since last dispatch: ");
+            TimeUtils.formatDuration(nowELAPSED - mLastAlarmDeliveryTime, pw);
+            pw.println();
+            pw.print("  Next non-wakeup delivery time: ");
+            TimeUtils.formatDuration(nowELAPSED - mNextNonWakeupDeliveryTime, pw);
+            pw.println();
 
             long nextWakeupRTC = mNextWakeup + (nowRTC - nowELAPSED);
             long nextNonWakeupRTC = mNextNonWakeup + (nowRTC - nowELAPSED);
@@ -2584,7 +2584,7 @@
         if (mAlarmBatches.size() > 0) {
             final Batch firstWakeup = findFirstWakeupBatchLocked();
             final Batch firstBatch = mAlarmBatches.get(0);
-            if (firstWakeup != null && mNextWakeup != firstWakeup.start) {
+            if (firstWakeup != null) {
                 mNextWakeup = firstWakeup.start;
                 mLastWakeupSet = SystemClock.elapsedRealtime();
                 setLocked(ELAPSED_REALTIME_WAKEUP, firstWakeup.start);
@@ -2598,7 +2598,7 @@
                 nextNonWakeup = mNextNonWakeupDeliveryTime;
             }
         }
-        if (nextNonWakeup != 0 && mNextNonWakeup != nextNonWakeup) {
+        if (nextNonWakeup != 0) {
             mNextNonWakeup = nextNonWakeup;
             setLocked(ELAPSED_REALTIME, nextNonWakeup);
         }
@@ -3229,6 +3229,8 @@
                     expectedMaxWhenElapsed, nowELAPSED, pw);
                     pw.print(" whenElapsed="); TimeUtils.formatDuration(whenElapsed,
                             nowELAPSED, pw);
+                    pw.print(" maxWhenElapsed="); TimeUtils.formatDuration(maxWhenElapsed,
+                            nowELAPSED, pw);
                     pw.print(" when=");
                     if (isRtc) {
                         pw.print(sdf.format(new Date(when)));
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index 2077790..55ad8cc 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -948,8 +948,11 @@
         return true;
     }
 
-    private boolean startConsentUiIfNeeded(String packageName, int callingUid, String intentAction)
-            throws RemoteException {
+    private boolean startConsentUiIfNeeded(String packageName,
+            int callingUid, String intentAction) throws RemoteException {
+        if (checkBluetoothPermissionWhenPermissionReviewRequired()) {
+            return false;
+        }
         try {
             // Validate the package only if we are going to use it
             ApplicationInfo applicationInfo = mContext.getPackageManager()
@@ -957,7 +960,8 @@
                             PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
                             UserHandle.getUserId(callingUid));
             if (applicationInfo.uid != callingUid) {
-                throw new SecurityException("Package " + callingUid + " not in uid " + callingUid);
+                throw new SecurityException("Package " + packageName
+                        + " not in uid " + callingUid);
             }
 
             Intent intent = new Intent(intentAction);
@@ -977,6 +981,26 @@
         }
     }
 
+    /**
+     * Check if the caller must still pass permission check or if the caller is exempted
+     * from the consent UI via the MANAGE_BLUETOOTH_WHEN_PERMISSION_REVIEW_REQUIRED check.
+     *
+     * Commands from some callers may be exempted from triggering the consent UI when
+     * enabling bluetooth. This exemption is checked via the
+     * MANAGE_BLUETOOTH_WHEN_PERMISSION_REVIEW_REQUIRED and allows calls to skip
+     * the consent UI where it may otherwise be required.
+     *
+     * @hide
+     */
+    private boolean checkBluetoothPermissionWhenPermissionReviewRequired() {
+        if (!mPermissionReviewRequired) {
+            return false;
+        }
+        int result = mContext.checkCallingPermission(
+                android.Manifest.permission.MANAGE_BLUETOOTH_WHEN_PERMISSION_REVIEW_REQUIRED);
+        return result == PackageManager.PERMISSION_GRANTED;
+    }
+
     public void unbindAndFinish() {
         if (DBG) {
             Slog.d(TAG, "unbindAndFinish(): " + mBluetooth + " mBinding = " + mBinding
diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java
index a07a982..45a4dfb9 100644
--- a/services/core/java/com/android/server/IpSecService.java
+++ b/services/core/java/com/android/server/IpSecService.java
@@ -1438,7 +1438,9 @@
 
         switch (config.getMode()) {
             case IpSecTransform.MODE_TRANSPORT:
+                break;
             case IpSecTransform.MODE_TUNNEL:
+                enforceNetworkStackPermission();
                 break;
             default:
                 throw new IllegalArgumentException(
@@ -1446,6 +1448,11 @@
         }
     }
 
+    private void enforceNetworkStackPermission() {
+        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.NETWORK_STACK,
+                "IpSecService");
+    }
+
     private void createOrUpdateTransform(
             IpSecConfig c, int resourceId, SpiRecord spiRecord, EncapSocketRecord socketRecord)
             throws RemoteException {
@@ -1615,6 +1622,7 @@
     @Override
     public synchronized void applyTunnelModeTransform(
             int tunnelResourceId, int direction, int transformResourceId) throws RemoteException {
+        enforceNetworkStackPermission();
         checkDirection(direction);
 
         UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid());
diff --git a/services/core/java/com/android/server/VibratorService.java b/services/core/java/com/android/server/VibratorService.java
index 0baa3d0..7fe5d7c 100644
--- a/services/core/java/com/android/server/VibratorService.java
+++ b/services/core/java/com/android/server/VibratorService.java
@@ -912,6 +912,7 @@
         Vibration fallbackVib =
                 new Vibration(vib.token, effect, vib.usageHint, vib.uid, vib.opPkg);
         final int intensity = getCurrentIntensityLocked(fallbackVib);
+        linkVibration(fallbackVib);
         applyVibrationIntensityScalingLocked(fallbackVib, intensity);
         startVibrationInnerLocked(fallbackVib);
         return 0;
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 230f69d..14404f5 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -1043,14 +1043,20 @@
                         throw new SecurityException("Instant app " + r.appInfo.packageName
                                 + " does not have permission to create foreground services");
                     default:
-                        mAm.enforcePermission(
-                                android.Manifest.permission.INSTANT_APP_FOREGROUND_SERVICE,
-                                r.app.pid, r.appInfo.uid, "startForeground");
+                        try {
+                            if (AppGlobals.getPackageManager().checkPermission(
+                                    android.Manifest.permission.INSTANT_APP_FOREGROUND_SERVICE,
+                                    r.appInfo.packageName, UserHandle.getUserId(r.appInfo.uid))
+                                            != PackageManager.PERMISSION_GRANTED) {
+                                throw new SecurityException("Instant app " + r.appInfo.packageName
+                                        + " does not have permission to create foreground"
+                                        + "services");
+                            }
+                        } catch (RemoteException e) {
+                            throw new SecurityException("Failed to check instant app permission." ,
+                                    e);
+                        }
                 }
-            } else if (r.appInfo.targetSdkVersion >= Build.VERSION_CODES.P) {
-                mAm.enforcePermission(
-                        android.Manifest.permission.FOREGROUND_SERVICE,
-                        r.app.pid, r.appInfo.uid, "startForeground");
             }
             if (r.fgRequired) {
                 if (DEBUG_SERVICE || DEBUG_BACKGROUND_CHECK) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java b/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java
index 0a7d3fd..87e8121 100644
--- a/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java
+++ b/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java
@@ -65,7 +65,7 @@
     static final boolean DEBUG_NETWORK = DEBUG_ALL || false;
     static final boolean DEBUG_OOM_ADJ = DEBUG_ALL || false;
     static final boolean DEBUG_OOM_ADJ_REASON = DEBUG_ALL || false;
-    static final boolean DEBUG_PAUSE = DEBUG_ALL || false;
+    static final boolean DEBUG_PAUSE = DEBUG_ALL || true;
     static final boolean DEBUG_POWER = DEBUG_ALL || false;
     static final boolean DEBUG_POWER_QUICK = DEBUG_POWER || false;
     static final boolean DEBUG_PROCESS_OBSERVERS = DEBUG_ALL || false;
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index cd8b6d7..c958b67 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -8889,20 +8889,6 @@
     /**
      * This can be called with or without the global lock held.
      */
-    void enforcePermission(String permission, int pid, int uid, String func) {
-        if (checkPermission(permission, pid, uid) == PackageManager.PERMISSION_GRANTED) {
-            return;
-        }
-
-        String msg = "Permission Denial: " + func + " from pid=" + pid + ", uid=" + uid
-                + " requires " + permission;
-        Slog.w(TAG, msg);
-        throw new SecurityException(msg);
-    }
-
-    /**
-     * This can be called with or without the global lock held.
-     */
     void enforceCallerIsRecentsOrHasPermission(String permission, String func) {
         if (!mRecentTasks.isCallerRecents(Binder.getCallingUid())) {
             enforceCallingPermission(permission, func);
@@ -25697,9 +25683,11 @@
             }
 
             synchronized (ActivityManagerService.this) {
-                return mActivityStartController.startActivitiesInPackage(packageUid, packageName,
+                return mActivityStartController.startActivitiesInPackage(
+                        packageUid, packageName,
                         intents, resolvedTypes, null /* resultTo */,
-                        SafeActivityOptions.fromBundle(bOptions), userId);
+                        SafeActivityOptions.fromBundle(bOptions), userId,
+                        false /* validateIncomingUser */);
             }
         }
 
diff --git a/services/core/java/com/android/server/am/ActivityMetricsLogger.java b/services/core/java/com/android/server/am/ActivityMetricsLogger.java
index 66f0592..e2ceb31 100644
--- a/services/core/java/com/android/server/am/ActivityMetricsLogger.java
+++ b/services/core/java/com/android/server/am/ActivityMetricsLogger.java
@@ -32,6 +32,8 @@
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_METRICS;
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
+import static com.android.server.am.MemoryStatUtil.MemoryStat;
+import static com.android.server.am.MemoryStatUtil.readMemoryStatFromMemcg;
 
 import android.content.Context;
 import android.metrics.LogMaker;
@@ -67,6 +69,7 @@
     private static final long INVALID_START_TIME = -1;
 
     private static final int MSG_CHECK_VISIBILITY = 0;
+    private static final int MSG_LOG_APP_START_MEMORY_STATE_CAPTURE = 1;
 
     // Preallocated strings we are sending to tron, so we don't have to allocate a new one every
     // time we log.
@@ -102,6 +105,9 @@
                     final SomeArgs args = (SomeArgs) msg.obj;
                     checkVisibility((TaskRecord) args.arg1, (ActivityRecord) args.arg2);
                     break;
+                case MSG_LOG_APP_START_MEMORY_STATE_CAPTURE:
+                    logAppStartMemoryStateCapture((StackTransitionInfo) msg.obj);
+                    break;
             }
         }
     };
@@ -187,10 +193,7 @@
      * @param launchedActivity the activity that is being launched
      */
     void notifyActivityLaunched(int resultCode, ActivityRecord launchedActivity) {
-        final ProcessRecord processRecord = launchedActivity != null
-                ? mSupervisor.mService.mProcessNames.get(launchedActivity.processName,
-                        launchedActivity.appInfo.uid)
-                : null;
+        final ProcessRecord processRecord = findProcessForActivity(launchedActivity);
         final boolean processRunning = processRecord != null;
 
         // We consider this a "process switch" if the process of the activity that gets launched
@@ -492,6 +495,7 @@
                     info.bindApplicationDelayMs,
                     info.windowsDrawnDelayMs,
                     launchToken);
+            mHandler.obtainMessage(MSG_LOG_APP_START_MEMORY_STATE_CAPTURE, info).sendToTarget();
         }
     }
 
@@ -548,4 +552,38 @@
         }
         return -1;
     }
+
+    private void logAppStartMemoryStateCapture(StackTransitionInfo info) {
+        final ProcessRecord processRecord = findProcessForActivity(info.launchedActivity);
+        if (processRecord == null) {
+            if (DEBUG_METRICS) Slog.i(TAG, "logAppStartMemoryStateCapture processRecord null");
+            return;
+        }
+
+        final int pid = processRecord.pid;
+        final int uid = info.launchedActivity.appInfo.uid;
+        final MemoryStat memoryStat = readMemoryStatFromMemcg(uid, pid);
+        if (memoryStat == null) {
+            if (DEBUG_METRICS) Slog.i(TAG, "logAppStartMemoryStateCapture memoryStat null");
+            return;
+        }
+
+        StatsLog.write(
+                StatsLog.APP_START_MEMORY_STATE_CAPTURED,
+                uid,
+                info.launchedActivity.processName,
+                info.launchedActivity.info.name,
+                memoryStat.pgfault,
+                memoryStat.pgmajfault,
+                memoryStat.rssInBytes,
+                memoryStat.cacheInBytes,
+                memoryStat.swapInBytes);
+    }
+
+    private ProcessRecord findProcessForActivity(ActivityRecord launchedActivity) {
+        return launchedActivity != null
+                ? mSupervisor.mService.mProcessNames.get(launchedActivity.processName,
+                        launchedActivity.appInfo.uid)
+                : null;
+    }
 }
diff --git a/services/core/java/com/android/server/am/ActivityStartController.java b/services/core/java/com/android/server/am/ActivityStartController.java
index 5551914..da11f686 100644
--- a/services/core/java/com/android/server/am/ActivityStartController.java
+++ b/services/core/java/com/android/server/am/ActivityStartController.java
@@ -245,11 +245,25 @@
                 .execute();
     }
 
+    /**
+     * Start intents as a package.
+     *
+     * @param uid Make a call as if this UID did.
+     * @param callingPackage Make a call as if this package did.
+     * @param intents Intents to start.
+     * @param userId Start the intents on this user.
+     * @param validateIncomingUser Set true to skip checking {@code userId} with the calling UID.
+     */
     final int startActivitiesInPackage(int uid, String callingPackage, Intent[] intents,
-            String[] resolvedTypes, IBinder resultTo, SafeActivityOptions options, int userId) {
+            String[] resolvedTypes, IBinder resultTo, SafeActivityOptions options, int userId,
+            boolean validateIncomingUser) {
         final String reason = "startActivityInPackage";
-        userId = mService.mUserController.handleIncomingUser(Binder.getCallingPid(),
-                Binder.getCallingUid(), userId, false, ALLOW_FULL_ONLY, reason, null);
+        if (validateIncomingUser) {
+            userId = mService.mUserController.handleIncomingUser(Binder.getCallingPid(),
+                    Binder.getCallingUid(), userId, false, ALLOW_FULL_ONLY, reason, null);
+        } else {
+            mService.mUserController.ensureNotSpecialUser(userId);
+        }
         // TODO: Switch to user app stacks here.
         return startActivities(null, uid, callingPackage, intents, resolvedTypes, resultTo, options,
                 userId, reason);
diff --git a/services/core/java/com/android/server/am/MemoryStatUtil.java b/services/core/java/com/android/server/am/MemoryStatUtil.java
new file mode 100644
index 0000000..d97c2a2
--- /dev/null
+++ b/services/core/java/com/android/server/am/MemoryStatUtil.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.am;
+
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_METRICS;
+import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
+import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
+
+import android.annotation.Nullable;
+import android.os.FileUtils;
+import android.util.Slog;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Static utility methods related to {@link MemoryStat}.
+ */
+final class MemoryStatUtil {
+    private static final String TAG = TAG_WITH_CLASS_NAME ? "MemoryStatUtil" : TAG_AM;
+
+    /** Path to memory stat file for logging app start memory state */
+    private static final String MEMORY_STAT_FILE_FMT = "/dev/memcg/apps/uid_%d/pid_%d/memory.stat";
+
+    private static final Pattern PGFAULT = Pattern.compile("total_pgfault (\\d+)");
+    private static final Pattern PGMAJFAULT = Pattern.compile("total_pgmajfault (\\d+)");
+    private static final Pattern RSS_IN_BYTES = Pattern.compile("total_rss (\\d+)");
+    private static final Pattern CACHE_IN_BYTES = Pattern.compile("total_cache (\\d+)");
+    private static final Pattern SWAP_IN_BYTES = Pattern.compile("total_swap (\\d+)");
+
+    private MemoryStatUtil() {}
+
+    /**
+     * Reads memory.stat of a process from memcg.
+     */
+    static @Nullable MemoryStat readMemoryStatFromMemcg(int uid, int pid) {
+        final String memoryStatPath = String.format(MEMORY_STAT_FILE_FMT, uid, pid);
+        final File memoryStatFile = new File(memoryStatPath);
+        if (!memoryStatFile.exists()) {
+            if (DEBUG_METRICS) Slog.i(TAG, memoryStatPath + " not found");
+            return null;
+        }
+
+        try {
+            final String memoryStatContents = FileUtils.readTextFile(
+                    memoryStatFile, 0 /* max */, null /* ellipsis */);
+            return parseMemoryStat(memoryStatContents);
+        } catch (IOException e) {
+            Slog.e(TAG, "Failed to read file:", e);
+            return null;
+        }
+    }
+
+    /**
+     * Parses relevant statistics out from the contents of a memory.stat file in memcg.
+     */
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+    static @Nullable MemoryStat parseMemoryStat(String memoryStatContents) {
+        MemoryStat memoryStat = new MemoryStat();
+        if (memoryStatContents == null) {
+            return memoryStat;
+        }
+
+        Matcher m;
+        m = PGFAULT.matcher(memoryStatContents);
+        memoryStat.pgfault = m.find() ? Long.valueOf(m.group(1)) : 0;
+        m = PGMAJFAULT.matcher(memoryStatContents);
+        memoryStat.pgmajfault = m.find() ? Long.valueOf(m.group(1)) : 0;
+        m = RSS_IN_BYTES.matcher(memoryStatContents);
+        memoryStat.rssInBytes = m.find() ? Long.valueOf(m.group(1)) : 0;
+        m = CACHE_IN_BYTES.matcher(memoryStatContents);
+        memoryStat.cacheInBytes = m.find() ? Long.valueOf(m.group(1)) : 0;
+        m = SWAP_IN_BYTES.matcher(memoryStatContents);
+        memoryStat.swapInBytes = m.find() ? Long.valueOf(m.group(1)) : 0;
+        return memoryStat;
+    }
+
+    static final class MemoryStat {
+        /** Number of page faults */
+        long pgfault;
+        /** Number of major page faults */
+        long pgmajfault;
+        /** Number of bytes of anonymous and swap cache memory */
+        long rssInBytes;
+        /** Number of bytes of page cache memory */
+        long cacheInBytes;
+        /** Number of bytes of swap usage */
+        long swapInBytes;
+    }
+}
diff --git a/services/core/java/com/android/server/am/PendingIntentRecord.java b/services/core/java/com/android/server/am/PendingIntentRecord.java
index 8e9d85d..264609f 100644
--- a/services/core/java/com/android/server/am/PendingIntentRecord.java
+++ b/services/core/java/com/android/server/am/PendingIntentRecord.java
@@ -335,7 +335,8 @@
                                 allResolvedTypes[allResolvedTypes.length-1] = resolvedType;
                                 res = owner.getActivityStartController().startActivitiesInPackage(
                                         uid, key.packageName, allIntents, allResolvedTypes,
-                                        resultTo, mergedOptions, userId);
+                                        resultTo, mergedOptions, userId,
+                                        true /* validateIncomingUser */);
                             } else {
                                 res = owner.getActivityStartController().startActivityInPackage(uid,
                                         callingPid, callingUid, key.packageName, finalIntent,
diff --git a/services/core/java/com/android/server/am/RecentsAnimation.java b/services/core/java/com/android/server/am/RecentsAnimation.java
index db4e09f..6dcf041 100644
--- a/services/core/java/com/android/server/am/RecentsAnimation.java
+++ b/services/core/java/com/android/server/am/RecentsAnimation.java
@@ -28,7 +28,9 @@
 import android.content.ComponentName;
 import android.content.Intent;
 import android.os.Handler;
+import android.os.RemoteException;
 import android.os.Trace;
+import android.util.Slog;
 import android.view.IRecentsAnimationRunner;
 import com.android.server.wm.RecentsAnimationController.RecentsAnimationCallbacks;
 import com.android.server.wm.WindowManagerService;
@@ -63,6 +65,7 @@
         mHandler = new Handler(mStackSupervisor.mLooper);
         mWindowManager = wm;
         mUserController = userController;
+
         mCancelAnimationRunnable = () -> {
             // The caller has not finished the animation in a predefined amount of time, so
             // force-cancel the animation
@@ -73,13 +76,33 @@
     void startRecentsActivity(Intent intent, IRecentsAnimationRunner recentsAnimationRunner,
             ComponentName recentsComponent, int recentsUid) {
         Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "RecentsAnimation#startRecentsActivity");
+
+        if (!mWindowManager.canStartRecentsAnimation()) {
+            notifyAnimationCancelBeforeStart(recentsAnimationRunner);
+            return;
+        }
+
+        // If the existing home activity is already on top, then cancel
+        ActivityRecord homeActivity = mStackSupervisor.getHomeActivity();
+        final boolean hasExistingHomeActivity = homeActivity != null;
+        if (hasExistingHomeActivity) {
+            final ActivityDisplay display = homeActivity.getDisplay();
+            mRestoreHomeBehindStack = display.getStackAboveHome();
+            if (mRestoreHomeBehindStack == null) {
+                notifyAnimationCancelBeforeStart(recentsAnimationRunner);
+                return;
+            }
+        }
+
         mWindowManager.deferSurfaceLayout();
         try {
-            // Cancel the previous recents animation if necessary
-            mWindowManager.cancelRecentsAnimation();
 
-            final boolean hasExistingHomeActivity = mStackSupervisor.getHomeActivity() != null;
-            if (!hasExistingHomeActivity) {
+            final ActivityDisplay display;
+            if (hasExistingHomeActivity) {
+                // Move the home activity into place for the animation if it is not already top most
+                display = homeActivity.getDisplay();
+                display.moveHomeStackBehindBottomMostVisibleStack();
+            } else {
                 // No home activity
                 final ActivityOptions opts = ActivityOptions.makeBasic();
                 opts.setLaunchActivityType(ACTIVITY_TYPE_HOME);
@@ -95,25 +118,20 @@
                         .execute();
                 mWindowManager.prepareAppTransition(TRANSIT_NONE, false);
 
+                homeActivity = mStackSupervisor.getHomeActivity();
+                display = homeActivity.getDisplay();
+
                 // TODO: Maybe wait for app to draw in this particular case?
             }
 
-            final ActivityRecord homeActivity = mStackSupervisor.getHomeActivity();
-            final ActivityDisplay display = homeActivity.getDisplay();
-
-            // Save the initial position of the home activity stack to be restored to after the
-            // animation completes
-            mRestoreHomeBehindStack = hasExistingHomeActivity
-                    ? display.getStackAboveHome()
-                    : null;
-
-            // Move the home activity into place for the animation
-            display.moveHomeStackBehindBottomMostVisibleStack();
-
             // Mark the home activity as launch-behind to bump its visibility for the
             // duration of the gesture that is driven by the recents component
             homeActivity.mLaunchTaskBehind = true;
 
+            // Post a timeout for the animation. This needs to happen before initializing the
+            // recents animation on the WM side since we may decide to cancel the animation there
+            mHandler.postDelayed(mCancelAnimationRunnable, RECENTS_ANIMATION_TIMEOUT);
+
             // Fetch all the surface controls and pass them to the client to get the animation
             // started
             mWindowManager.initializeRecentsAnimation(recentsAnimationRunner, this,
@@ -122,9 +140,6 @@
             // If we updated the launch-behind state, update the visibility of the activities after
             // we fetch the visible tasks to be controlled by the animation
             mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, PRESERVE_WINDOWS);
-
-            // Post a timeout for the animation
-            mHandler.postDelayed(mCancelAnimationRunnable, RECENTS_ANIMATION_TIMEOUT);
         } finally {
             mWindowManager.continueSurfaceLayout();
             Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
@@ -178,4 +193,15 @@
             });
         }
     }
+
+    /**
+     * Called only when the animation should be canceled prior to starting.
+     */
+    private void notifyAnimationCancelBeforeStart(IRecentsAnimationRunner recentsAnimationRunner) {
+        try {
+            recentsAnimationRunner.onAnimationCanceled();
+        } catch (RemoteException e) {
+            Slog.e(TAG, "Failed to cancel recents animation before start", e);
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index d54e264..bfc787e 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -1489,9 +1489,8 @@
                 }
             }
         }
-        if (!allowAll && targetUserId < 0) {
-            throw new IllegalArgumentException(
-                    "Call does not support special user #" + targetUserId);
+        if (!allowAll) {
+            ensureNotSpecialUser(targetUserId);
         }
         // Check shell permission
         if (callingUid == Process.SHELL_UID && targetUserId >= UserHandle.USER_SYSTEM) {
@@ -1508,6 +1507,13 @@
                 ? getCurrentUserId(): userId;
     }
 
+    void ensureNotSpecialUser(int userId) {
+        if (userId >= 0) {
+            return;
+        }
+        throw new IllegalArgumentException("Call does not support special user #" + userId);
+    }
+
     void registerUserSwitchObserver(IUserSwitchObserver observer, String name) {
         Preconditions.checkNotNull(name, "Observer name cannot be null");
         if (mInjector.checkCallingPermission(INTERACT_ACROSS_USERS_FULL)
diff --git a/services/core/java/com/android/server/broadcastradio/hal1/Tuner.java b/services/core/java/com/android/server/broadcastradio/hal1/Tuner.java
index e77cb7a..2a9d3860 100644
--- a/services/core/java/com/android/server/broadcastradio/hal1/Tuner.java
+++ b/services/core/java/com/android/server/broadcastradio/hal1/Tuner.java
@@ -98,10 +98,6 @@
     private native boolean nativeIsAnalogForced(long nativeContext);
     private native void nativeSetAnalogForced(long nativeContext, boolean isForced);
 
-    private native Map<String, String> nativeSetParameters(long nativeContext,
-            Map<String, String> parameters);
-    private native Map<String, String> nativeGetParameters(long nativeContext, List<String> keys);
-
     @Override
     public void close() {
         synchronized (mLock) {
@@ -291,26 +287,11 @@
 
     @Override
     public Map setParameters(Map parameters) {
-        Map<String, String> results;
-        synchronized (mLock) {
-            checkNotClosedLocked();
-            results = nativeSetParameters(mNativeContext, Objects.requireNonNull(parameters));
-        }
-        if (results == null) return Collections.emptyMap();
-        return results;
+        throw new UnsupportedOperationException("Not supported by HAL 1.x");
     }
 
     @Override
     public Map getParameters(List<String> keys) {
-        if (keys == null) {
-            throw new IllegalArgumentException("The argument must not be a null pointer");
-        }
-        Map<String, String> results;
-        synchronized (mLock) {
-            checkNotClosedLocked();
-            results = nativeGetParameters(mNativeContext, keys);
-        }
-        if (results == null) return Collections.emptyMap();
-        return results;
+        throw new UnsupportedOperationException("Not supported by HAL 1.x");
     }
 }
diff --git a/services/core/java/com/android/server/broadcastradio/hal1/TunerCallback.java b/services/core/java/com/android/server/broadcastradio/hal1/TunerCallback.java
index 04c0e57..7ad73c3 100644
--- a/services/core/java/com/android/server/broadcastradio/hal1/TunerCallback.java
+++ b/services/core/java/com/android/server/broadcastradio/hal1/TunerCallback.java
@@ -169,7 +169,7 @@
 
     @Override
     public void onParametersUpdated(Map parameters) {
-        dispatch(() -> mClientCallback.onParametersUpdated(parameters));
+        Slog.e(TAG, "Not applicable for HAL 1.x");
     }
 
     @Override
diff --git a/services/core/java/com/android/server/content/ContentService.java b/services/core/java/com/android/server/content/ContentService.java
index c3f020a..95a0246 100644
--- a/services/core/java/com/android/server/content/ContentService.java
+++ b/services/core/java/com/android/server/content/ContentService.java
@@ -97,9 +97,7 @@
 
         @Override
         public void onBootPhase(int phase) {
-            if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) {
-                mService.systemReady();
-            }
+            mService.onBootPhase(phase);
         }
 
 
@@ -300,8 +298,15 @@
                 localeFilter, null, null);
     }
 
-    void systemReady() {
-        getSyncManager();
+    void onBootPhase(int phase) {
+        switch (phase) {
+            case SystemService.PHASE_SYSTEM_SERVICES_READY:
+                getSyncManager();
+                break;
+        }
+        if (mSyncManager != null) {
+            mSyncManager.onBootPhase(phase);
+        }
     }
 
     /**
diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
index de17ec7..d87a1bb 100644
--- a/services/core/java/com/android/server/content/SyncManager.java
+++ b/services/core/java/com/android/server/content/SyncManager.java
@@ -89,6 +89,7 @@
 import com.android.internal.notification.SystemNotificationChannels;
 import com.android.internal.util.ArrayUtils;
 import com.android.server.LocalServices;
+import com.android.server.SystemService;
 import com.android.server.job.JobSchedulerInternal;
 import com.google.android.collect.Lists;
 import com.google.android.collect.Maps;
@@ -102,7 +103,6 @@
 import com.android.server.content.SyncStorageEngine.AuthorityInfo;
 import com.android.server.content.SyncStorageEngine.EndPoint;
 import com.android.server.content.SyncStorageEngine.OnSyncRequestListener;
-import com.android.server.job.JobSchedulerInternal.JobStorePersistStats;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -158,18 +158,6 @@
     }
 
     /**
-     * When retrying a sync for the first time use this delay. After that
-     * the retry time will double until it reached MAX_SYNC_RETRY_TIME.
-     * In milliseconds.
-     */
-    private static final long INITIAL_SYNC_RETRY_TIME_IN_MS = 30 * 1000; // 30 seconds
-
-    /**
-     * Default the max sync retry time to this value.
-     */
-    private static final long DEFAULT_MAX_SYNC_RETRY_TIME_IN_SECONDS = 60 * 60; // one hour
-
-    /**
      * How long to wait before retrying a sync that failed due to one already being in progress.
      */
     private static final int DELAY_RETRY_SYNC_IN_PROGRESS_IN_SECONDS = 10;
@@ -449,6 +437,7 @@
     };
 
     private final SyncHandler mSyncHandler;
+    private final SyncManagerConstants mConstants;
 
     private volatile boolean mBootCompleted = false;
     private volatile boolean mJobServiceReady = false;
@@ -616,6 +605,7 @@
         }, mSyncHandler);
 
         mRand = new Random(System.currentTimeMillis());
+        mConstants = new SyncManagerConstants(context);
 
         IntentFilter intentFilter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
         context.registerReceiver(mConnectivityIntentReceiver, intentFilter);
@@ -756,6 +746,14 @@
         mSyncHandler.post(() -> mLogger.log("onStopUser: user=", userHandle));
     }
 
+    public void onBootPhase(int phase) {
+        // Note SyncManager only receives PHASE_SYSTEM_SERVICES_READY and after.
+        switch (phase) {
+            case SystemService.PHASE_SYSTEM_SERVICES_READY:
+                mConstants.start();
+                break;
+        }
+    }
 
     private void whiteListExistingSyncAdaptersIfNeeded() {
         if (!mSyncStorageEngine.shouldGrantSyncAdaptersAccountAccess()) {
@@ -903,7 +901,10 @@
         }
         if (isLoggable) {
             Log.d(TAG, "one-time sync for: " + requestedAccount + " " + extras.toString() + " "
-                    + requestedAuthority);
+                    + requestedAuthority
+                    + " reason=" + reason
+                    + " checkIfAccountReady=" + checkIfAccountReady
+                    + " isAppStandbyExempted=" + isAppStandbyExempted);
         }
 
         AccountAndUser[] accounts = null;
@@ -1368,18 +1369,18 @@
                 return;
             }
             // Subsequent delays are the double of the previous delay.
-            newDelayInMs = previousSettings.second * 2;
+            newDelayInMs =
+                    (long) (previousSettings.second * mConstants.getRetryTimeIncreaseFactor());
         }
         if (newDelayInMs <= 0) {
             // The initial delay is the jitterized INITIAL_SYNC_RETRY_TIME_IN_MS.
-            newDelayInMs = jitterize(INITIAL_SYNC_RETRY_TIME_IN_MS,
-                    (long)(INITIAL_SYNC_RETRY_TIME_IN_MS * 1.1));
+            final long initialRetryMs = mConstants.getInitialSyncRetryTimeInSeconds() * 1000;
+            newDelayInMs = jitterize(initialRetryMs, (long)(initialRetryMs * 1.1));
         }
 
         // Cap the delay.
-        long maxSyncRetryTimeInSeconds = Settings.Global.getLong(mContext.getContentResolver(),
-                Settings.Global.SYNC_MAX_RETRY_DELAY_IN_SECONDS,
-                DEFAULT_MAX_SYNC_RETRY_TIME_IN_SECONDS);
+        final long maxSyncRetryTimeInSeconds = mConstants.getMaxSyncRetryTimeInSeconds();
+
         if (newDelayInMs > maxSyncRetryTimeInSeconds * 1000) {
             newDelayInMs = maxSyncRetryTimeInSeconds * 1000;
         }
@@ -1930,6 +1931,7 @@
     protected void dump(FileDescriptor fd, PrintWriter pw, boolean dumpAll) {
         final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "  ");
         dumpSyncState(ipw);
+        mConstants.dump(pw, "");
         dumpSyncAdapters(ipw);
 
         if (dumpAll) {
@@ -3573,7 +3575,13 @@
                         reschedulePeriodicSyncH(syncOperation);
                     }
                 } else {
-                    Log.d(TAG, "failed sync operation " + syncOperation + ", " + syncResult);
+                    Log.w(TAG, "failed sync operation " + syncOperation + ", " + syncResult);
+
+                    syncOperation.retries++;
+                    if (syncOperation.retries > mConstants.getMaxRetriesWithAppStandbyExemption()) {
+                        syncOperation.isAppStandbyExempted = false;
+                    }
+
                     // the operation failed so increase the backoff time
                     increaseBackoffSetting(syncOperation.target);
                     if (!syncOperation.isPeriodic) {
diff --git a/services/core/java/com/android/server/content/SyncManagerConstants.java b/services/core/java/com/android/server/content/SyncManagerConstants.java
new file mode 100644
index 0000000..2f35687
--- /dev/null
+++ b/services/core/java/com/android/server/content/SyncManagerConstants.java
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.content;
+
+import android.content.Context;
+import android.database.ContentObserver;
+import android.provider.Settings;
+import android.provider.Settings.Global;
+import android.util.KeyValueListParser;
+import android.util.Slog;
+
+import java.io.PrintWriter;
+
+public class SyncManagerConstants extends ContentObserver {
+    private static final String TAG = "SyncManagerConfig";
+
+    private final Object mLock = new Object();
+    private final Context mContext;
+
+    private static final String KEY_INITIAL_SYNC_RETRY_TIME_IN_SECONDS =
+            "initial_sync_retry_time_in_seconds";
+    private static final int DEF_INITIAL_SYNC_RETRY_TIME_IN_SECONDS = 30;
+    private int mInitialSyncRetryTimeInSeconds = DEF_INITIAL_SYNC_RETRY_TIME_IN_SECONDS;
+
+    private static final String KEY_RETRY_TIME_INCREASE_FACTOR =
+            "retry_time_increase_factor";
+    private static final float DEF_RETRY_TIME_INCREASE_FACTOR = 2.0f;
+    private float mRetryTimeIncreaseFactor = DEF_RETRY_TIME_INCREASE_FACTOR;
+
+    private static final String KEY_MAX_SYNC_RETRY_TIME_IN_SECONDS =
+            "max_sync_retry_time_in_seconds";
+    private static final int DEF_MAX_SYNC_RETRY_TIME_IN_SECONDS = 60 * 60;
+    private int mMaxSyncRetryTimeInSeconds = DEF_MAX_SYNC_RETRY_TIME_IN_SECONDS;
+
+    private static final String KEY_MAX_RETRIES_WITH_APP_STANDBY_EXEMPTION =
+            "max_retries_with_app_standby_exemption";
+    private static final int DEF_MAX_RETRIES_WITH_APP_STANDBY_EXEMPTION = 5;
+    private int mMaxRetriesWithAppStandbyExemption = DEF_MAX_RETRIES_WITH_APP_STANDBY_EXEMPTION;
+
+    protected SyncManagerConstants(Context context) {
+        super(null);
+        mContext = context;
+        refresh();
+    }
+
+    public void start() {
+        mContext.getContentResolver().registerContentObserver(Settings.Global.getUriFor(
+                Settings.Global.SYNC_MANAGER_CONSTANTS), false, this);
+        refresh();
+    }
+
+    @Override
+    public void onChange(boolean selfChange) {
+        refresh();
+    }
+
+    private void refresh() {
+        synchronized (mLock) {
+
+            String newValue = Settings.Global.getString(mContext.getContentResolver(),
+                    Global.SYNC_MANAGER_CONSTANTS);
+            final KeyValueListParser parser = new KeyValueListParser(',');
+            try {
+                parser.setString(newValue);
+            } catch (IllegalArgumentException e) {
+                Slog.wtf(TAG, "Bad constants: " + newValue);
+            }
+
+            mInitialSyncRetryTimeInSeconds = parser.getInt(
+                    KEY_INITIAL_SYNC_RETRY_TIME_IN_SECONDS,
+                    DEF_INITIAL_SYNC_RETRY_TIME_IN_SECONDS);
+
+            mMaxSyncRetryTimeInSeconds = parser.getInt(
+                    KEY_MAX_SYNC_RETRY_TIME_IN_SECONDS,
+                    DEF_MAX_SYNC_RETRY_TIME_IN_SECONDS);
+
+            mRetryTimeIncreaseFactor = parser.getFloat(
+                    KEY_RETRY_TIME_INCREASE_FACTOR,
+                    DEF_RETRY_TIME_INCREASE_FACTOR);
+
+            mMaxRetriesWithAppStandbyExemption = parser.getInt(
+                    KEY_MAX_RETRIES_WITH_APP_STANDBY_EXEMPTION,
+                    DEF_MAX_RETRIES_WITH_APP_STANDBY_EXEMPTION);
+        }
+    }
+
+    public int getInitialSyncRetryTimeInSeconds() {
+        synchronized (mLock) {
+            return mInitialSyncRetryTimeInSeconds;
+        }
+    }
+
+    public float getRetryTimeIncreaseFactor() {
+        synchronized (mLock) {
+            return mRetryTimeIncreaseFactor;
+        }
+    }
+
+    public int getMaxSyncRetryTimeInSeconds() {
+        synchronized (mLock) {
+            return mMaxSyncRetryTimeInSeconds;
+        }
+    }
+
+    public int getMaxRetriesWithAppStandbyExemption() {
+        synchronized (mLock) {
+            return mMaxRetriesWithAppStandbyExemption;
+        }
+    }
+
+    public void dump(PrintWriter pw, String prefix) {
+        synchronized (mLock) {
+            pw.print(prefix);
+            pw.println("SyncManager Config:");
+
+            pw.print(prefix);
+            pw.print("  mInitialSyncRetryTimeInSeconds=");
+            pw.println(mInitialSyncRetryTimeInSeconds);
+
+            pw.print(prefix);
+            pw.print("  mRetryTimeIncreaseFactor=");
+            pw.println(mRetryTimeIncreaseFactor);
+
+            pw.print(prefix);
+            pw.print("  mMaxSyncRetryTimeInSeconds=");
+            pw.println(mMaxSyncRetryTimeInSeconds);
+
+            pw.print(prefix);
+            pw.print("  mMaxRetriesWithAppStandbyExemption=");
+            pw.println(mMaxRetriesWithAppStandbyExemption);
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/content/SyncOperation.java b/services/core/java/com/android/server/content/SyncOperation.java
index f6b4819..96bdaea 100644
--- a/services/core/java/com/android/server/content/SyncOperation.java
+++ b/services/core/java/com/android/server/content/SyncOperation.java
@@ -408,6 +408,10 @@
                 extrasToStringBuilder(extras, sb);
             }
         }
+        if (retries > 0) {
+            sb.append(" Retries=");
+            sb.append(retries);
+        }
         return sb.toString();
     }
 
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 23de592..fa39ce4 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -500,6 +500,7 @@
     }
 
     public void onSwitchUser(@UserIdInt int newUserId) {
+        handleSettingsChange();
         mBrightnessTracker.onSwitchUser(newUserId);
     }
 
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index 47a4fb2..be48f69 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -2337,9 +2337,9 @@
                 if (callingUid != Process.SYSTEM_UID) {
                     throw new SecurityException("Job has invalid flags");
                 }
-                if (job.hasLateConstraint() || job.hasEarlyConstraint()) {
-                    Slog.wtf(TAG, "Jobs with time-constraints mustn't have"
-                            +" FLAG_EXEMPT_FROM_APP_STANDBY. Job=" + job);
+                if (job.isPeriodic()) {
+                    Slog.wtf(TAG, "Periodic jobs mustn't have"
+                            + " FLAG_EXEMPT_FROM_APP_STANDBY. Job=" + job);
                 }
             }
         }
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index 55c0f5a..3e43d8e 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -206,7 +206,7 @@
     private static final int UPDATE_NETWORK_STATE = 4;
     private static final int INJECT_NTP_TIME = 5;
     private static final int DOWNLOAD_XTRA_DATA = 6;
-    private static final int UPDATE_LOCATION = 7;
+    private static final int UPDATE_LOCATION = 7;  // Handle external location from network listener
     private static final int ADD_LISTENER = 8;
     private static final int REMOVE_LISTENER = 9;
     private static final int INJECT_NTP_TIME_FINISHED = 10;
@@ -259,6 +259,42 @@
         }
     }
 
+    // Simple class to hold stats reported in the Extras Bundle
+    private static class LocationExtras {
+        private int mSvCount;
+        private int mMeanCn0;
+        private int mMaxCn0;
+        private final Bundle mBundle;
+
+        public LocationExtras() {
+            mBundle = new Bundle();
+        }
+
+        public void set(int svCount, int meanCn0, int maxCn0) {
+            mSvCount = svCount;
+            mMeanCn0 = meanCn0;
+            mMaxCn0 = maxCn0;
+            setBundle(mBundle);
+        }
+
+        public void reset() {
+            set(0,0,0);
+        }
+
+        // Also used by outside methods to add to other bundles
+        public void setBundle(Bundle extras) {
+            if (extras != null) {
+                extras.putInt("satellites", mSvCount);
+                extras.putInt("meanCn0", mMeanCn0);
+                extras.putInt("maxCn0", mMaxCn0);
+            }
+        }
+
+        public Bundle getBundle() {
+            return mBundle;
+        }
+    }
+
     private Object mLock = new Object();
 
     // current status
@@ -369,7 +405,7 @@
     private final NtpTrustedTime mNtpTime;
     private final ILocationManager mILocationManager;
     private Location mLocation = new Location(LocationManager.GPS_PROVIDER);
-    private Bundle mLocationExtras = new Bundle();
+    private final LocationExtras mLocationExtras = new LocationExtras();
     private final GnssStatusListenerHelper mListenerHelper;
     private final GnssMeasurementsProvider mGnssMeasurementsProvider;
     private final GnssNavigationMessageProvider mGnssNavigationMessageProvider;
@@ -713,7 +749,7 @@
         mNtpTime = NtpTrustedTime.getInstance(context);
         mILocationManager = ilocationManager;
 
-        mLocation.setExtras(mLocationExtras);
+        mLocation.setExtras(mLocationExtras.getBundle());
 
         // Create a wake lock
         mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
@@ -1245,29 +1281,17 @@
 
     @Override
     public int getStatus(Bundle extras) {
-        setLocationExtras(extras);
+        mLocationExtras.setBundle(extras);
         return mStatus;
     }
 
-    private void updateStatus(int status, int svCount, int meanCn0, int maxCn0) {
-        if (status != mStatus || svCount != mSvCount || meanCn0 != mMeanCn0 || maxCn0 != mMaxCn0) {
+    private void updateStatus(int status) {
+        if (status != mStatus) {
             mStatus = status;
-            mSvCount = svCount;
-            mMeanCn0 = meanCn0;
-            mMaxCn0 = maxCn0;
-            setLocationExtras(mLocationExtras);
             mStatusUpdateTime = SystemClock.elapsedRealtime();
         }
     }
 
-    private void setLocationExtras(Bundle extras) {
-        if (extras != null) {
-            extras.putInt("satellites", mSvCount);
-            extras.putInt("meanCn0", mMeanCn0);
-            extras.putInt("maxCn0", mMaxCn0);
-        }
-    }
-
     @Override
     public long getStatusUpdateTime() {
         return mStatusUpdateTime;
@@ -1563,7 +1587,8 @@
             }
 
             // reset SV count to zero
-            updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE, 0, 0, 0);
+            updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE);
+            mLocationExtras.reset();
             mFixRequestTime = SystemClock.elapsedRealtime();
             if (!hasCapability(GPS_CAPABILITY_SCHEDULING)) {
                 // set timer to give up if we do not receive a fix within NO_FIX_TIMEOUT
@@ -1586,7 +1611,8 @@
             mLastFixTime = 0;
 
             // reset SV count to zero
-            updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE, 0, 0, 0);
+            updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE);
+            mLocationExtras.reset();
         }
     }
 
@@ -1626,7 +1652,7 @@
             // It would be nice to push the elapsed real-time timestamp
             // further down the stack, but this is still useful
             mLocation.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos());
-            mLocation.setExtras(mLocationExtras);
+            mLocation.setExtras(mLocationExtras.getBundle());
 
             try {
                 mILocationManager.reportLocation(mLocation, false);
@@ -1662,8 +1688,9 @@
         }
 
         if (mStarted && mStatus != LocationProvider.AVAILABLE) {
-            // we want to time out if we do not receive a fix
-            // within the time out and we are requesting infrequent fixes
+            // For devices that use framework scheduling, a timer may be set to ensure we don't
+            // spend too much power searching for a location, when the requested update rate is slow.
+            // As we just recievied a location, we'll cancel that timer.
             if (!hasCapability(GPS_CAPABILITY_SCHEDULING) && mFixInterval < NO_FIX_TIMEOUT) {
                 mAlarmManager.cancel(mTimeoutIntent);
             }
@@ -1672,7 +1699,7 @@
             Intent intent = new Intent(LocationManager.GPS_FIX_CHANGE_ACTION);
             intent.putExtra(LocationManager.EXTRA_GPS_ENABLED, true);
             mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
-            updateStatus(LocationProvider.AVAILABLE, mSvCount, mMeanCn0, mMaxCn0);
+            updateStatus(LocationProvider.AVAILABLE);
         }
 
         if (!hasCapability(GPS_CAPABILITY_SCHEDULING) && mStarted &&
@@ -1771,7 +1798,7 @@
             meanCn0 /= usedInFixCount;
         }
         // return number of sats used in fix instead of total reported
-        updateStatus(mStatus, usedInFixCount, meanCn0, maxCn0);
+        mLocationExtras.set(usedInFixCount, meanCn0, maxCn0);
 
         if (mNavigating && mStatus == LocationProvider.AVAILABLE && mLastFixTime > 0 &&
                 SystemClock.elapsedRealtime() - mLastFixTime > RECENT_FIX_TIMEOUT) {
@@ -1779,7 +1806,7 @@
             Intent intent = new Intent(LocationManager.GPS_FIX_CHANGE_ACTION);
             intent.putExtra(LocationManager.EXTRA_GPS_ENABLED, false);
             mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
-            updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE, mSvCount, mMeanCn0, mMaxCn0);
+            updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE);
         }
     }
 
@@ -2726,9 +2753,6 @@
     private float mSvElevations[] = new float[MAX_SVS];
     private float mSvAzimuths[] = new float[MAX_SVS];
     private float mSvCarrierFreqs[] = new float[MAX_SVS];
-    private int mSvCount;
-    private int mMeanCn0;
-    private int mMaxCn0;
     // preallocated to avoid memory allocation in reportNmea()
     private byte[] mNmeaBuffer = new byte[120];
 
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java
index 9f82268..152c910 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java
@@ -655,7 +655,7 @@
                 // Ignore the exception to continue to recover the other application keys.
             }
         }
-        if (keyMaterialByAlias.isEmpty()) {
+        if (!applicationKeys.isEmpty() && keyMaterialByAlias.isEmpty()) {
             Log.e(TAG, "Failed to recover any of the application keys.");
             throw new ServiceSpecificException(ERROR_DECRYPTION_FAILED,
                     "Failed to recover any of the application keys.");
diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java
index 1ad8c74..8d2f0dd 100644
--- a/services/core/java/com/android/server/notification/NotificationRecord.java
+++ b/services/core/java/com/android/server/notification/NotificationRecord.java
@@ -15,6 +15,7 @@
  */
 package com.android.server.notification;
 
+import static android.app.NotificationChannel.USER_LOCKED_IMPORTANCE;
 import static android.app.NotificationManager.IMPORTANCE_MIN;
 import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
 import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
@@ -22,6 +23,8 @@
 import static android.app.NotificationManager.IMPORTANCE_LOW;
 import static android.service.notification.NotificationListenerService.Ranking
         .USER_SENTIMENT_NEUTRAL;
+import static android.service.notification.NotificationListenerService.Ranking
+        .USER_SENTIMENT_POSITIVE;
 
 import android.app.Notification;
 import android.app.NotificationChannel;
@@ -163,6 +166,7 @@
         mLight = calculateLights();
         mAdjustments = new ArrayList<>();
         mStats = new NotificationStats();
+        calculateUserSentiment();
     }
 
     private boolean isPreChannelsNotification() {
@@ -320,7 +324,7 @@
         if (mPreChannelsNotification
                 && (importance == IMPORTANCE_UNSPECIFIED
                 || (getChannel().getUserLockedFields()
-                & NotificationChannel.USER_LOCKED_IMPORTANCE) == 0)) {
+                & USER_LOCKED_IMPORTANCE) == 0)) {
             if (!stats.isNoisy && requestedImportance > IMPORTANCE_LOW) {
                 requestedImportance = IMPORTANCE_LOW;
             }
@@ -585,8 +589,12 @@
                     setOverrideGroupKey(groupOverrideKey);
                 }
                 if (signals.containsKey(Adjustment.KEY_USER_SENTIMENT)) {
-                    setUserSentiment(adjustment.getSignals().getInt(
-                            Adjustment.KEY_USER_SENTIMENT, USER_SENTIMENT_NEUTRAL));
+                    // Only allow user sentiment update from assistant if user hasn't already
+                    // expressed a preference for this channel
+                    if ((getChannel().getUserLockedFields() & USER_LOCKED_IMPORTANCE) == 0) {
+                        setUserSentiment(adjustment.getSignals().getInt(
+                                Adjustment.KEY_USER_SENTIMENT, USER_SENTIMENT_NEUTRAL));
+                    }
                 }
             }
         }
@@ -845,10 +853,6 @@
         }
     }
 
-    public boolean isImportanceFromUser() {
-        return mImportance == mUserImportance;
-    }
-
     public NotificationChannel getChannel() {
         return mChannel;
     }
@@ -857,6 +861,7 @@
         if (channel != null) {
             mChannel = channel;
             calculateImportance();
+            calculateUserSentiment();
         }
     }
 
@@ -900,6 +905,12 @@
         mSnoozeCriteria = snoozeCriteria;
     }
 
+    private void calculateUserSentiment() {
+        if ((getChannel().getUserLockedFields() & USER_LOCKED_IMPORTANCE) != 0) {
+            mUserSentiment = USER_SENTIMENT_POSITIVE;
+        }
+    }
+
     private void setUserSentiment(int userSentiment) {
         mUserSentiment = userSentiment;
     }
diff --git a/services/core/java/com/android/server/notification/RankingHelper.java b/services/core/java/com/android/server/notification/RankingHelper.java
index b0e3820..dc936d2 100644
--- a/services/core/java/com/android/server/notification/RankingHelper.java
+++ b/services/core/java/com/android/server/notification/RankingHelper.java
@@ -640,9 +640,11 @@
         if (updatedChannel.getLockscreenVisibility() == Notification.VISIBILITY_PUBLIC) {
             updatedChannel.setLockscreenVisibility(Ranking.VISIBILITY_NO_OVERRIDE);
         }
-        updatedChannel.unlockFields(updatedChannel.getUserLockedFields());
-        updatedChannel.lockFields(channel.getUserLockedFields());
+        if (!fromUser) {
+            updatedChannel.unlockFields(updatedChannel.getUserLockedFields());
+        }
         if (fromUser) {
+            updatedChannel.lockFields(channel.getUserLockedFields());
             lockFieldsForUpdate(channel, updatedChannel);
         }
         r.channels.put(updatedChannel.getId(), updatedChannel);
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 61effb8..7ca6bb95c 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -2720,11 +2720,12 @@
                          * application can be scanned.
                          */
                         if (mSettings.isDisabledSystemPackageLPr(ps.name)) {
-                            logCriticalInfo(Log.WARN, "Expecting better updated system app for "
-                                    + ps.name + "; removing system app.  Last known codePath="
-                                    + ps.codePathString + ", installStatus=" + ps.installStatus
-                                    + ", versionCode=" + ps.versionCode + "; scanned versionCode="
-                                    + scannedPkg.getLongVersionCode());
+                            logCriticalInfo(Log.WARN,
+                                    "Expecting better updated system app for " + ps.name
+                                    + "; removing system app.  Last known"
+                                    + " codePath=" + ps.codePathString
+                                    + ", versionCode=" + ps.versionCode
+                                    + "; scanned versionCode=" + scannedPkg.getLongVersionCode());
                             removePackageLI(scannedPkg, true);
                             mExpectingBetter.put(ps.name, ps.codePath);
                         }
@@ -2753,18 +2754,6 @@
                 }
             }
 
-            //look for any incomplete package installations
-            ArrayList<PackageSetting> deletePkgsList = mSettings.getListOfIncompleteInstallPackagesLPr();
-            for (int i = 0; i < deletePkgsList.size(); i++) {
-                // Actual deletion of code and data will be handled by later
-                // reconciliation step
-                final String packageName = deletePkgsList.get(i).name;
-                logCriticalInfo(Log.WARN, "Cleaning up incompletely installed app: " + packageName);
-                synchronized (mPackages) {
-                    mSettings.removePackageLPw(packageName);
-                }
-            }
-
             //delete tmp files
             deleteTempPackageFiles();
 
@@ -16574,17 +16563,7 @@
             PackageInstalledInfo res, UserHandle user, int installReason) {
         Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "updateSettings");
 
-        String pkgName = pkg.packageName;
-        synchronized (mPackages) {
-            //write settings. the installStatus will be incomplete at this stage.
-            //note that the new package setting would have already been
-            //added to mPackages. It hasn't been persisted yet.
-            mSettings.setInstallStatus(pkgName, PackageSettingBase.PKG_INSTALL_INCOMPLETE);
-            // TODO: Remove this write? It's also written at the end of this method
-            Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "writeSettings");
-            mSettings.writeLPr();
-            Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
-        }
+        final String pkgName = pkg.packageName;
 
         if (DEBUG_INSTALL) Slog.d(TAG, "New package installed in " + pkg.codePath);
         synchronized (mPackages) {
@@ -16665,7 +16644,6 @@
             res.name = pkgName;
             res.uid = pkg.applicationInfo.uid;
             res.pkg = pkg;
-            mSettings.setInstallStatus(pkgName, PackageSettingBase.PKG_INSTALL_COMPLETE);
             mSettings.setInstallerPackageName(pkgName, installerPackageName);
             res.setReturnCode(PackageManager.INSTALL_SUCCEEDED);
             //to update install status
@@ -18751,7 +18729,7 @@
         return true;
     }
 
-    private final class ClearStorageConnection implements ServiceConnection {
+    private static final class ClearStorageConnection implements ServiceConnection {
         IMediaContainerService mContainerService;
 
         @Override
@@ -19118,8 +19096,21 @@
     public void deleteApplicationCacheFilesAsUser(final String packageName, final int userId,
             final IPackageDataObserver observer) {
         final int callingUid = Binder.getCallingUid();
-        mContext.enforceCallingOrSelfPermission(
-                android.Manifest.permission.DELETE_CACHE_FILES, null);
+        if (mContext.checkCallingOrSelfPermission(
+                android.Manifest.permission.INTERNAL_DELETE_CACHE_FILES)
+                != PackageManager.PERMISSION_GRANTED) {
+            // If the caller has the old delete cache permission, silently ignore.  Else throw.
+            if (mContext.checkCallingOrSelfPermission(
+                    android.Manifest.permission.DELETE_CACHE_FILES)
+                    == PackageManager.PERMISSION_GRANTED) {
+                Slog.w(TAG, "Calling uid " + callingUid + " does not have " +
+                        android.Manifest.permission.INTERNAL_DELETE_CACHE_FILES +
+                        ", silently ignoring");
+                return;
+            }
+            mContext.enforceCallingOrSelfPermission(
+                    android.Manifest.permission.INTERNAL_DELETE_CACHE_FILES, null);
+        }
         mPermissionManager.enforceCrossUserPermission(callingUid, userId,
                 /* requireFullPermission= */ true, /* checkShell= */ false,
                 "delete application cache files");
@@ -21449,35 +21440,37 @@
                 // the given package is involved with.
                 if (dumpState.onTitlePrinted()) pw.println();
 
-                final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "  ", 120);
-                ipw.println();
-                ipw.println("Frozen packages:");
-                ipw.increaseIndent();
-                if (mFrozenPackages.size() == 0) {
-                    ipw.println("(none)");
-                } else {
-                    for (int i = 0; i < mFrozenPackages.size(); i++) {
-                        ipw.println(mFrozenPackages.valueAt(i));
+                try (final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "  ", 120)) {
+                    ipw.println();
+                    ipw.println("Frozen packages:");
+                    ipw.increaseIndent();
+                    if (mFrozenPackages.size() == 0) {
+                        ipw.println("(none)");
+                    } else {
+                        for (int i = 0; i < mFrozenPackages.size(); i++) {
+                            ipw.println(mFrozenPackages.valueAt(i));
+                        }
                     }
+                    ipw.decreaseIndent();
                 }
-                ipw.decreaseIndent();
             }
 
             if (!checkin && dumpState.isDumping(DumpState.DUMP_VOLUMES) && packageName == null) {
                 if (dumpState.onTitlePrinted()) pw.println();
 
-                final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "  ", 120);
-                ipw.println();
-                ipw.println("Loaded volumes:");
-                ipw.increaseIndent();
-                if (mLoadedVolumes.size() == 0) {
-                    ipw.println("(none)");
-                } else {
-                    for (int i = 0; i < mLoadedVolumes.size(); i++) {
-                        ipw.println(mLoadedVolumes.valueAt(i));
+                try (final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "  ", 120)) {
+                    ipw.println();
+                    ipw.println("Loaded volumes:");
+                    ipw.increaseIndent();
+                    if (mLoadedVolumes.size() == 0) {
+                        ipw.println("(none)");
+                    } else {
+                        for (int i = 0; i < mLoadedVolumes.size(); i++) {
+                            ipw.println(mLoadedVolumes.valueAt(i));
+                        }
                     }
+                    ipw.decreaseIndent();
                 }
-                ipw.decreaseIndent();
             }
 
             if (!checkin && dumpState.isDumping(DumpState.DUMP_SERVICE_PERMISSIONS)
@@ -21606,61 +21599,63 @@
     }
 
     private void dumpDexoptStateLPr(PrintWriter pw, String packageName) {
-        final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "  ");
-        ipw.println();
-        ipw.println("Dexopt state:");
-        ipw.increaseIndent();
-        Collection<PackageParser.Package> packages = null;
-        if (packageName != null) {
-            PackageParser.Package targetPackage = mPackages.get(packageName);
-            if (targetPackage != null) {
-                packages = Collections.singletonList(targetPackage);
-            } else {
-                ipw.println("Unable to find package: " + packageName);
-                return;
-            }
-        } else {
-            packages = mPackages.values();
-        }
-
-        for (PackageParser.Package pkg : packages) {
-            ipw.println("[" + pkg.packageName + "]");
+        try (final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "  ")) {
+            ipw.println();
+            ipw.println("Dexopt state:");
             ipw.increaseIndent();
-            mPackageDexOptimizer.dumpDexoptState(ipw, pkg,
-                    mDexManager.getPackageUseInfoOrDefault(pkg.packageName));
-            ipw.decreaseIndent();
+            Collection<PackageParser.Package> packages = null;
+            if (packageName != null) {
+                PackageParser.Package targetPackage = mPackages.get(packageName);
+                if (targetPackage != null) {
+                    packages = Collections.singletonList(targetPackage);
+                } else {
+                    ipw.println("Unable to find package: " + packageName);
+                    return;
+                }
+            } else {
+                packages = mPackages.values();
+            }
+
+            for (PackageParser.Package pkg : packages) {
+                ipw.println("[" + pkg.packageName + "]");
+                ipw.increaseIndent();
+                mPackageDexOptimizer.dumpDexoptState(ipw, pkg,
+                        mDexManager.getPackageUseInfoOrDefault(pkg.packageName));
+                ipw.decreaseIndent();
+            }
         }
     }
 
     private void dumpCompilerStatsLPr(PrintWriter pw, String packageName) {
-        final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "  ");
-        ipw.println();
-        ipw.println("Compiler stats:");
-        ipw.increaseIndent();
-        Collection<PackageParser.Package> packages = null;
-        if (packageName != null) {
-            PackageParser.Package targetPackage = mPackages.get(packageName);
-            if (targetPackage != null) {
-                packages = Collections.singletonList(targetPackage);
-            } else {
-                ipw.println("Unable to find package: " + packageName);
-                return;
-            }
-        } else {
-            packages = mPackages.values();
-        }
-
-        for (PackageParser.Package pkg : packages) {
-            ipw.println("[" + pkg.packageName + "]");
+        try (final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "  ")) {
+            ipw.println();
+            ipw.println("Compiler stats:");
             ipw.increaseIndent();
-
-            CompilerStats.PackageStats stats = getCompilerPackageStats(pkg.packageName);
-            if (stats == null) {
-                ipw.println("(No recorded stats)");
+            Collection<PackageParser.Package> packages = null;
+            if (packageName != null) {
+                PackageParser.Package targetPackage = mPackages.get(packageName);
+                if (targetPackage != null) {
+                    packages = Collections.singletonList(targetPackage);
+                } else {
+                    ipw.println("Unable to find package: " + packageName);
+                    return;
+                }
             } else {
-                stats.dump(ipw);
+                packages = mPackages.values();
             }
-            ipw.decreaseIndent();
+
+            for (PackageParser.Package pkg : packages) {
+                ipw.println("[" + pkg.packageName + "]");
+                ipw.increaseIndent();
+
+                CompilerStats.PackageStats stats = getCompilerPackageStats(pkg.packageName);
+                if (stats == null) {
+                    ipw.println("(No recorded stats)");
+                } else {
+                    stats.dump(ipw);
+                }
+                ipw.decreaseIndent();
+            }
         }
     }
 
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index 758c9d5..d2ef67b 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -34,6 +34,7 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.FeatureInfo;
 import android.content.pm.IPackageDataObserver;
+import android.content.pm.IPackageInstaller;
 import android.content.pm.IPackageManager;
 import android.content.pm.InstrumentationInfo;
 import android.content.pm.PackageInfo;
@@ -89,12 +90,7 @@
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.net.URISyntaxException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.List;
-import java.util.Map;
-import java.util.WeakHashMap;
+import java.util.*;
 import java.util.concurrent.SynchronousQueue;
 import java.util.concurrent.TimeUnit;
 
@@ -235,6 +231,8 @@
                     return runSetHarmfulAppWarning();
                 case "get-harmful-app-warning":
                     return runGetHarmfulAppWarning();
+                case "uninstall-system-updates":
+                    return uninstallSystemUpdates();
                 default: {
                     String nextArg = getNextArg();
                     if (nextArg == null) {
@@ -257,6 +255,47 @@
         return -1;
     }
 
+    private int uninstallSystemUpdates() {
+        final PrintWriter pw = getOutPrintWriter();
+        List<String> failedUninstalls = new LinkedList<>();
+        try {
+            final ParceledListSlice<ApplicationInfo> packages =
+                    mInterface.getInstalledApplications(
+                            PackageManager.MATCH_SYSTEM_ONLY, UserHandle.USER_SYSTEM);
+            final IPackageInstaller installer = mInterface.getPackageInstaller();
+            List<ApplicationInfo> list = packages.getList();
+            for (ApplicationInfo info : list) {
+                if (info.isUpdatedSystemApp()) {
+                    pw.println("Uninstalling updates to " + info.packageName + "...");
+                    final LocalIntentReceiver receiver = new LocalIntentReceiver();
+                    installer.uninstall(new VersionedPackage(info.packageName,
+                                    info.versionCode), null /*callerPackageName*/, 0 /* flags */,
+                            receiver.getIntentSender(), 0);
+
+                    final Intent result = receiver.getResult();
+                    final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,
+                            PackageInstaller.STATUS_FAILURE);
+                    if (status != PackageInstaller.STATUS_SUCCESS) {
+                        failedUninstalls.add(info.packageName);
+                    }
+                }
+            }
+        } catch (RemoteException e) {
+            pw.println("Failure ["
+                    + e.getClass().getName() + " - "
+                    + e.getMessage() + "]");
+            return 0;
+        }
+        if (!failedUninstalls.isEmpty()) {
+            pw.println("Failure [Couldn't uninstall packages: "
+                    + TextUtils.join(", ", failedUninstalls)
+                    + "]");
+            return 0;
+        }
+        pw.println("Success");
+        return 1;
+    }
+
     private void setParamsSize(InstallParams params, String inPath) {
         if (params.sessionParams.sizeBytes == -1 && !STDIN_PATH.equals(inPath)) {
             final ParcelFileDescriptor fd = openFileForSystem(inPath, "r");
@@ -2705,6 +2744,10 @@
         pw.println("  get-harmful-app-warning [--user <USER_ID>] <PACKAGE>");
         pw.println("    Return the harmful app warning message for the given app, if present");
         pw.println();
+        pw.println("  uninstall-system-updates");
+        pw.println("    Remove updates to all system applications and fall back to their /system " +
+                "version.");
+        pw.println();
         Intent.printIntentArgsHelp(pw , "");
     }
 
diff --git a/services/core/java/com/android/server/pm/PackageSettingBase.java b/services/core/java/com/android/server/pm/PackageSettingBase.java
index f14a684..a0ed126 100644
--- a/services/core/java/com/android/server/pm/PackageSettingBase.java
+++ b/services/core/java/com/android/server/pm/PackageSettingBase.java
@@ -46,19 +46,6 @@
 
     private static final int[] EMPTY_INT_ARRAY = new int[0];
 
-    /**
-     * Indicates the state of installation. Used by PackageManager to figure out
-     * incomplete installations. Say a package is being installed (the state is
-     * set to PKG_INSTALL_INCOMPLETE) and remains so till the package
-     * installation is successful or unsuccessful in which case the
-     * PackageManager will no longer maintain state information associated with
-     * the package. If some exception(like device freeze or battery being pulled
-     * out) occurs during installation of a package, the PackageManager needs
-     * this information to clean up the previously failed installation.
-     */
-    static final int PKG_INSTALL_COMPLETE = 1;
-    static final int PKG_INSTALL_INCOMPLETE = 0;
-
     public final String name;
     final String realName;
 
@@ -122,8 +109,6 @@
     // started until explicitly launched by the user.
     private final SparseArray<PackageUserState> userState = new SparseArray<PackageUserState>();
 
-    int installStatus = PKG_INSTALL_COMPLETE;
-
     /**
      * Non-persisted value. During an "upgrade without restart", we need the set
      * of all previous code paths so we can surgically add the new APKs to the
@@ -209,14 +194,6 @@
         return volumeUuid;
     }
 
-    public void setInstallStatus(int newStatus) {
-        installStatus = newStatus;
-    }
-
-    public int getInstallStatus() {
-        return installStatus;
-    }
-
     public void setTimeStamp(long newStamp) {
         timeStamp = newStamp;
     }
@@ -260,7 +237,6 @@
         cpuAbiOverrideString = orig.cpuAbiOverrideString;
         firstInstallTime = orig.firstInstallTime;
         installPermissionsFixed = orig.installPermissionsFixed;
-        installStatus = orig.installStatus;
         installerPackageName = orig.installerPackageName;
         isOrphaned = orig.isOrphaned;
         keySetData = orig.keySetData;
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index b6e1534..b5fe9ea 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -455,15 +455,6 @@
         return mRenamedPackages.put(pkgName, origPkgName);
     }
 
-    void setInstallStatus(String pkgName, final int status) {
-        PackageSetting p = mPackages.get(pkgName);
-        if(p != null) {
-            if(p.getInstallStatus() != status) {
-                p.setInstallStatus(status);
-            }
-        }
-    }
-
     void applyPendingPermissionGrantsLPw(String packageName, int userId) {
         ArrayMap<String, ArraySet<RestoredPermissionGrant>> grantsByPackage =
                 mRestoredUserGrants.get(userId);
@@ -2839,9 +2830,6 @@
         if (pkg.uidError) {
             serializer.attribute(null, "uidError", "true");
         }
-        if (pkg.installStatus == PackageSettingBase.PKG_INSTALL_INCOMPLETE) {
-            serializer.attribute(null, "installStatus", "false");
-        }
         if (pkg.installerPackageName != null) {
             serializer.attribute(null, "installer", pkg.installerPackageName);
         }
@@ -2912,20 +2900,6 @@
         bp.writeLPr(serializer);
     }
 
-    ArrayList<PackageSetting> getListOfIncompleteInstallPackagesLPr() {
-        final ArraySet<String> kList = new ArraySet<String>(mPackages.keySet());
-        final Iterator<String> its = kList.iterator();
-        final ArrayList<PackageSetting> ret = new ArrayList<PackageSetting>();
-        while (its.hasNext()) {
-            final String key = its.next();
-            final PackageSetting ps = mPackages.get(key);
-            if (ps.getInstallStatus() == PackageSettingBase.PKG_INSTALL_INCOMPLETE) {
-                ret.add(ps);
-            }
-        }
-        return ret;
-    }
-
     void addPackageToCleanLPw(PackageCleanItem pkg) {
         if (!mPackagesToBeCleaned.contains(pkg)) {
             mPackagesToBeCleaned.add(pkg);
@@ -3874,15 +3848,6 @@
                 mInstallerPackages.add(installerPackageName);
             }
 
-            final String installStatusStr = parser.getAttributeValue(null, "installStatus");
-            if (installStatusStr != null) {
-                if (installStatusStr.equalsIgnoreCase("false")) {
-                    packageSetting.installStatus = PackageSettingBase.PKG_INSTALL_INCOMPLETE;
-                } else {
-                    packageSetting.installStatus = PackageSettingBase.PKG_INSTALL_COMPLETE;
-                }
-            }
-
             int outerDepth = parser.getDepth();
             int type;
             while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
@@ -4668,7 +4633,7 @@
         pw.print(prefix); pw.print("  signatures="); pw.println(ps.signatures);
         pw.print(prefix); pw.print("  installPermissionsFixed=");
                 pw.print(ps.installPermissionsFixed);
-                pw.print(" installStatus="); pw.println(ps.installStatus);
+                pw.println();
         pw.print(prefix); pw.print("  pkgFlags="); printFlags(pw, ps.pkgFlags, FLAG_DUMP_SPEC);
                 pw.println();
 
diff --git a/services/core/java/com/android/server/power/ShutdownThread.java b/services/core/java/com/android/server/power/ShutdownThread.java
index bd4aa1c..0a6b38f 100644
--- a/services/core/java/com/android/server/power/ShutdownThread.java
+++ b/services/core/java/com/android/server/power/ShutdownThread.java
@@ -451,7 +451,7 @@
         // First send the high-level shut down broadcast.
         mActionDone = false;
         Intent intent = new Intent(Intent.ACTION_SHUTDOWN);
-        intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+        intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND | Intent.FLAG_RECEIVER_REGISTERED_ONLY);
         mContext.sendOrderedBroadcastAsUser(intent,
                 UserHandle.ALL, null, br, mHandler, 0, null, null);
 
diff --git a/services/core/java/com/android/server/stats/StatsCompanionService.java b/services/core/java/com/android/server/stats/StatsCompanionService.java
index ef6067a..4bc9404 100644
--- a/services/core/java/com/android/server/stats/StatsCompanionService.java
+++ b/services/core/java/com/android/server/stats/StatsCompanionService.java
@@ -290,7 +290,8 @@
     public final static class AnomalyAlarmReceiver extends BroadcastReceiver {
         @Override
         public void onReceive(Context context, Intent intent) {
-            Slog.i(TAG, "StatsCompanionService believes an anomaly has occurred.");
+            Slog.i(TAG, "StatsCompanionService believes an anomaly has occurred at time "
+                    + System.currentTimeMillis() + "ms.");
             synchronized (sStatsdLock) {
                 if (sStatsd == null) {
                     Slog.w(TAG, "Could not access statsd to inform it of anomaly alarm firing");
@@ -361,9 +362,8 @@
         final long callingToken = Binder.clearCallingIdentity();
         try {
             // using RTC, not RTC_WAKEUP, so if device is asleep, will only fire when it awakens.
-            // This alarm is inexact, leaving its exactness completely up to the OS optimizations.
             // AlarmManager will automatically cancel any previous mAnomalyAlarmIntent alarm.
-            mAlarmManager.set(AlarmManager.RTC, timestampMs, mAnomalyAlarmIntent);
+            mAlarmManager.setExact(AlarmManager.RTC, timestampMs, mAnomalyAlarmIntent);
         } finally {
             Binder.restoreCallingIdentity(callingToken);
         }
@@ -783,7 +783,9 @@
         enforceCallingPermission();
         if (DEBUG) Slog.d(TAG, "learned that statsdReady");
         sayHiToStatsd(); // tell statsd that we're ready too and link to it
-        mContext.sendBroadcastAsUser(new Intent(StatsManager.ACTION_STATSD_STARTED),
+        mContext.sendBroadcastAsUser(
+                new Intent(StatsManager.ACTION_STATSD_STARTED)
+                        .addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND),
                 UserHandle.SYSTEM,
                 android.Manifest.permission.DUMP);
     }
diff --git a/services/core/java/com/android/server/timezone/PackageTracker.java b/services/core/java/com/android/server/timezone/PackageTracker.java
index 0e8d8bc..8f4cada 100644
--- a/services/core/java/com/android/server/timezone/PackageTracker.java
+++ b/services/core/java/com/android/server/timezone/PackageTracker.java
@@ -59,7 +59,7 @@
     private static final String TAG = "timezone.PackageTracker";
 
     private final PackageManagerHelper mPackageManagerHelper;
-    private final IntentHelper mIntentHelper;
+    private final PackageTrackerIntentHelper mIntentHelper;
     private final ConfigHelper mConfigHelper;
     private final PackageStatusStorage mPackageStatusStorage;
     private final Clock mElapsedRealtimeClock;
@@ -103,13 +103,13 @@
                 helperImpl /* configHelper */,
                 helperImpl /* packageManagerHelper */,
                 new PackageStatusStorage(storageDir),
-                new IntentHelperImpl(context));
+                new PackageTrackerIntentHelperImpl(context));
     }
 
     // A constructor that can be used by tests to supply mocked / faked dependencies.
     PackageTracker(Clock elapsedRealtimeClock, ConfigHelper configHelper,
             PackageManagerHelper packageManagerHelper, PackageStatusStorage packageStatusStorage,
-            IntentHelper intentHelper) {
+            PackageTrackerIntentHelper intentHelper) {
         mElapsedRealtimeClock = elapsedRealtimeClock;
         mConfigHelper = configHelper;
         mPackageManagerHelper = packageManagerHelper;
diff --git a/services/core/java/com/android/server/timezone/IntentHelper.java b/services/core/java/com/android/server/timezone/PackageTrackerIntentHelper.java
similarity index 97%
rename from services/core/java/com/android/server/timezone/IntentHelper.java
rename to services/core/java/com/android/server/timezone/PackageTrackerIntentHelper.java
index 5de5432..3753ece 100644
--- a/services/core/java/com/android/server/timezone/IntentHelper.java
+++ b/services/core/java/com/android/server/timezone/PackageTrackerIntentHelper.java
@@ -21,7 +21,7 @@
  * it is not possible to test various cases with the real one because of the need to simulate
  * receiving and broadcasting intents.
  */
-interface IntentHelper {
+interface PackageTrackerIntentHelper {
 
     void initialize(String updateAppPackageName, String dataAppPackageName,
             PackageTracker packageTracker);
diff --git a/services/core/java/com/android/server/timezone/IntentHelperImpl.java b/services/core/java/com/android/server/timezone/PackageTrackerIntentHelperImpl.java
similarity index 93%
rename from services/core/java/com/android/server/timezone/IntentHelperImpl.java
rename to services/core/java/com/android/server/timezone/PackageTrackerIntentHelperImpl.java
index 6e6259d..4110d88 100644
--- a/services/core/java/com/android/server/timezone/IntentHelperImpl.java
+++ b/services/core/java/com/android/server/timezone/PackageTrackerIntentHelperImpl.java
@@ -28,16 +28,16 @@
 import android.util.Slog;
 
 /**
- * The bona fide implementation of {@link IntentHelper}.
+ * The bona fide implementation of {@link PackageTrackerIntentHelper}.
  */
-final class IntentHelperImpl implements IntentHelper {
+final class PackageTrackerIntentHelperImpl implements PackageTrackerIntentHelper {
 
-    private final static String TAG = "timezone.IntentHelperImpl";
+    private final static String TAG = "timezone.PackageTrackerIntentHelperImpl";
 
     private final Context mContext;
     private String mUpdaterAppPackageName;
 
-    IntentHelperImpl(Context context) {
+    PackageTrackerIntentHelperImpl(Context context) {
         mContext = context;
     }
 
diff --git a/services/core/java/com/android/server/timezone/RulesManagerIntentHelper.java b/services/core/java/com/android/server/timezone/RulesManagerIntentHelper.java
new file mode 100644
index 0000000..bb317cf
--- /dev/null
+++ b/services/core/java/com/android/server/timezone/RulesManagerIntentHelper.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.timezone;
+
+/**
+ * An easy-to-mock interface around intent sending / receiving for use by
+ * {@link RulesManagerService}; it is not possible to test various cases with the real one because
+ * of the need to simulate broadcasting intents.
+ */
+interface RulesManagerIntentHelper {
+
+    /**
+     * Send a broadcast informing listeners that a time zone operation is staged.
+     */
+    void sendTimeZoneOperationStaged();
+
+    /**
+     * Send a broadcast informing listeners that a time zone operation is no longer staged.
+     */
+    void sendTimeZoneOperationUnstaged();
+}
diff --git a/services/core/java/com/android/server/timezone/RulesManagerService.java b/services/core/java/com/android/server/timezone/RulesManagerService.java
index be9b204..872d723 100644
--- a/services/core/java/com/android/server/timezone/RulesManagerService.java
+++ b/services/core/java/com/android/server/timezone/RulesManagerService.java
@@ -99,6 +99,7 @@
     private final PermissionHelper mPermissionHelper;
     private final PackageTracker mPackageTracker;
     private final Executor mExecutor;
+    private final RulesManagerIntentHelper mIntentHelper;
     private final TimeZoneDistroInstaller mInstaller;
 
     private static RulesManagerService create(Context context) {
@@ -106,16 +107,19 @@
         return new RulesManagerService(
                 helper /* permissionHelper */,
                 helper /* executor */,
+                helper /* intentHelper */,
                 PackageTracker.create(context),
                 new TimeZoneDistroInstaller(TAG, SYSTEM_TZ_DATA_FILE, TZ_DATA_DIR));
     }
 
     // A constructor that can be used by tests to supply mocked / faked dependencies.
-    RulesManagerService(PermissionHelper permissionHelper,
-            Executor executor, PackageTracker packageTracker,
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+    RulesManagerService(PermissionHelper permissionHelper, Executor executor,
+            RulesManagerIntentHelper intentHelper, PackageTracker packageTracker,
             TimeZoneDistroInstaller timeZoneDistroInstaller) {
         mPermissionHelper = permissionHelper;
         mExecutor = executor;
+        mIntentHelper = intentHelper;
         mPackageTracker = packageTracker;
         mInstaller = timeZoneDistroInstaller;
     }
@@ -271,6 +275,10 @@
 
                 TimeZoneDistro distro = new TimeZoneDistro(is);
                 int installerResult = mInstaller.stageInstallWithErrorCode(distro);
+
+                // Notify interested parties that something is staged.
+                sendInstallNotificationIntentIfRequired(installerResult);
+
                 int resultCode = mapInstallerResultToApiCode(installerResult);
                 EventLogTags.writeTimezoneInstallComplete(toStringOrNull(mCheckToken), resultCode);
                 sendFinishedStatus(mCallback, resultCode);
@@ -291,6 +299,12 @@
             }
         }
 
+        private void sendInstallNotificationIntentIfRequired(int installerResult) {
+            if (installerResult == TimeZoneDistroInstaller.INSTALL_SUCCESS) {
+                mIntentHelper.sendTimeZoneOperationStaged();
+            }
+        }
+
         private int mapInstallerResultToApiCode(int installerResult) {
             switch (installerResult) {
                 case TimeZoneDistroInstaller.INSTALL_SUCCESS:
@@ -351,6 +365,10 @@
             boolean packageTrackerStatus = false;
             try {
                 int uninstallResult = mInstaller.stageUninstall();
+
+                // Notify interested parties that something is staged.
+                sendUninstallNotificationIntentIfRequired(uninstallResult);
+
                 packageTrackerStatus = (uninstallResult == TimeZoneDistroInstaller.UNINSTALL_SUCCESS
                         || uninstallResult == TimeZoneDistroInstaller.UNINSTALL_NOTHING_INSTALLED);
 
@@ -374,6 +392,20 @@
                 mOperationInProgress.set(false);
             }
         }
+
+        private void sendUninstallNotificationIntentIfRequired(int uninstallResult) {
+            switch (uninstallResult) {
+                case TimeZoneDistroInstaller.UNINSTALL_SUCCESS:
+                    mIntentHelper.sendTimeZoneOperationStaged();
+                    break;
+                case TimeZoneDistroInstaller.UNINSTALL_NOTHING_INSTALLED:
+                    mIntentHelper.sendTimeZoneOperationUnstaged();
+                    break;
+                case TimeZoneDistroInstaller.UNINSTALL_FAIL:
+                default:
+                    // No-op - unknown or nothing to notify about.
+            }
+        }
     }
 
     private void sendFinishedStatus(ICallback callback, int resultCode) {
diff --git a/services/core/java/com/android/server/timezone/RulesManagerServiceHelperImpl.java b/services/core/java/com/android/server/timezone/RulesManagerServiceHelperImpl.java
index e8a401e..8f5c7a7 100644
--- a/services/core/java/com/android/server/timezone/RulesManagerServiceHelperImpl.java
+++ b/services/core/java/com/android/server/timezone/RulesManagerServiceHelperImpl.java
@@ -18,22 +18,20 @@
 
 import com.android.internal.util.DumpUtils;
 
+import android.app.timezone.RulesManager;
 import android.content.Context;
-import android.content.pm.PackageManager;
+import android.content.Intent;
 import android.os.AsyncTask;
-import android.os.Binder;
-import android.os.ParcelFileDescriptor;
+import android.os.UserHandle;
 
-import java.io.FileInputStream;
-import java.io.IOException;
 import java.io.PrintWriter;
 import java.util.concurrent.Executor;
-import libcore.io.Streams;
 
 /**
  * A single class that implements multiple helper interfaces for use by {@link RulesManagerService}.
  */
-final class RulesManagerServiceHelperImpl implements PermissionHelper, Executor {
+final class RulesManagerServiceHelperImpl
+        implements PermissionHelper, Executor, RulesManagerIntentHelper {
 
     private final Context mContext;
 
@@ -55,4 +53,22 @@
     public void execute(Runnable runnable) {
         AsyncTask.execute(runnable);
     }
+
+    @Override
+    public void sendTimeZoneOperationStaged() {
+        sendOperationIntent(true /* staged */);
+    }
+
+    @Override
+    public void sendTimeZoneOperationUnstaged() {
+        sendOperationIntent(false /* staged */);
+    }
+
+    private void sendOperationIntent(boolean staged) {
+        Intent intent = new Intent(RulesManager.ACTION_RULES_UPDATE_OPERATION);
+        intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
+        intent.putExtra(RulesManager.EXTRA_OPERATION_STAGED, staged);
+        mContext.sendBroadcastAsUser(intent, UserHandle.SYSTEM);
+    }
+
 }
diff --git a/services/core/java/com/android/server/updates/CarrierIdInstallReceiver.java b/services/core/java/com/android/server/updates/CarrierIdInstallReceiver.java
index 116fe7f..0450816 100644
--- a/services/core/java/com/android/server/updates/CarrierIdInstallReceiver.java
+++ b/services/core/java/com/android/server/updates/CarrierIdInstallReceiver.java
@@ -33,7 +33,7 @@
     @Override
     protected void postInstall(Context context, Intent intent) {
         ContentResolver resolver = context.getContentResolver();
-        resolver.update(Uri.withAppendedPath(Telephony.CarrierIdentification.CONTENT_URI,
+        resolver.update(Uri.withAppendedPath(Telephony.CarrierIdentification.All.CONTENT_URI,
                 "update_db"), new ContentValues(), null, null);
     }
 }
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index 2bdaa1a..0d36145 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -78,9 +78,12 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.res.Configuration;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
 import android.graphics.Color;
 import android.graphics.GraphicBuffer;
 import android.graphics.Path;
+import android.graphics.Picture;
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.os.Binder;
@@ -96,11 +99,8 @@
 import android.util.SparseArray;
 import android.util.proto.ProtoOutputStream;
 import android.view.AppTransitionAnimationSpec;
-import android.view.DisplayListCanvas;
 import android.view.IAppTransitionAnimationSpecsFuture;
 import android.view.RemoteAnimationAdapter;
-import android.view.RenderNode;
-import android.view.ThreadedRenderer;
 import android.view.WindowManager.TransitionFlags;
 import android.view.WindowManager.TransitionType;
 import android.view.animation.AlphaAnimation;
@@ -973,11 +973,8 @@
         final int width = frame.width();
         final int height = frame.height();
 
-        final RenderNode node = RenderNode.create("CrossProfileAppsThumbnail", null);
-        node.setLeftTopRightBottom(0, 0, width, height);
-        node.setClipToBounds(false);
-
-        final DisplayListCanvas canvas = node.start(width, height);
+        final Picture picture = new Picture();
+        final Canvas canvas = picture.beginRecording(width, height);
         canvas.drawColor(Color.argb(0.6f, 0, 0, 0));
         final int thumbnailSize = mService.mContext.getResources().getDimensionPixelSize(
                 com.android.internal.R.dimen.cross_profile_apps_thumbnail_size);
@@ -988,10 +985,9 @@
                 (width + thumbnailSize) / 2,
                 (height + thumbnailSize) / 2);
         drawable.draw(canvas);
-        node.end(canvas);
+        picture.endRecording();
 
-        return ThreadedRenderer.createHardwareBitmap(node, width, height)
-                .createGraphicBufferHandle();
+        return Bitmap.createBitmap(picture).createGraphicBufferHandle();
     }
 
     Animation createCrossProfileAppsThumbnailAnimationLocked(Rect appRect) {
diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java
index e869f58..6c3beaf 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimationController.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java
@@ -59,6 +59,7 @@
     private final IRecentsAnimationRunner mRunner;
     private final RecentsAnimationCallbacks mCallbacks;
     private final ArrayList<TaskAnimationAdapter> mPendingAnimations = new ArrayList<>();
+    private final int mDisplayId;
 
     // The recents component app token that is shown behind the visibile tasks
     private AppWindowToken mHomeAppToken;
@@ -159,8 +160,6 @@
     };
 
     /**
-     * Initializes a new RecentsAnimationController.
-     *
      * @param remoteAnimationRunner The remote runner which should be notified when the animation is
      *                              ready to start or has been canceled
      * @param callbacks Callbacks to be made when the animation finishes
@@ -171,16 +170,19 @@
         mService = service;
         mRunner = remoteAnimationRunner;
         mCallbacks = callbacks;
+        mDisplayId = displayId;
+    }
 
-        final DisplayContent dc = mService.mRoot.getDisplayContent(displayId);
-        final ArrayList<Task> visibleTasks = dc.getVisibleTasks();
-        if (visibleTasks.isEmpty()) {
-            cancelAnimation();
-            return;
-        }
-
+    /**
+     * Initializes the recents animation controller. This is a separate call from the constructor
+     * because it may call cancelAnimation() which needs to properly clean up the controller
+     * in the window manager.
+     */
+    public void initialize() {
         // Make leashes for each of the visible tasks and add it to the recents animation to be
         // started
+        final DisplayContent dc = mService.mRoot.getDisplayContent(mDisplayId);
+        final ArrayList<Task> visibleTasks = dc.getVisibleTasks();
         final int taskCount = visibleTasks.size();
         for (int i = 0; i < taskCount; i++) {
             final Task task = visibleTasks.get(i);
@@ -193,6 +195,12 @@
             addAnimation(task);
         }
 
+        // Skip the animation if there is nothing to animate
+        if (mPendingAnimations.isEmpty()) {
+            cancelAnimation();
+            return;
+        }
+
         // Adjust the wallpaper visibility for the showing home activity
         final AppWindowToken recentsComponentAppToken =
                 dc.getHomeStack().getTopChild().getTopFullscreenAppToken();
@@ -222,8 +230,10 @@
     }
 
     void startAnimation() {
-        if (DEBUG) Log.d(TAG, "startAnimation(): mPendingStart=" + mPendingStart);
-        if (!mPendingStart) {
+        if (DEBUG) Log.d(TAG, "startAnimation(): mPendingStart=" + mPendingStart
+                + " mCanceled=" + mCanceled);
+        if (!mPendingStart || mCanceled) {
+            // Skip starting if we've already started or canceled the animation
             return;
         }
         try {
diff --git a/services/core/java/com/android/server/wm/SurfaceAnimationRunner.java b/services/core/java/com/android/server/wm/SurfaceAnimationRunner.java
index 1b2f954..98fcb0b 100644
--- a/services/core/java/com/android/server/wm/SurfaceAnimationRunner.java
+++ b/services/core/java/com/android/server/wm/SurfaceAnimationRunner.java
@@ -169,7 +169,12 @@
         anim.addUpdateListener(animation -> {
             synchronized (mCancelLock) {
                 if (!a.mCancelled) {
-                    applyTransformation(a, mFrameTransaction, anim.getCurrentPlayTime());
+                    final long duration = anim.getDuration();
+                    long currentPlayTime = anim.getCurrentPlayTime();
+                    if (currentPlayTime > duration) {
+                        currentPlayTime = duration;
+                    }
+                    applyTransformation(a, mFrameTransaction, currentPlayTime);
                 }
             }
 
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index c2ed2ae..e68fbdb 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -2680,6 +2680,7 @@
             cancelRecentsAnimation();
             mRecentsAnimationController = new RecentsAnimationController(this,
                     recentsAnimationRunner, callbacks, displayId);
+            mRecentsAnimationController.initialize();
         }
     }
 
@@ -2687,6 +2688,19 @@
         return mRecentsAnimationController;
     }
 
+    /**
+     * @return Whether the next recents animation can continue to start. Called from
+     *         {@link RecentsAnimation#startRecentsActivity}.
+     */
+    public boolean canStartRecentsAnimation() {
+        synchronized (mWindowMap) {
+            if (mAppTransition.isTransitionSet()) {
+                return false;
+            }
+            return true;
+        }
+    }
+
     public void cancelRecentsAnimation() {
         synchronized (mWindowMap) {
             if (mRecentsAnimationController != null) {
diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp
index 4045b72..72f95fb 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -110,7 +110,6 @@
         "android.hardware.audio.common@2.0",
         "android.hardware.broadcastradio@1.0",
         "android.hardware.broadcastradio@1.1",
-        "android.hardware.broadcastradio@1.2",
         "android.hardware.contexthub@1.0",
         "android.hardware.gnss@1.0",
         "android.hardware.gnss@1.1",
diff --git a/services/core/jni/BroadcastRadio/BroadcastRadioService.cpp b/services/core/jni/BroadcastRadio/BroadcastRadioService.cpp
index 176ae81..14e3578 100644
--- a/services/core/jni/BroadcastRadio/BroadcastRadioService.cpp
+++ b/services/core/jni/BroadcastRadio/BroadcastRadioService.cpp
@@ -23,7 +23,7 @@
 #include "convert.h"
 
 #include <android/hardware/broadcastradio/1.1/IBroadcastRadio.h>
-#include <android/hardware/broadcastradio/1.2/IBroadcastRadioFactory.h>
+#include <android/hardware/broadcastradio/1.1/IBroadcastRadioFactory.h>
 #include <android/hidl/manager/1.0/IServiceManager.h>
 #include <broadcastradio-utils-1x/Utils.h>
 #include <core_jni_helpers.h>
@@ -45,7 +45,6 @@
 
 namespace V1_0 = hardware::broadcastradio::V1_0;
 namespace V1_1 = hardware::broadcastradio::V1_1;
-namespace V1_2 = hardware::broadcastradio::V1_2;
 namespace utils = hardware::broadcastradio::utils;
 
 using V1_0::BandConfig;
@@ -149,11 +148,7 @@
 
         auto halRev = HalRevision::V1_0;
         auto halMinor = 0;
-        if (V1_2::IBroadcastRadioFactory::castFrom(factory).withDefault(nullptr) != nullptr) {
-            halRev = HalRevision::V1_2;
-            halMinor = 2;
-        } else if (V1_1::IBroadcastRadioFactory::castFrom(factory).withDefault(nullptr)
-                != nullptr) {
+        if (V1_1::IBroadcastRadioFactory::castFrom(factory).withDefault(nullptr) != nullptr) {
             halRev = HalRevision::V1_1;
             halMinor = 1;
         }
diff --git a/services/core/jni/BroadcastRadio/Tuner.cpp b/services/core/jni/BroadcastRadio/Tuner.cpp
index 42c1332..36d2994 100644
--- a/services/core/jni/BroadcastRadio/Tuner.cpp
+++ b/services/core/jni/BroadcastRadio/Tuner.cpp
@@ -22,7 +22,7 @@
 #include "convert.h"
 #include "TunerCallback.h"
 
-#include <android/hardware/broadcastradio/1.2/IBroadcastRadioFactory.h>
+#include <android/hardware/broadcastradio/1.1/IBroadcastRadioFactory.h>
 #include <binder/IPCThreadState.h>
 #include <broadcastradio-utils-1x/Utils.h>
 #include <core_jni_helpers.h>
@@ -44,16 +44,15 @@
 
 namespace V1_0 = hardware::broadcastradio::V1_0;
 namespace V1_1 = hardware::broadcastradio::V1_1;
-namespace V1_2 = hardware::broadcastradio::V1_2;
 namespace utils = hardware::broadcastradio::utils;
 
 using V1_0::Band;
 using V1_0::BandConfig;
 using V1_0::MetaData;
 using V1_0::Result;
+using V1_1::ITunerCallback;
 using V1_1::ProgramListResult;
 using V1_1::VendorKeyValue;
-using V1_2::ITunerCallback;
 using utils::HalRevision;
 
 static mutex gContextMutex;
@@ -94,7 +93,6 @@
     wp<V1_1::IBroadcastRadio> mHalModule11;
     sp<V1_0::ITuner> mHalTuner;
     sp<V1_1::ITuner> mHalTuner11;
-    sp<V1_2::ITuner> mHalTuner12;
     sp<HalDeathRecipient> mHalDeathRecipient;
 
 private:
@@ -181,11 +179,8 @@
 
     ctx.mHalTuner = halTuner;
     ctx.mHalTuner11 = V1_1::ITuner::castFrom(halTuner).withDefault(nullptr);
-    ctx.mHalTuner12 = V1_2::ITuner::castFrom(halTuner).withDefault(nullptr);
     ALOGW_IF(ctx.mHalRev >= HalRevision::V1_1 && ctx.mHalTuner11 == nullptr,
             "Provided tuner does not implement 1.1 HAL");
-    ALOGW_IF(ctx.mHalRev >= HalRevision::V1_2 && ctx.mHalTuner12 == nullptr,
-            "Provided tuner does not implement 1.2 HAL");
 
     ctx.mHalDeathRecipient = new HalDeathRecipient(getNativeCallback(env, jTuner));
     halTuner->linkToDeath(ctx.mHalDeathRecipient, 0);
@@ -209,11 +204,6 @@
     return getNativeContext(nativeContext).mHalTuner11;
 }
 
-static sp<V1_2::ITuner> getHalTuner12(jlong nativeContext) {
-    lock_guard<mutex> lk(gContextMutex);
-    return getNativeContext(nativeContext).mHalTuner12;
-}
-
 sp<ITunerCallback> getNativeCallback(JNIEnv *env, JavaRef<jobject> const &tuner) {
     return TunerCallback::getNativeCallback(env,
             env->GetObjectField(tuner.get(), gjni.Tuner.tunerCallback));
@@ -243,7 +233,6 @@
     ctx.mHalDeathRecipient = nullptr;
 
     ctx.mHalTuner11 = nullptr;
-    ctx.mHalTuner12 = nullptr;
     ctx.mHalTuner = nullptr;
 }
 
@@ -466,48 +455,6 @@
     convert::ThrowIfFailed(env, halResult);
 }
 
-static jobject nativeSetParameters(JNIEnv *env, jobject obj, jlong nativeContext, jobject jParameters) {
-    ALOGV("%s", __func__);
-
-    auto halTuner = getHalTuner12(nativeContext);
-    if (halTuner == nullptr) {
-        ALOGI("Parameters are not supported with HAL < 1.2");
-        return nullptr;
-    }
-
-    JavaRef<jobject> jResults = nullptr;
-    auto parameters = convert::VendorInfoToHal(env, jParameters);
-    auto hidlResult = halTuner->setParameters(parameters,
-            [&](const hidl_vec<VendorKeyValue> results) {
-        jResults = convert::VendorInfoFromHal(env, results);
-    });
-
-    if (convert::ThrowIfFailed(env, hidlResult)) return nullptr;
-
-    return jResults.release();
-}
-
-static jobject nativeGetParameters(JNIEnv *env, jobject obj, jlong nativeContext, jobject jKeys) {
-    ALOGV("%s", __func__);
-
-    auto halTuner = getHalTuner12(nativeContext);
-    if (halTuner == nullptr) {
-        ALOGI("Parameters are not supported with HAL < 1.2");
-        return nullptr;
-    }
-
-    JavaRef<jobject> jResults = nullptr;
-    auto keys = convert::StringListToHal(env, jKeys);
-    auto hidlResult = halTuner->getParameters(keys,
-            [&](const hidl_vec<VendorKeyValue> parameters) {
-        jResults = convert::VendorInfoFromHal(env, parameters);
-    });
-
-    if (convert::ThrowIfFailed(env, hidlResult)) return nullptr;
-
-    return jResults.release();
-}
-
 static const JNINativeMethod gTunerMethods[] = {
     { "nativeInit", "(IZI)J", (void*)nativeInit },
     { "nativeFinalize", "(J)V", (void*)nativeFinalize },
@@ -528,8 +475,6 @@
     { "nativeGetImage", "(JI)[B", (void*)nativeGetImage},
     { "nativeIsAnalogForced", "(J)Z", (void*)nativeIsAnalogForced },
     { "nativeSetAnalogForced", "(JZ)V", (void*)nativeSetAnalogForced },
-    { "nativeSetParameters", "(JLjava/util/Map;)Ljava/util/Map;", (void*)nativeSetParameters },
-    { "nativeGetParameters", "(JLjava/util/List;)Ljava/util/Map;", (void*)nativeGetParameters },
 };
 
 } // namespace Tuner
diff --git a/services/core/jni/BroadcastRadio/Tuner.h b/services/core/jni/BroadcastRadio/Tuner.h
index 48c3bc7..818597b 100644
--- a/services/core/jni/BroadcastRadio/Tuner.h
+++ b/services/core/jni/BroadcastRadio/Tuner.h
@@ -22,8 +22,8 @@
 #include "JavaRef.h"
 
 #include <android/hardware/broadcastradio/1.1/IBroadcastRadio.h>
-#include <android/hardware/broadcastradio/1.2/ITuner.h>
-#include <android/hardware/broadcastradio/1.2/ITunerCallback.h>
+#include <android/hardware/broadcastradio/1.1/ITuner.h>
+#include <android/hardware/broadcastradio/1.1/ITunerCallback.h>
 #include <jni.h>
 #include <utils/StrongPointer.h>
 
@@ -39,7 +39,7 @@
         sp<hardware::broadcastradio::V1_0::IBroadcastRadio> halModule,
         sp<hardware::broadcastradio::V1_0::ITuner> halTuner);
 
-sp<hardware::broadcastradio::V1_2::ITunerCallback>
+sp<hardware::broadcastradio::V1_1::ITunerCallback>
 getNativeCallback(JNIEnv *env, JavaRef<jobject> const &tuner);
 
 Region getRegion(JNIEnv *env, jobject obj);
diff --git a/services/core/jni/BroadcastRadio/TunerCallback.cpp b/services/core/jni/BroadcastRadio/TunerCallback.cpp
index 39f2c05..085a86a 100644
--- a/services/core/jni/BroadcastRadio/TunerCallback.cpp
+++ b/services/core/jni/BroadcastRadio/TunerCallback.cpp
@@ -40,18 +40,17 @@
 
 namespace V1_0 = hardware::broadcastradio::V1_0;
 namespace V1_1 = hardware::broadcastradio::V1_1;
-namespace V1_2 = hardware::broadcastradio::V1_2;
 namespace utils = hardware::broadcastradio::utils;
 
 using V1_0::Band;
 using V1_0::BandConfig;
 using V1_0::MetaData;
 using V1_0::Result;
+using V1_1::ITunerCallback;
 using V1_1::ProgramInfo;
 using V1_1::ProgramListResult;
 using V1_1::ProgramSelector;
 using V1_1::VendorKeyValue;
-using V1_2::ITunerCallback;
 using utils::HalRevision;
 
 static JavaVM *gvm = nullptr;
@@ -70,7 +69,6 @@
         jmethodID onBackgroundScanAvailabilityChange;
         jmethodID onBackgroundScanComplete;
         jmethodID onProgramListChanged;
-        jmethodID onParametersUpdated;
     } TunerCallback;
 } gjni;
 
@@ -122,7 +120,6 @@
     virtual Return<void> backgroundScanComplete(ProgramListResult result);
     virtual Return<void> programListChanged();
     virtual Return<void> currentProgramInfoChanged(const ProgramInfo& info);
-    virtual Return<void> parametersUpdated(const hidl_vec<VendorKeyValue>& parameters);
 };
 
 struct TunerCallbackContext {
@@ -344,17 +341,6 @@
     return Return<void>();
 }
 
-Return<void> NativeCallback::parametersUpdated(const hidl_vec<VendorKeyValue>& parameters) {
-    ALOGV("%s", __func__);
-
-    mCallbackThread.enqueue([this, parameters](JNIEnv *env) {
-        auto jParameters = convert::VendorInfoFromHal(env, parameters);
-        env->CallVoidMethod(mJCallback, gjni.TunerCallback.onParametersUpdated, jParameters.get());
-    });
-
-    return {};
-}
-
 static TunerCallbackContext& getNativeContext(jlong nativeContextHandle) {
     auto nativeContext = reinterpret_cast<TunerCallbackContext*>(nativeContextHandle);
     LOG_ALWAYS_FATAL_IF(nativeContext == nullptr, "Native context not initialized");
@@ -441,8 +427,6 @@
             "onBackgroundScanComplete", "()V");
     gjni.TunerCallback.onProgramListChanged = GetMethodIDOrDie(env, tunerCbClass,
             "onProgramListChanged", "()V");
-    gjni.TunerCallback.onParametersUpdated = GetMethodIDOrDie(env, tunerCbClass,
-            "onParametersUpdated", "(Ljava/util/Map;)V");
 
     auto res = jniRegisterNativeMethods(env, "com/android/server/broadcastradio/hal1/TunerCallback",
             gTunerCallbackMethods, NELEM(gTunerCallbackMethods));
diff --git a/services/core/jni/BroadcastRadio/TunerCallback.h b/services/core/jni/BroadcastRadio/TunerCallback.h
index 7e776c2..af12d21 100644
--- a/services/core/jni/BroadcastRadio/TunerCallback.h
+++ b/services/core/jni/BroadcastRadio/TunerCallback.h
@@ -21,7 +21,7 @@
 #include "NativeCallbackThread.h"
 #include "types.h"
 
-#include <android/hardware/broadcastradio/1.2/ITunerCallback.h>
+#include <android/hardware/broadcastradio/1.1/ITunerCallback.h>
 #include <jni.h>
 
 namespace android {
@@ -32,7 +32,7 @@
 namespace BroadcastRadio {
 namespace TunerCallback {
 
-sp<hardware::broadcastradio::V1_2::ITunerCallback>
+sp<hardware::broadcastradio::V1_1::ITunerCallback>
 getNativeCallback(JNIEnv *env, jobject jTunerCallback);
 
 } // namespace TunerCallback
diff --git a/services/robotests/src/com/android/server/backup/PerformBackupTaskTest.java b/services/robotests/src/com/android/server/backup/PerformBackupTaskTest.java
index cd9311f..a5beed0 100644
--- a/services/robotests/src/com/android/server/backup/PerformBackupTaskTest.java
+++ b/services/robotests/src/com/android/server/backup/PerformBackupTaskTest.java
@@ -17,19 +17,21 @@
 package com.android.server.backup;
 
 import static com.android.server.backup.testing.TransportData.backupTransport;
-import static com.android.server.backup.testing.TransportTestUtils.setUpTransport;
 
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.junit.Assert.fail;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyLong;
 import static org.mockito.ArgumentMatchers.argThat;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 import static org.robolectric.Shadows.shadowOf;
@@ -44,6 +46,7 @@
 import android.app.backup.BackupAgent;
 import android.app.backup.BackupDataInput;
 import android.app.backup.BackupDataOutput;
+import android.app.backup.BackupManager;
 import android.app.backup.BackupTransport;
 import android.app.backup.FullBackupDataOutput;
 import android.app.backup.IBackupManager;
@@ -70,6 +73,7 @@
 import com.android.server.backup.internal.OnTaskFinishedListener;
 import com.android.server.backup.internal.PerformBackupTask;
 import com.android.server.backup.testing.TransportData;
+import com.android.server.backup.testing.TransportTestUtils;
 import com.android.server.backup.testing.TransportTestUtils.TransportMock;
 import com.android.server.backup.transport.TransportClient;
 import com.android.server.testing.FrameworkRobolectricTestRunner;
@@ -132,31 +136,25 @@
     @Mock private IBackupManagerMonitor mMonitor;
     @Mock private OnTaskFinishedListener mListener;
     private TransportData mTransport;
-    private IBackupTransport mTransportBinder;
-    private TransportClient mTransportClient;
     private ShadowLooper mShadowBackupLooper;
     private BackupHandler mBackupHandler;
     private PowerManager.WakeLock mWakeLock;
     private ShadowPackageManager mShadowPackageManager;
     private FakeIBackupManager mBackupManager;
+    private File mBaseStateDir;
 
     @Before
     public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
 
         mTransport = backupTransport();
-        TransportMock transportMock = setUpTransport(mTransportManager, mTransport);
-        mTransportBinder = transportMock.transport;
-        mTransportClient = transportMock.transportClient;
 
         Application application = RuntimeEnvironment.application;
         File cacheDir = application.getCacheDir();
-        File baseStateDir = new File(cacheDir, "base_state_dir");
+        mBaseStateDir = new File(cacheDir, "base_state_dir");
         File dataDir = new File(cacheDir, "data_dir");
-        File stateDir = new File(baseStateDir, mTransport.transportDirName);
-        assertThat(baseStateDir.mkdir()).isTrue();
+        assertThat(mBaseStateDir.mkdir()).isTrue();
         assertThat(dataDir.mkdir()).isTrue();
-        assertThat(stateDir.mkdir()).isTrue();
 
         PackageManager packageManager = application.getPackageManager();
         mShadowPackageManager = Shadow.extract(packageManager);
@@ -182,7 +180,7 @@
         when(mBackupManagerService.getWakelock()).thenReturn(mWakeLock);
         when(mBackupManagerService.getCurrentOpLock()).thenReturn(new Object());
         when(mBackupManagerService.getQueueLock()).thenReturn(new Object());
-        when(mBackupManagerService.getBaseStateDir()).thenReturn(baseStateDir);
+        when(mBackupManagerService.getBaseStateDir()).thenReturn(mBaseStateDir);
         when(mBackupManagerService.getDataDir()).thenReturn(dataDir);
         when(mBackupManagerService.getCurrentOperations()).thenReturn(new SparseArray<>());
         when(mBackupManagerService.getBackupHandler()).thenReturn(mBackupHandler);
@@ -192,10 +190,16 @@
 
     @Test
     public void testRunTask_whenTransportProvidesFlags_passesThemToTheAgent() throws Exception {
+        TransportMock transportMock = setUpTransport(mTransport);
         AgentMock agentMock = setUpAgent(PACKAGE_1);
         int flags = BackupAgent.FLAG_CLIENT_SIDE_ENCRYPTION_ENABLED;
-        when(mTransportBinder.getTransportFlags()).thenReturn(flags);
-        PerformBackupTask task = createPerformBackupTask(emptyList(), false, true, PACKAGE_1);
+        when(transportMock.transport.getTransportFlags()).thenReturn(flags);
+        PerformBackupTask task =
+                createPerformBackupTask(
+                        transportMock.transportClient,
+                        mTransport.transportDirName,
+                        emptyList(),
+                        PACKAGE_1);
 
         runTask(task);
 
@@ -205,8 +209,14 @@
 
     @Test
     public void testRunTask_whenTransportDoesNotProvidesFlags() throws Exception {
+        TransportMock transportMock = setUpTransport(mTransport);
         AgentMock agentMock = setUpAgent(PACKAGE_1);
-        PerformBackupTask task = createPerformBackupTask(emptyList(), false, true, PACKAGE_1);
+        PerformBackupTask task =
+                createPerformBackupTask(
+                        transportMock.transportClient,
+                        mTransport.transportDirName,
+                        emptyList(),
+                        PACKAGE_1);
 
         runTask(task);
 
@@ -216,13 +226,19 @@
     @Test
     public void testRunTask_whenTransportProvidesFlagsAndMultipleAgents_passesToAll()
             throws Exception {
+        TransportMock transportMock = setUpTransport(mTransport);
         List<AgentMock> agentMocks = setUpAgents(PACKAGE_1, PACKAGE_2);
         BackupAgent agent1 = agentMocks.get(0).agent;
         BackupAgent agent2 = agentMocks.get(1).agent;
         int flags = BackupAgent.FLAG_CLIENT_SIDE_ENCRYPTION_ENABLED;
-        when(mTransportBinder.getTransportFlags()).thenReturn(flags);
+        when(transportMock.transport.getTransportFlags()).thenReturn(flags);
         PerformBackupTask task =
-                createPerformBackupTask(emptyList(), false, true, PACKAGE_1, PACKAGE_2);
+                createPerformBackupTask(
+                        transportMock.transportClient,
+                        mTransport.transportDirName,
+                        emptyList(),
+                        PACKAGE_1,
+                        PACKAGE_2);
 
         runTask(task);
 
@@ -232,10 +248,16 @@
 
     @Test
     public void testRunTask_whenTransportChangeFlagsAfterTaskCreation() throws Exception {
+        TransportMock transportMock = setUpTransport(mTransport);
         AgentMock agentMock = setUpAgent(PACKAGE_1);
-        PerformBackupTask task = createPerformBackupTask(emptyList(), false, true, PACKAGE_1);
+        PerformBackupTask task =
+                createPerformBackupTask(
+                        transportMock.transportClient,
+                        mTransport.transportDirName,
+                        emptyList(),
+                        PACKAGE_1);
         int flags = BackupAgent.FLAG_CLIENT_SIDE_ENCRYPTION_ENABLED;
-        when(mTransportBinder.getTransportFlags()).thenReturn(flags);
+        when(transportMock.transport.getTransportFlags()).thenReturn(flags);
 
         runTask(task);
 
@@ -244,17 +266,26 @@
     }
 
     @Test
-    public void testRunTask_callsListenerOnTaskFinished() throws Exception {
+    public void testRunTask_callsListenerAndObserver() throws Exception {
+        TransportMock transportMock = setUpTransport(mTransport);
         setUpAgent(PACKAGE_1);
-        PerformBackupTask task = createPerformBackupTask(emptyList(), false, true, PACKAGE_1);
+        PerformBackupTask task =
+                createPerformBackupTask(
+                        transportMock.transportClient,
+                        mTransport.transportDirName,
+                        emptyList(),
+                        PACKAGE_1);
 
         runTask(task);
 
         verify(mListener).onFinished(any());
+        verify(mObserver).backupFinished(eq(BackupManager.SUCCESS));
     }
 
     @Test
-    public void testRunTask_callsTransportPerformBackup() throws Exception {
+    public void testRunTask_callsTransportPerformBackupWithAgentData() throws Exception {
+        TransportMock transportMock = setUpTransport(mTransport);
+        IBackupTransport transportBinder = transportMock.transport;
         AgentMock agentMock = setUpAgent(PACKAGE_1);
         agentOnBackupDo(
                 agentMock.agent,
@@ -262,15 +293,20 @@
                     writeData(dataOutput, "key1", "foo".getBytes());
                     writeData(dataOutput, "key2", "bar".getBytes());
                 });
-        PerformBackupTask task = createPerformBackupTask(emptyList(), false, true, PACKAGE_1);
+        PerformBackupTask task =
+                createPerformBackupTask(
+                        transportMock.transportClient,
+                        mTransport.transportDirName,
+                        emptyList(),
+                        PACKAGE_1);
         // We need to verify at call time because the file is deleted right after
-        when(mTransportBinder.performBackup(argThat(packageInfo(PACKAGE_1)), any(), anyInt()))
+        when(transportBinder.performBackup(argThat(packageInfo(PACKAGE_1)), any(), anyInt()))
                 .then(this::mockAndVerifyTransportPerformBackupData);
 
         runTask(task);
 
         // Already verified data in mockAndVerifyPerformBackupData
-        verify(mTransportBinder).performBackup(argThat(packageInfo(PACKAGE_1)), any(), anyInt());
+        verify(transportBinder).performBackup(argThat(packageInfo(PACKAGE_1)), any(), anyInt());
     }
 
     private int mockAndVerifyTransportPerformBackupData(InvocationOnMock invocation)
@@ -305,18 +341,26 @@
     @Test
     public void testRunTask_whenPerformBackupSucceeds_callsTransportFinishBackup()
             throws Exception {
+        TransportMock transportMock = setUpTransport(mTransport);
+        IBackupTransport transportBinder = transportMock.transport;
         setUpAgent(PACKAGE_1);
-        PerformBackupTask task = createPerformBackupTask(emptyList(), false, true, PACKAGE_1);
-        when(mTransportBinder.performBackup(argThat(packageInfo(PACKAGE_1)), any(), anyInt()))
+        PerformBackupTask task =
+                createPerformBackupTask(
+                        transportMock.transportClient,
+                        mTransport.transportDirName,
+                        emptyList(),
+                        PACKAGE_1);
+        when(transportBinder.performBackup(argThat(packageInfo(PACKAGE_1)), any(), anyInt()))
                 .thenReturn(BackupTransport.TRANSPORT_OK);
 
         runTask(task);
 
-        verify(mTransportBinder).finishBackup();
+        verify(transportBinder).finishBackup();
     }
 
     @Test
     public void testRunTask_whenProhibitedKey_failsAgent() throws Exception {
+        TransportMock transportMock = setUpTransport(mTransport);
         AgentMock agentMock = setUpAgent(PACKAGE_1);
         agentOnBackupDo(
                 agentMock.agent,
@@ -324,13 +368,149 @@
                     char prohibitedChar = 0xff00;
                     writeData(dataOutput, prohibitedChar + "key", "foo".getBytes());
                 });
-        PerformBackupTask task = createPerformBackupTask(emptyList(), false, true, PACKAGE_1);
+        PerformBackupTask task =
+                createPerformBackupTask(
+                        transportMock.transportClient,
+                        mTransport.transportDirName,
+                        emptyList(),
+                        PACKAGE_1);
 
         runTask(task);
 
+        // TODO: Should it not call mListener.onFinished()? PerformBackupTask:891 return?
+        // verify(mListener).onFinished(any());
+        verify(mObserver).onResult(eq(PACKAGE_1), eq(BackupManager.ERROR_AGENT_FAILURE));
         verify(agentMock.agentBinder).fail(any());
     }
 
+    @Test
+    public void testRunTask_whenTransportUnavailable() throws Exception {
+        TransportMock transportMock = setUpTransport(mTransport.unavailable());
+        setUpAgent(PACKAGE_1);
+        PerformBackupTask task =
+                createPerformBackupTask(
+                        transportMock.transportClient,
+                        mTransport.transportDirName,
+                        emptyList(),
+                        PACKAGE_1);
+
+        runTask(task);
+
+        verify(mListener).onFinished(any());
+        // TODO: Should it be 2 times? (PBT.beginBackup() and PBT.finalizeBackup())
+        verify(mObserver, times(2)).backupFinished(eq(BackupManager.ERROR_TRANSPORT_ABORTED));
+    }
+
+    @Test
+    public void testRunTask_whenTransportRejectsPackage() throws Exception {
+        TransportMock transportMock = setUpTransport(mTransport);
+        setUpAgent(PACKAGE_1);
+        when(transportMock.transport.performBackup(
+                        argThat(packageInfo(PACKAGE_1)), any(), anyInt()))
+                .thenReturn(BackupTransport.TRANSPORT_PACKAGE_REJECTED);
+        PerformBackupTask task =
+                createPerformBackupTask(
+                        transportMock.transportClient,
+                        mTransport.transportDirName,
+                        emptyList(),
+                        PACKAGE_1);
+
+        runTask(task);
+
+        verify(mObserver).onResult(PACKAGE_1, BackupManager.ERROR_TRANSPORT_PACKAGE_REJECTED);
+        verify(mObserver).backupFinished(BackupManager.ERROR_TRANSPORT_ABORTED);
+    }
+
+    @Test
+    public void testRunTask_whenTransportRejectsFirstPackageButLastSucceeds() throws Exception {
+        TransportMock transportMock = setUpTransport(mTransport);
+        IBackupTransport transportBinder = transportMock.transport;
+        setUpAgents(PACKAGE_1, PACKAGE_2);
+        when(transportBinder.performBackup(argThat(packageInfo(PACKAGE_1)), any(), anyInt()))
+                .thenReturn(BackupTransport.TRANSPORT_PACKAGE_REJECTED);
+        when(transportBinder.performBackup(argThat(packageInfo(PACKAGE_2)), any(), anyInt()))
+                .thenReturn(BackupTransport.TRANSPORT_OK);
+        PerformBackupTask task =
+                createPerformBackupTask(
+                        transportMock.transportClient,
+                        mTransport.transportDirName,
+                        emptyList(),
+                        PACKAGE_1,
+                        PACKAGE_2);
+
+        runTask(task);
+
+        verify(mObserver).onResult(PACKAGE_1, BackupManager.ERROR_TRANSPORT_PACKAGE_REJECTED);
+        verify(mObserver).onResult(PACKAGE_2, BackupManager.SUCCESS);
+        verify(mObserver).backupFinished(BackupManager.SUCCESS);
+    }
+
+    @Test
+    public void testRunTask_whenTransportRejectsLastPackageButFirstSucceeds() throws Exception {
+        TransportMock transportMock = setUpTransport(mTransport);
+        IBackupTransport transportBinder = transportMock.transport;
+        setUpAgents(PACKAGE_1, PACKAGE_2);
+        when(transportBinder.performBackup(argThat(packageInfo(PACKAGE_1)), any(), anyInt()))
+                .thenReturn(BackupTransport.TRANSPORT_OK);
+        when(transportBinder.performBackup(argThat(packageInfo(PACKAGE_2)), any(), anyInt()))
+                .thenReturn(BackupTransport.TRANSPORT_PACKAGE_REJECTED);
+        PerformBackupTask task =
+                createPerformBackupTask(
+                        transportMock.transportClient,
+                        mTransport.transportDirName,
+                        emptyList(),
+                        PACKAGE_1,
+                        PACKAGE_2);
+
+        runTask(task);
+
+        verify(mObserver).onResult(PACKAGE_1, BackupManager.SUCCESS);
+        verify(mObserver).onResult(PACKAGE_2, BackupManager.ERROR_TRANSPORT_PACKAGE_REJECTED);
+        // TODO: Should we return the status of the last?
+        verify(mObserver).backupFinished(BackupManager.ERROR_TRANSPORT_ABORTED);
+    }
+
+    @Test
+    public void testRunTask_whenTransportReturnsQuotaExceeded() throws Exception {
+        TransportMock transportMock = setUpTransport(mTransport);
+        AgentMock agentMock = setUpAgent(PACKAGE_1);
+        when(transportMock.transport.performBackup(
+                        argThat(packageInfo(PACKAGE_1)), any(), anyInt()))
+                .thenReturn(BackupTransport.TRANSPORT_QUOTA_EXCEEDED);
+        PerformBackupTask task =
+                createPerformBackupTask(
+                        transportMock.transportClient,
+                        mTransport.transportDirName,
+                        emptyList(),
+                        PACKAGE_1);
+
+        runTask(task);
+
+        verify(mObserver).onResult(PACKAGE_1, BackupManager.ERROR_TRANSPORT_QUOTA_EXCEEDED);
+        verify(mObserver).backupFinished(BackupManager.ERROR_TRANSPORT_ABORTED);
+        verify(agentMock.agent).onQuotaExceeded(anyLong(), anyLong());
+    }
+
+    // TODO: Giving NPE at PerformBackupTask:524 because mCurrentPackage is null (PackageManager
+    // rightfully threw NameNotFoundException). Uncomment @Test when fixed.
+    // @Test
+    public void testRunTask_whenAgentUnknown() throws Exception {
+        // Not calling setUpAgent()
+        TransportMock transportMock = setUpTransport(mTransport);
+        PerformBackupTask task =
+                createPerformBackupTask(
+                        transportMock.transportClient,
+                        mTransport.transportDirName,
+                        emptyList(),
+                        PACKAGE_1);
+
+        runTask(task);
+
+        verify(transportMock.transport, never()).performBackup(any(), any(), anyInt());
+        verify(mObserver).onResult(PACKAGE_1, BackupManager.ERROR_PACKAGE_NOT_FOUND);
+        verify(mObserver).backupFinished(BackupManager.SUCCESS);
+    }
+
     private void runTask(PerformBackupTask task) {
         Message message = mBackupHandler.obtainMessage(BackupHandler.MSG_BACKUP_RESTORE_STEP, task);
         mBackupHandler.sendMessage(message);
@@ -339,6 +519,14 @@
         }
     }
 
+    private TransportMock setUpTransport(TransportData transport) throws Exception {
+        TransportMock transportMock =
+                TransportTestUtils.setUpTransport(mTransportManager, transport);
+        File stateDir = new File(mBaseStateDir, transport.transportDirName);
+        assertThat(stateDir.mkdir()).isTrue();
+        return transportMock;
+    }
+
     private List<AgentMock> setUpAgents(String... packageNames) {
         return Stream.of(packageNames).map(this::setUpAgent).collect(toList());
     }
@@ -370,9 +558,9 @@
     }
 
     private PerformBackupTask createPerformBackupTask(
+            TransportClient transportClient,
+            String transportDirName,
             List<String> pendingFullBackups,
-            boolean userInitiated,
-            boolean nonIncremental,
             String... packages) {
         ArrayList<BackupRequest> backupRequests =
                 Stream.of(packages).map(BackupRequest::new).collect(toCollection(ArrayList::new));
@@ -380,22 +568,30 @@
         PerformBackupTask task =
                 new PerformBackupTask(
                         mBackupManagerService,
-                        mTransportClient,
-                        mTransport.transportDirName,
+                        transportClient,
+                        transportDirName,
                         backupRequests,
                         mDataChangedJournal,
                         mObserver,
                         mMonitor,
                         mListener,
                         pendingFullBackups,
-                        userInitiated,
-                        nonIncremental);
+                        /* userInitiated */ false,
+                        /* nonIncremental */ true);
         mBackupManager.setUp(mBackupHandler, task);
         return task;
     }
 
     private static ArgumentMatcher<PackageInfo> packageInfo(String packageName) {
-        return packageInfo -> packageName.equals(packageInfo.packageName);
+        // We have to test for packageInfo nulity because of Mockito's own stubbing with argThat().
+        // E.g. if you do:
+        //
+        //   1. when(object.method(argThat(str -> str.equals("foo")))).thenReturn(0)
+        //   2. when(object.method(argThat(str -> str.equals("bar")))).thenReturn(2)
+        //
+        // The second line will throw NPE because it will call lambda 1 with null, since argThat()
+        // returns null. So we guard against that by checking for null.
+        return packageInfo -> packageInfo != null && packageName.equals(packageInfo.packageName);
     }
 
     private static ArgumentMatcher<BackupDataOutput> dataOutputWithTransportFlags(int flags) {
@@ -435,7 +631,7 @@
         private final IBackupAgent agentBinder;
         private final BackupAgent agent;
 
-        public AgentMock(IBackupAgent agentBinder, BackupAgent agent) {
+        private AgentMock(IBackupAgent agentBinder, BackupAgent agent) {
             this.agentBinder = agentBinder;
             this.agent = agent;
         }
diff --git a/services/tests/servicestests/AndroidManifest.xml b/services/tests/servicestests/AndroidManifest.xml
index 97d6c43..5d8aca1 100644
--- a/services/tests/servicestests/AndroidManifest.xml
+++ b/services/tests/servicestests/AndroidManifest.xml
@@ -60,7 +60,6 @@
     <uses-permission android:name="android.permission.ACCESS_SURFACE_FLINGER" />
     <uses-permission android:name="android.permission.READ_FRAME_BUFFER" />
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
-    <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
 
     <!-- Uses API introduced in O (26) -->
     <uses-sdk android:minSdkVersion="1"
diff --git a/services/tests/servicestests/src/com/android/server/am/MemoryStatUtilTest.java b/services/tests/servicestests/src/com/android/server/am/MemoryStatUtilTest.java
new file mode 100644
index 0000000..a7e3810
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/am/MemoryStatUtilTest.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.am;
+
+import static com.android.server.am.MemoryStatUtil.parseMemoryStat;
+import static com.android.server.am.MemoryStatUtil.MemoryStat;
+
+import static org.junit.Assert.assertEquals;
+
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class MemoryStatUtilTest {
+  private String MEMORY_STAT_CONTENTS = String.join(
+      "\n",
+      "cache 96", // keep different from total_cache to catch reading wrong value
+      "rss 97", // keep different from total_rss to catch reading wrong value
+      "rss_huge 0",
+      "mapped_file 524288",
+      "writeback 0",
+      "swap 95", // keep different from total_rss to catch reading wrong value
+      "pgpgin 16717",
+      "pgpgout 5037",
+      "pgfault 99", // keep different from total_pgfault to catch reading wrong value
+      "pgmajfault 98", // keep different from total_pgmajfault to catch reading wrong value
+      "inactive_anon 503808",
+      "active_anon 46309376",
+      "inactive_file 876544",
+      "active_file 81920",
+      "unevictable 0",
+      "hierarchical_memory_limit 18446744073709551615",
+      "hierarchical_memsw_limit 18446744073709551615",
+      "total_cache 4",
+      "total_rss 3",
+      "total_rss_huge 0",
+      "total_mapped_file 524288",
+      "total_writeback 0",
+      "total_swap 5",
+      "total_pgpgin 16717",
+      "total_pgpgout 5037",
+      "total_pgfault 1",
+      "total_pgmajfault 2",
+      "total_inactive_anon 503808",
+      "total_active_anon 46309376",
+      "total_inactive_file 876544",
+      "total_active_file 81920",
+      "total_unevictable 0");
+
+
+  @Test
+  public void testParseMemoryStat_parsesCorrectValues() throws Exception {
+    MemoryStat stat = parseMemoryStat(MEMORY_STAT_CONTENTS);
+    assertEquals(stat.pgfault, 1);
+    assertEquals(stat.pgmajfault, 2);
+    assertEquals(stat.rssInBytes, 3);
+    assertEquals(stat.cacheInBytes, 4);
+    assertEquals(stat.swapInBytes, 5);
+  }
+
+  @Test
+  public void testParseMemoryStat_emptyMemoryStatContents() throws Exception {
+    MemoryStat stat = parseMemoryStat("");
+    assertEquals(stat.pgfault, 0);
+    assertEquals(stat.pgmajfault, 0);
+    assertEquals(stat.rssInBytes, 0);
+    assertEquals(stat.cacheInBytes, 0);
+    assertEquals(stat.swapInBytes, 0);
+
+    stat = parseMemoryStat(null);
+    assertEquals(stat.pgfault, 0);
+    assertEquals(stat.pgmajfault, 0);
+    assertEquals(stat.rssInBytes, 0);
+    assertEquals(stat.cacheInBytes, 0);
+    assertEquals(stat.swapInBytes, 0);
+  }
+}
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java
index a523b86..8bd0df4 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java
@@ -503,6 +503,30 @@
     }
 
     @Test
+    public void recoverKeys_doesNotThrowIfNoApplicationKeysToBeDecrypted() throws Exception {
+        mRecoverableKeyStoreManager.startRecoverySession(
+                TEST_SESSION_ID,
+                TEST_PUBLIC_KEY,
+                TEST_VAULT_PARAMS,
+                TEST_VAULT_CHALLENGE,
+                ImmutableList.of(new KeyChainProtectionParams(
+                        TYPE_LOCKSCREEN,
+                        UI_FORMAT_PASSWORD,
+                        KeyDerivationParams.createSha256Params(TEST_SALT),
+                        TEST_SECRET)));
+        byte[] keyClaimant = mRecoverySessionStorage.get(Binder.getCallingUid(), TEST_SESSION_ID)
+                .getKeyClaimant();
+        SecretKey recoveryKey = randomRecoveryKey();
+        byte[] encryptedClaimResponse = encryptClaimResponse(
+                keyClaimant, TEST_SECRET, TEST_VAULT_PARAMS, recoveryKey);
+
+        mRecoverableKeyStoreManager.recoverKeys(
+                TEST_SESSION_ID,
+                /*encryptedRecoveryKey=*/ encryptedClaimResponse,
+                /*applicationKeys=*/ ImmutableList.of());
+    }
+
+    @Test
     public void recoverKeys_returnsDecryptedKeys() throws Exception {
         mRecoverableKeyStoreManager.startRecoverySession(
                 TEST_SESSION_ID,
diff --git a/services/tests/servicestests/src/com/android/server/net/ConnOnActivityStartTest.java b/services/tests/servicestests/src/com/android/server/net/ConnOnActivityStartTest.java
index 376db5b..6e1808b 100644
--- a/services/tests/servicestests/src/com/android/server/net/ConnOnActivityStartTest.java
+++ b/services/tests/servicestests/src/com/android/server/net/ConnOnActivityStartTest.java
@@ -117,7 +117,8 @@
     }
 
     @AfterClass
-    public static void tearDownOnce() {
+    public static void tearDownOnce() throws Exception {
+        batteryReset();
         if (mAppIdleConstsUpdated) {
             Settings.Global.putString(mContext.getContentResolver(),
                     Settings.Global.APP_IDLE_CONSTANTS, mOriginalAppIdleConsts);
@@ -213,12 +214,12 @@
     @Test
     public void testStartActivity_appStandby() throws Exception {
         try{
-            turnBatteryOff();
+            turnBatteryOn();
             setAppIdle(true);
             turnScreenOn();
             startActivityAndCheckNetworkAccess();
         } finally {
-            turnBatteryOn();
+            turnBatteryOff();
             finishActivity();
             setAppIdle(false);
         }
@@ -251,11 +252,11 @@
     // create a static library which can be used by both servicestests and cts.
     private void setBatterySaverMode(boolean enabled) throws Exception {
         if (enabled) {
-            turnBatteryOff();
+            turnBatteryOn();
             executeCommand("settings put global low_power 1");
         } else {
             executeCommand("settings put global low_power 0");
-            turnBatteryOn();
+            turnBatteryOff();
         }
         final String result = executeCommand("settings get global low_power");
         assertEquals(enabled ? "1" : "0", result);
@@ -271,12 +272,12 @@
 
     private void setDozeMode(boolean enabled) throws Exception {
         if (enabled) {
-            turnBatteryOff();
+            turnBatteryOn();
             turnScreenOff();
             executeCommand("dumpsys deviceidle force-idle deep");
         } else {
             turnScreenOn();
-            turnBatteryOn();
+            turnBatteryOff();
             executeCommand("dumpsys deviceidle unforce");
         }
         assertDelayedCommandResult("dumpsys deviceidle get deep", enabled ? "IDLE" : "ACTIVE",
@@ -320,12 +321,12 @@
                 + ". Full list: " + uids);
     }
 
-    private void turnBatteryOff() throws Exception {
+    private void turnBatteryOn() throws Exception {
         executeCommand("cmd battery unplug");
-        assertBatteryOff();
+        assertBatteryOn();
     }
 
-    private void assertBatteryOff() throws Exception {
+    private void assertBatteryOn() throws Exception {
         final long endTime = SystemClock.uptimeMillis() + BATTERY_OFF_TIMEOUT_MS;
         while (mBatteryManager.isCharging() && SystemClock.uptimeMillis() < endTime) {
             SystemClock.sleep(BATTERY_OFF_CHECK_INTERVAL_MS);
@@ -333,7 +334,11 @@
         assertFalse("Power should be disconnected", mBatteryManager.isCharging());
     }
 
-    private void turnBatteryOn() throws Exception {
+    private void turnBatteryOff() throws Exception {
+        executeCommand("cmd battery set ac " + BatteryManager.BATTERY_PLUGGED_AC);
+    }
+
+    private static void batteryReset() throws Exception {
         executeCommand("cmd battery reset");
     }
 
@@ -348,7 +353,7 @@
         SystemClock.sleep(SCREEN_ON_DELAY_MS);
     }
 
-    private String executeCommand(String cmd) throws IOException {
+    private static String executeCommand(String cmd) throws IOException {
         final String result = executeSilentCommand(cmd);
         Log.d(TAG, String.format("Result for '%s': %s", cmd, result));
         return result;
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
index 98483a8..53d97e7 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
@@ -612,7 +612,6 @@
         assertThat(origPkgSetting.installerPackageName, is(testPkgSetting.installerPackageName));
         assertThat(origPkgSetting.installPermissionsFixed,
                 is(testPkgSetting.installPermissionsFixed));
-        assertThat(origPkgSetting.installStatus, is(testPkgSetting.installStatus));
         assertThat(origPkgSetting.isOrphaned, is(testPkgSetting.isOrphaned));
         assertSame(origPkgSetting.keySetData, testPkgSetting.keySetData);
         assertThat(origPkgSetting.keySetData, is(testPkgSetting.keySetData));
diff --git a/services/tests/servicestests/src/com/android/server/timezone/PackageTrackerTest.java b/services/tests/servicestests/src/com/android/server/timezone/PackageTrackerTest.java
index 9cf6392..d9f4adf 100644
--- a/services/tests/servicestests/src/com/android/server/timezone/PackageTrackerTest.java
+++ b/services/tests/servicestests/src/com/android/server/timezone/PackageTrackerTest.java
@@ -31,7 +31,6 @@
 import android.support.test.filters.SmallTest;
 
 import java.io.File;
-import java.io.IOException;
 import java.io.PrintWriter;
 import java.io.StringWriter;
 import java.time.Clock;
@@ -1400,7 +1399,7 @@
     /**
      * A fake IntentHelper implementation for use in tests.
      */
-    private static class FakeIntentHelper implements IntentHelper {
+    private static class FakeIntentHelper implements PackageTrackerIntentHelper {
 
         private PackageTracker mPackageTracker;
         private String mUpdateAppPackageName;
diff --git a/services/tests/servicestests/src/com/android/server/timezone/RulesManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/timezone/RulesManagerServiceTest.java
index 1cfae1e..f5969f3 100644
--- a/services/tests/servicestests/src/com/android/server/timezone/RulesManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/timezone/RulesManagerServiceTest.java
@@ -68,6 +68,7 @@
 
     private FakeExecutor mFakeExecutor;
     private PermissionHelper mMockPermissionHelper;
+    private RulesManagerIntentHelper mMockIntentHelper;
     private PackageTracker mMockPackageTracker;
     private TimeZoneDistroInstaller mMockTimeZoneDistroInstaller;
 
@@ -77,11 +78,13 @@
 
         mMockPackageTracker = mock(PackageTracker.class);
         mMockPermissionHelper = mock(PermissionHelper.class);
+        mMockIntentHelper = mock(RulesManagerIntentHelper.class);
         mMockTimeZoneDistroInstaller = mock(TimeZoneDistroInstaller.class);
 
         mRulesManagerService = new RulesManagerService(
                 mMockPermissionHelper,
                 mFakeExecutor,
+                mMockIntentHelper,
                 mMockPackageTracker,
                 mMockTimeZoneDistroInstaller);
     }
@@ -329,6 +332,7 @@
         mFakeExecutor.assertNothingQueued();
         verifyNoInstallerCallsMade();
         verifyNoPackageTrackerCallsMade();
+        verifyNoIntentsSent();
     }
 
     @Test
@@ -353,6 +357,7 @@
         mFakeExecutor.assertNothingQueued();
         verifyNoInstallerCallsMade();
         verifyNoPackageTrackerCallsMade();
+        verifyNoIntentsSent();
     }
 
     @Test
@@ -372,6 +377,7 @@
         mFakeExecutor.assertNothingQueued();
         verifyNoInstallerCallsMade();
         verifyNoPackageTrackerCallsMade();
+        verifyNoIntentsSent();
     }
 
     @Test
@@ -394,6 +400,7 @@
         mFakeExecutor.assertNothingQueued();
         verifyNoInstallerCallsMade();
         verifyNoPackageTrackerCallsMade();
+        verifyNoIntentsSent();
     }
 
     @Test
@@ -416,6 +423,7 @@
         callback.assertNoResultReceived();
         verifyNoInstallerCallsMade();
         verifyNoPackageTrackerCallsMade();
+        verifyNoIntentsSent();
 
         // Set up the installer.
         configureStageInstallExpectation(TimeZoneDistroInstaller.INSTALL_SUCCESS);
@@ -428,6 +436,7 @@
         // Verify the expected calls were made to other components.
         verifyStageInstallCalled();
         verifyPackageTrackerCalled(token, true /* success */);
+        verifyStagedOperationIntentSent();
 
         // Check the callback was called.
         callback.assertResultReceived(Callback.SUCCESS);
@@ -450,6 +459,7 @@
         // Assert nothing has happened yet.
         verifyNoInstallerCallsMade();
         callback.assertNoResultReceived();
+        verifyNoIntentsSent();
 
         // Set up the installer.
         configureStageInstallExpectation(TimeZoneDistroInstaller.INSTALL_SUCCESS);
@@ -462,6 +472,7 @@
         // Verify the expected calls were made to other components.
         verifyStageInstallCalled();
         verifyPackageTrackerCalled(null /* expectedToken */, true /* success */);
+        verifyStagedOperationIntentSent();
 
         // Check the callback was received.
         callback.assertResultReceived(Callback.SUCCESS);
@@ -486,6 +497,7 @@
         // Assert nothing has happened yet.
         verifyNoInstallerCallsMade();
         callback.assertNoResultReceived();
+        verifyNoIntentsSent();
 
         // Set up the installer.
         configureStageInstallExpectation(TimeZoneDistroInstaller.INSTALL_FAIL_VALIDATION_ERROR);
@@ -502,6 +514,9 @@
         boolean expectedSuccess = true;
         verifyPackageTrackerCalled(token, expectedSuccess);
 
+        // Nothing should be staged, so no intents sent.
+        verifyNoIntentsSent();
+
         // Check the callback was received.
         callback.assertResultReceived(Callback.ERROR_INSTALL_VALIDATION_ERROR);
     }
@@ -529,6 +544,7 @@
         mFakeExecutor.assertNothingQueued();
         verifyNoInstallerCallsMade();
         verifyNoPackageTrackerCallsMade();
+        verifyNoIntentsSent();
     }
 
     @Test
@@ -548,6 +564,7 @@
         mFakeExecutor.assertNothingQueued();
         verifyNoInstallerCallsMade();
         verifyNoPackageTrackerCallsMade();
+        verifyNoIntentsSent();
     }
 
     @Test
@@ -566,6 +583,7 @@
         mFakeExecutor.assertNothingQueued();
         verifyNoInstallerCallsMade();
         verifyNoPackageTrackerCallsMade();
+        verifyNoIntentsSent();
     }
 
     @Test
@@ -585,6 +603,7 @@
         callback.assertNoResultReceived();
         verifyNoInstallerCallsMade();
         verifyNoPackageTrackerCallsMade();
+        verifyNoIntentsSent();
 
         // Set up the installer.
         configureStageUninstallExpectation(TimeZoneDistroInstaller.UNINSTALL_SUCCESS);
@@ -595,6 +614,7 @@
         // Verify the expected calls were made to other components.
         verifyStageUninstallCalled();
         verifyPackageTrackerCalled(token, true /* success */);
+        verifyStagedOperationIntentSent();
 
         // Check the callback was called.
         callback.assertResultReceived(Callback.SUCCESS);
@@ -617,6 +637,7 @@
         callback.assertNoResultReceived();
         verifyNoInstallerCallsMade();
         verifyNoPackageTrackerCallsMade();
+        verifyNoIntentsSent();
 
         // Set up the installer.
         configureStageUninstallExpectation(TimeZoneDistroInstaller.UNINSTALL_NOTHING_INSTALLED);
@@ -627,6 +648,7 @@
         // Verify the expected calls were made to other components.
         verifyStageUninstallCalled();
         verifyPackageTrackerCalled(token, true /* success */);
+        verifyUnstagedOperationIntentSent();
 
         // Check the callback was called.
         callback.assertResultReceived(Callback.SUCCESS);
@@ -645,6 +667,7 @@
         // Assert nothing has happened yet.
         verifyNoInstallerCallsMade();
         callback.assertNoResultReceived();
+        verifyNoIntentsSent();
 
         // Set up the installer.
         configureStageUninstallExpectation(TimeZoneDistroInstaller.UNINSTALL_SUCCESS);
@@ -655,6 +678,7 @@
         // Verify the expected calls were made to other components.
         verifyStageUninstallCalled();
         verifyPackageTrackerCalled(null /* expectedToken */, true /* success */);
+        verifyStagedOperationIntentSent();
 
         // Check the callback was received.
         callback.assertResultReceived(Callback.SUCCESS);
@@ -676,6 +700,7 @@
         // Assert nothing has happened yet.
         verifyNoInstallerCallsMade();
         callback.assertNoResultReceived();
+        verifyNoIntentsSent();
 
         // Set up the installer.
         configureStageUninstallExpectation(TimeZoneDistroInstaller.UNINSTALL_FAIL);
@@ -686,6 +711,7 @@
         // Verify the expected calls were made to other components.
         verifyStageUninstallCalled();
         verifyPackageTrackerCalled(token, false /* success */);
+        verifyNoIntentsSent();
 
         // Check the callback was received.
         callback.assertResultReceived(Callback.ERROR_UNKNOWN_FAILURE);
@@ -714,6 +740,7 @@
         // Verify the expected calls were made to other components.
         verifyPackageTrackerCalled(token, true /* success */);
         verifyNoInstallerCallsMade();
+        verifyNoIntentsSent();
     }
 
     @Test
@@ -734,6 +761,7 @@
         // Assert no other calls were made.
         verifyNoInstallerCallsMade();
         verifyNoPackageTrackerCallsMade();
+        verifyNoIntentsSent();
     }
 
     @Test
@@ -749,6 +777,7 @@
         // Assert everything required was done.
         verifyNoInstallerCallsMade();
         verifyPackageTrackerCalled(token, false /* success */);
+        verifyNoIntentsSent();
     }
 
     @Test
@@ -761,6 +790,7 @@
         // Assert everything required was done.
         verifyNoInstallerCallsMade();
         verifyPackageTrackerCalled(null /* token */, true /* success */);
+        verifyNoIntentsSent();
     }
 
     @Test
@@ -865,6 +895,21 @@
         reset(mMockPackageTracker);
     }
 
+    private void verifyNoIntentsSent() {
+        verifyNoMoreInteractions(mMockIntentHelper);
+        reset(mMockIntentHelper);
+    }
+
+    private void verifyStagedOperationIntentSent() {
+        verify(mMockIntentHelper).sendTimeZoneOperationStaged();
+        reset(mMockIntentHelper);
+    }
+
+    private void verifyUnstagedOperationIntentSent() {
+        verify(mMockIntentHelper).sendTimeZoneOperationUnstaged();
+        reset(mMockIntentHelper);
+    }
+
     private void configureCallerHasPermission() throws Exception {
         doNothing()
                 .when(mMockPermissionHelper)
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordTest.java
index a5fa903..a566327 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordTest.java
@@ -15,10 +15,13 @@
  */
 package com.android.server.notification;
 
+import static android.app.NotificationChannel.USER_LOCKED_IMPORTANCE;
 import static android.service.notification.NotificationListenerService.Ranking
         .USER_SENTIMENT_NEGATIVE;
 import static android.service.notification.NotificationListenerService.Ranking
         .USER_SENTIMENT_NEUTRAL;
+import static android.service.notification.NotificationListenerService.Ranking
+        .USER_SENTIMENT_POSITIVE;
 
 import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.assertFalse;
@@ -315,7 +318,7 @@
     @Test
     public void testImportance_locked_preUpgrade() throws Exception {
         defaultChannel.setImportance(NotificationManager.IMPORTANCE_LOW);
-        defaultChannel.lockFields(NotificationChannel.USER_LOCKED_IMPORTANCE);
+        defaultChannel.lockFields(USER_LOCKED_IMPORTANCE);
         StatusBarNotification sbn = getNotification(true /*preO */, true /* noisy */,
                 true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
                 false /* lights */, false /* defaultLights */, null /* group */);
@@ -327,7 +330,7 @@
     @Test
     public void testImportance_locked_unspecified_preUpgrade() throws Exception {
         defaultChannel.setImportance(NotificationManager.IMPORTANCE_UNSPECIFIED);
-        defaultChannel.lockFields(NotificationChannel.USER_LOCKED_IMPORTANCE);
+        defaultChannel.lockFields(USER_LOCKED_IMPORTANCE);
         StatusBarNotification sbn = getNotification(true /*preO */, true /* noisy */,
                 true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
                 false /* lights */, false /* defaultLights */, null /* group */);
@@ -549,4 +552,23 @@
 
         assertEquals(USER_SENTIMENT_NEGATIVE, record.getUserSentiment());
     }
+
+    @Test
+    public void testUserSentiment_userLocked() throws Exception {
+        channel.lockFields(USER_LOCKED_IMPORTANCE);
+        StatusBarNotification sbn = getNotification(false /*preO */, true /* noisy */,
+                true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
+                false /* lights */, false /* defaultLights */, groupId /* group */);
+        NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
+
+        assertEquals(USER_SENTIMENT_POSITIVE, record.getUserSentiment());
+
+        Bundle signals = new Bundle();
+        signals.putInt(Adjustment.KEY_USER_SENTIMENT, USER_SENTIMENT_NEGATIVE);
+        record.addAdjustment(new Adjustment(pkg, record.getKey(), signals, null, sbn.getUserId()));
+
+        record.applyAdjustments();
+
+        assertEquals(USER_SENTIMENT_POSITIVE, record.getUserSentiment());
+    }
 }
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/RankingHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/RankingHelperTest.java
index abfc54d..9ebce71 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/RankingHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/RankingHelperTest.java
@@ -914,16 +914,18 @@
         final NotificationChannel update1 = getChannel();
         update1.setSound(new Uri.Builder().scheme("test").build(),
                 new AudioAttributes.Builder().build());
-        update1.lockFields(NotificationChannel.USER_LOCKED_PRIORITY); // should be ignored
+        update1.lockFields(NotificationChannel.USER_LOCKED_PRIORITY);
         mHelper.updateNotificationChannel(PKG, UID, update1, true);
-        assertEquals(NotificationChannel.USER_LOCKED_SOUND,
+        assertEquals(NotificationChannel.USER_LOCKED_PRIORITY
+                | NotificationChannel.USER_LOCKED_SOUND,
                 mHelper.getNotificationChannel(PKG, UID, update1.getId(), false)
                         .getUserLockedFields());
 
         NotificationChannel update2 = getChannel();
         update2.enableVibration(true);
         mHelper.updateNotificationChannel(PKG, UID, update2, true);
-        assertEquals(NotificationChannel.USER_LOCKED_SOUND
+        assertEquals(NotificationChannel.USER_LOCKED_PRIORITY
+                        | NotificationChannel.USER_LOCKED_SOUND
                         | NotificationChannel.USER_LOCKED_VIBRATION,
                 mHelper.getNotificationChannel(PKG, UID, update2.getId(), false)
                         .getUserLockedFields());
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index 6806947..a7fc470 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -1786,7 +1786,7 @@
                         mGadgetProxy = IUsbGadget.getService();
                         mGadgetProxy.linkToDeath(new UsbGadgetDeathRecipient(),
                                 USB_GADGET_HAL_DEATH_COOKIE);
-                        if (!mCurrentFunctionsApplied) {
+                        if (!mCurrentFunctionsApplied && !mCurrentUsbFunctionsRequested) {
                             setEnabledFunctions(mCurrentFunctions, false);
                         }
                     } catch (NoSuchElementException e) {
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index 24184e0..d8599e8 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -2743,7 +2743,20 @@
     /**
      * Notifies this Connection, which is in {@link #STATE_RINGING}, of
      * a request to accept.
-     *
+     * <p>
+     * For managed {@link ConnectionService}s, this will be called when the user answers a call via
+     * the default dialer's {@link InCallService}.
+     * <p>
+     * Although a self-managed {@link ConnectionService} provides its own incoming call UI, the
+     * Telecom framework may request that the call is answered in the following circumstances:
+     * <ul>
+     *     <li>The user chooses to answer an incoming call via a Bluetooth device.</li>
+     *     <li>A car mode {@link InCallService} is in use which has declared
+     *     {@link TelecomManager#METADATA_INCLUDE_SELF_MANAGED_CALLS} in its manifest.  Such an
+     *     {@link InCallService} will be able to see calls from self-managed
+     *     {@link ConnectionService}s, and will be able to display an incoming call UI on their
+     *     behalf.</li>
+     * </ul>
      * @param videoState The video state in which to answer the connection.
      */
     public void onAnswer(int videoState) {}
@@ -2751,6 +2764,20 @@
     /**
      * Notifies this Connection, which is in {@link #STATE_RINGING}, of
      * a request to accept.
+     * <p>
+     * For managed {@link ConnectionService}s, this will be called when the user answers a call via
+     * the default dialer's {@link InCallService}.
+     * <p>
+     * Although a self-managed {@link ConnectionService} provides its own incoming call UI, the
+     * Telecom framework may request that the call is answered in the following circumstances:
+     * <ul>
+     *     <li>The user chooses to answer an incoming call via a Bluetooth device.</li>
+     *     <li>A car mode {@link InCallService} is in use which has declared
+     *     {@link TelecomManager#METADATA_INCLUDE_SELF_MANAGED_CALLS} in its manifest.  Such an
+     *     {@link InCallService} will be able to see calls from self-managed
+     *     {@link ConnectionService}s, and will be able to display an incoming call UI on their
+     *     behalf.</li>
+     * </ul>
      */
     public void onAnswer() {
         onAnswer(VideoProfile.STATE_AUDIO_ONLY);
@@ -2765,6 +2792,20 @@
     /**
      * Notifies this Connection, which is in {@link #STATE_RINGING}, of
      * a request to reject.
+     * <p>
+     * For managed {@link ConnectionService}s, this will be called when the user rejects a call via
+     * the default dialer's {@link InCallService}.
+     * <p>
+     * Although a self-managed {@link ConnectionService} provides its own incoming call UI, the
+     * Telecom framework may request that the call is rejected in the following circumstances:
+     * <ul>
+     *     <li>The user chooses to reject an incoming call via a Bluetooth device.</li>
+     *     <li>A car mode {@link InCallService} is in use which has declared
+     *     {@link TelecomManager#METADATA_INCLUDE_SELF_MANAGED_CALLS} in its manifest.  Such an
+     *     {@link InCallService} will be able to see calls from self-managed
+     *     {@link ConnectionService}s, and will be able to display an incoming call UI on their
+     *     behalf.</li>
+     * </ul>
      */
     public void onReject() {}
 
@@ -2847,9 +2888,10 @@
      * should show its own incoming call user interface.
      * <p>
      * Where there are ongoing calls in other self-managed {@link ConnectionService}s, or in a
-     * regular {@link ConnectionService}, the Telecom framework will display its own incoming call
-     * user interface to allow the user to choose whether to answer the new incoming call and
-     * disconnect other ongoing calls, or to reject the new incoming call.
+     * regular {@link ConnectionService}, and it is not possible to hold these other calls, the
+     * Telecom framework will display its own incoming call user interface to allow the user to
+     * choose whether to answer the new incoming call and disconnect other ongoing calls, or to
+     * reject the new incoming call.
      * <p>
      * You should trigger the display of the incoming call user interface for your application by
      * showing a {@link Notification} with a full-screen {@link Intent} specified.
diff --git a/telecomm/java/android/telecom/InCallService.java b/telecomm/java/android/telecom/InCallService.java
index fcf04c9..af65c65 100644
--- a/telecomm/java/android/telecom/InCallService.java
+++ b/telecomm/java/android/telecom/InCallService.java
@@ -60,6 +60,26 @@
  * </service>
  * }
  * </pre>
+ * <p>
+ * In addition to implementing the {@link InCallService} API, you must also declare an activity in
+ * your manifest which handles the {@link Intent#ACTION_DIAL} intent.  The example below illustrates
+ * how this is done:
+ * <pre>
+ * {@code
+ * <activity android:name="your.package.YourDialerActivity"
+ *           android:label="@string/yourDialerActivityLabel">
+ *      <intent-filter>
+ *           <action android:name="android.intent.action.DIAL" />
+ *           <category android:name="android.intent.category.DEFAULT" />
+ *      </intent-filter>
+ * </activity>
+ * }
+ * </pre>
+ * <p>
+ * When a user installs your application and runs it for the first time, you should prompt the user
+ * to see if they would like your application to be the new default phone app.  See the
+ * {@link TelecomManager#ACTION_CHANGE_DEFAULT_DIALER} intent documentation for more information on
+ * how to do this.
  */
 public abstract class InCallService extends Service {
 
diff --git a/telephony/java/android/provider/Telephony.java b/telephony/java/android/provider/Telephony.java
index 8c45724..63263bd 100644
--- a/telephony/java/android/provider/Telephony.java
+++ b/telephony/java/android/provider/Telephony.java
@@ -33,6 +33,7 @@
 import android.telephony.ServiceState;
 import android.telephony.SmsMessage;
 import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
 import android.text.TextUtils;
 import android.util.Patterns;
 
@@ -3345,73 +3346,118 @@
     }
 
     /**
-     * Contains carrier identification information.
-     * @hide
+     * Contains carrier identification information for the current subscriptions.
+     * @see SubscriptionManager#getActiveSubscriptionIdList()
      */
     public static final class CarrierIdentification implements BaseColumns {
         /**
-         * Numeric operator ID (as String). {@code MCC + MNC}
-         * <P>Type: TEXT </P>
+         * Not instantiable.
+         * @hide
          */
-        public static final String MCCMNC = "mccmnc";
+        private CarrierIdentification() {}
 
         /**
-         * Group id level 1 (as String).
-         * <P>Type: TEXT </P>
+         * The {@code content://} style URI for this provider.
          */
-        public static final String GID1 = "gid1";
+        public static final Uri CONTENT_URI = Uri.parse("content://carrier_identification");
 
         /**
-         * Group id level 2 (as String).
-         * <P>Type: TEXT </P>
+         * The authority string for the CarrierIdentification Provider
+         * @hide
          */
-        public static final String GID2 = "gid2";
+        public static final String AUTHORITY = "carrier_identification";
+
 
         /**
-         * Public Land Mobile Network name.
-         * <P>Type: TEXT </P>
+         * Generates a content {@link Uri} used to receive updates on carrier identity change
+         * on the given subscriptionId
+         * <p>
+         * Use this {@link Uri} with a {@link ContentObserver} to be notified of changes to the
+         * carrier identity {@link TelephonyManager#getAndroidCarrierIdForSubscription()}
+         * while your app is running. You can also use a {@link JobService} to ensure your app
+         * is notified of changes to the {@link Uri} even when it is not running.
+         * Note, however, that using a {@link JobService} does not guarantee timely delivery of
+         * updates to the {@link Uri}.
+         *
+         * @param subscriptionId the subscriptionId to receive updates on
+         * @return the Uri used to observe carrier identity changes
          */
-        public static final String PLMN = "plmn";
+        public static Uri getUriForSubscriptionId(int subscriptionId) {
+            return CONTENT_URI.buildUpon().appendEncodedPath(
+                    String.valueOf(subscriptionId)).build();
+        }
 
         /**
-         * Prefix xpattern of IMSI (International Mobile Subscriber Identity).
-         * <P>Type: TEXT </P>
-         */
-        public static final String IMSI_PREFIX_XPATTERN = "imsi_prefix_xpattern";
-
-        /**
-         * Service Provider Name.
-         * <P>Type: TEXT </P>
-         */
-        public static final String SPN = "spn";
-
-        /**
-         * Prefer APN name.
-         * <P>Type: TEXT </P>
-         */
-        public static final String APN = "apn";
-
-        /**
-         * Prefix of Integrated Circuit Card Identifier.
-         * <P>Type: TEXT </P>
-         */
-        public static final String ICCID_PREFIX = "iccid_prefix";
-
-        /**
-         * User facing carrier name.
+         * A user facing carrier name.
+         * @see TelephonyManager#getAndroidCarrierNameForSubscription()
          * <P>Type: TEXT </P>
          */
         public static final String NAME = "carrier_name";
 
         /**
          * A unique carrier id
+         * @see TelephonyManager#getAndroidCarrierIdForSubscription()
          * <P>Type: INTEGER </P>
          */
         public static final String CID = "carrier_id";
 
         /**
-         * The {@code content://} URI for this table.
+         * Contains mappings between matching rules with carrier id for all carriers.
+         * @hide
          */
-        public static final Uri CONTENT_URI = Uri.parse("content://carrier_identification");
+        public static final class All implements BaseColumns {
+            /**
+             * Numeric operator ID (as String). {@code MCC + MNC}
+             * <P>Type: TEXT </P>
+             */
+            public static final String MCCMNC = "mccmnc";
+
+            /**
+             * Group id level 1 (as String).
+             * <P>Type: TEXT </P>
+             */
+            public static final String GID1 = "gid1";
+
+            /**
+             * Group id level 2 (as String).
+             * <P>Type: TEXT </P>
+             */
+            public static final String GID2 = "gid2";
+
+            /**
+             * Public Land Mobile Network name.
+             * <P>Type: TEXT </P>
+             */
+            public static final String PLMN = "plmn";
+
+            /**
+             * Prefix xpattern of IMSI (International Mobile Subscriber Identity).
+             * <P>Type: TEXT </P>
+             */
+            public static final String IMSI_PREFIX_XPATTERN = "imsi_prefix_xpattern";
+
+            /**
+             * Service Provider Name.
+             * <P>Type: TEXT </P>
+             */
+            public static final String SPN = "spn";
+
+            /**
+             * Prefer APN name.
+             * <P>Type: TEXT </P>
+             */
+            public static final String APN = "apn";
+
+            /**
+             * Prefix of Integrated Circuit Card Identifier.
+             * <P>Type: TEXT </P>
+             */
+            public static final String ICCID_PREFIX = "iccid_prefix";
+
+            /**
+             * The {@code content://} URI for this table.
+             */
+            public static final Uri CONTENT_URI = Uri.parse("content://carrier_identification/all");
+        }
     }
 }
diff --git a/telephony/java/android/telephony/OWNERS b/telephony/java/android/telephony/OWNERS
new file mode 100644
index 0000000..68dedce
--- /dev/null
+++ b/telephony/java/android/telephony/OWNERS
@@ -0,0 +1,14 @@
+set noparent
+
+amitmahajan@google.com
+breadley@google.com
+fionaxu@google.com
+jackyu@google.com
+hallliu@google.com
+rgreenwalt@google.com
+tgunn@google.com
+jminjie@google.com
+mpq@google.com
+shuoq@google.com
+refuhoo@google.com
+
diff --git a/telephony/java/android/telephony/SubscriptionInfo.java b/telephony/java/android/telephony/SubscriptionInfo.java
index 38408fe..77413d9c 100644
--- a/telephony/java/android/telephony/SubscriptionInfo.java
+++ b/telephony/java/android/telephony/SubscriptionInfo.java
@@ -17,6 +17,7 @@
 package android.telephony;
 
 import android.annotation.Nullable;
+import android.annotation.SystemApi;
 import android.content.Context;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
@@ -34,6 +35,8 @@
 import android.util.DisplayMetrics;
 
 import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.List;
 
 /**
  * A Parcelable class for Subscription Information.
@@ -332,12 +335,7 @@
         return this.mCountryIso;
     }
 
-    /**
-     * @return whether the subscription is an embedded one.
-     * @hide
-     *
-     * TODO(b/35851809): Make this public.
-     */
+    /** @return whether the subscription is an embedded one. */
     public boolean isEmbedded() {
         return this.mIsEmbedded;
     }
@@ -351,9 +349,9 @@
      * @return whether the app is authorized to manage this subscription per its metadata.
      * @throws UnsupportedOperationException if this subscription is not embedded.
      * @hide
-     *
-     * TODO(b/35851809): Make this public.
+     * @deprecated - Do not use.
      */
+    @Deprecated
     public boolean canManageSubscription(Context context) {
         return canManageSubscription(context, context.getPackageName());
     }
@@ -367,7 +365,9 @@
      * @return whether the app is authorized to manage this subscription per its metadata.
      * @throws UnsupportedOperationException if this subscription is not embedded.
      * @hide
+     * @deprecated - Do not use.
      */
+    @Deprecated
     public boolean canManageSubscription(Context context, String packageName) {
         if (!isEmbedded()) {
             throw new UnsupportedOperationException("Not an embedded subscription");
@@ -395,14 +395,14 @@
      * @return the {@link UiccAccessRule}s dictating who is authorized to manage this subscription.
      * @throws UnsupportedOperationException if this subscription is not embedded.
      * @hide
-     *
-     * TODO(b/35851809): Make this a SystemApi.
      */
-    public @Nullable UiccAccessRule[] getAccessRules() {
+    @SystemApi
+    public @Nullable List<UiccAccessRule> getAccessRules() {
         if (!isEmbedded()) {
             throw new UnsupportedOperationException("Not an embedded subscription");
         }
-        return mAccessRules;
+        if (mAccessRules == null) return null;
+        return Arrays.asList(mAccessRules);
     }
 
     /**
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index debf43d..11a1984 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -30,6 +30,7 @@
 import android.app.BroadcastOptions;
 import android.content.Context;
 import android.content.Intent;
+import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.content.res.Configuration;
 import android.content.res.Resources;
@@ -822,10 +823,13 @@
      * if the list is non-empty the list is sorted by {@link SubscriptionInfo#getSimSlotIndex}
      * then by {@link SubscriptionInfo#getSubscriptionId}.
      * </ul>
-     * @hide
      *
-     * TODO(b/35851809): Make this a SystemApi.
+     * <p>
+     * Permissions android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE is required
+     * for #getAvailableSubscriptionInfoList to be invoked.
+     * @hide
      */
+    @SystemApi
     public List<SubscriptionInfo> getAvailableSubscriptionInfoList() {
         List<SubscriptionInfo> result = null;
 
@@ -863,9 +867,6 @@
      * if the list is non-empty the list is sorted by {@link SubscriptionInfo#getSimSlotIndex}
      * then by {@link SubscriptionInfo#getSubscriptionId}.
      * </ul>
-     * @hide
-     *
-     * TODO(b/35851809): Make this public.
      */
     public List<SubscriptionInfo> getAccessibleSubscriptionInfoList() {
         List<SubscriptionInfo> result = null;
@@ -891,9 +892,8 @@
      *
      * <p>Requires the {@link android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS} permission.
      * @hide
-     *
-     * TODO(b/35851809): Make this a SystemApi.
      */
+    @SystemApi
     public void requestEmbeddedSubscriptionInfoListRefresh() {
         try {
             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
@@ -1892,4 +1892,51 @@
         options.setTemporaryAppWhitelistDuration(TimeUnit.MINUTES.toMillis(1));
         mContext.sendBroadcast(intent, null, options.toBundle());
     }
+
+    /**
+     * Checks whether the app with the given context is authorized to manage the given subscription
+     * according to its metadata. Only supported for embedded subscriptions (if
+     * {@code SubscriptionInfo#isEmbedded} returns true).
+     *
+     * @param info The subscription to check.
+     * @return whether the app is authorized to manage this subscription per its metadata.
+     * @throws UnsupportedOperationException if this subscription is not embedded.
+     */
+    public boolean canManageSubscription(SubscriptionInfo info) {
+        return canManageSubscription(info, mContext.getPackageName());
+    }
+
+    /**
+     * Checks whether the given app is authorized to manage the given subscription according to its
+     * metadata. Only supported for embedded subscriptions (if {@code SubscriptionInfo#isEmbedded}
+     * returns true).
+     *
+     * @param info The subscription to check.
+     * @param packageName Package name of the app to check.
+     * @return whether the app is authorized to manage this subscription per its metadata.
+     * @throws UnsupportedOperationException if this subscription is not embedded.
+     * @hide
+     */
+    public boolean canManageSubscription(SubscriptionInfo info, String packageName) {
+        if (!info.isEmbedded()) {
+            throw new UnsupportedOperationException("Not an embedded subscription");
+        }
+        if (info.getAccessRules() == null) {
+            return false;
+        }
+        PackageManager packageManager = mContext.getPackageManager();
+        PackageInfo packageInfo;
+        try {
+            packageInfo = packageManager.getPackageInfo(packageName, PackageManager.GET_SIGNATURES);
+        } catch (PackageManager.NameNotFoundException e) {
+            throw new IllegalArgumentException("Unknown package: " + packageName, e);
+        }
+        for (UiccAccessRule rule : info.getAccessRules()) {
+            if (rule.getCarrierPrivilegeStatus(packageInfo)
+                    == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
+                return true;
+            }
+        }
+        return false;
+    }
 }
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 03d8b5c..7afd28c 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -4801,7 +4801,7 @@
     }
 
     /**
-     * Sets the telephony property with the value specified.
+     * Sets a per-phone telephony property with the value specified.
      *
      * @hide
      */
@@ -4851,6 +4851,20 @@
     }
 
     /**
+     * Sets a global telephony property with the value specified.
+     *
+     * @hide
+     */
+    public static void setTelephonyProperty(String property, String value) {
+        if (value == null) {
+            value = "";
+        }
+        Rlog.d(TAG, "setTelephonyProperty: success" + " property=" +
+                property + " value: " + value);
+        SystemProperties.set(property, value);
+    }
+
+    /**
      * Convenience function for retrieving a value from the secure settings
      * value list as an integer.  Note that internally setting values are
      * always stored as strings; this function converts the string to an
@@ -4939,7 +4953,7 @@
     }
 
     /**
-     * Gets the telephony property.
+     * Gets a per-phone telephony property.
      *
      * @hide
      */
@@ -4955,6 +4969,19 @@
         return propVal == null ? defaultVal : propVal;
     }
 
+    /**
+     * Gets a global telephony property.
+     *
+     * See also getTelephonyProperty(phoneId, property, defaultVal). Most telephony properties are
+     * per-phone.
+     *
+     * @hide
+     */
+    public static String getTelephonyProperty(String property, String defaultVal) {
+        String propVal = SystemProperties.get(property);
+        return propVal == null ? defaultVal : propVal;
+    }
+
     /** @hide */
     public int getSimCount() {
         // FIXME Need to get it from Telephony Dev Controller when that gets implemented!
diff --git a/telephony/java/android/telephony/UiccAccessRule.java b/telephony/java/android/telephony/UiccAccessRule.java
index 3937201..c3f8a19 100644
--- a/telephony/java/android/telephony/UiccAccessRule.java
+++ b/telephony/java/android/telephony/UiccAccessRule.java
@@ -16,6 +16,7 @@
 package android.telephony;
 
 import android.annotation.Nullable;
+import android.annotation.SystemApi;
 import android.content.pm.PackageInfo;
 import android.content.pm.Signature;
 import android.os.Parcel;
@@ -39,9 +40,8 @@
  * specification.
  *
  * @hide
- *
- * TODO(b/35851809): Make this a SystemApi.
  */
+@SystemApi
 public final class UiccAccessRule implements Parcelable {
     private static final String TAG = "UiccAccessRule";
 
diff --git a/telephony/java/android/telephony/euicc/DownloadableSubscription.java b/telephony/java/android/telephony/euicc/DownloadableSubscription.java
index 01041c8..88db22b 100644
--- a/telephony/java/android/telephony/euicc/DownloadableSubscription.java
+++ b/telephony/java/android/telephony/euicc/DownloadableSubscription.java
@@ -16,18 +16,17 @@
 package android.telephony.euicc;
 
 import android.annotation.Nullable;
+import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.telephony.UiccAccessRule;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
 
 import com.android.internal.util.Preconditions;
 
-/**
- * Information about a subscription which is available for download.
- *
- * TODO(b/35851809): Make this public.
- * @hide
- */
+/** Information about a subscription which is available for download. */
 public final class DownloadableSubscription implements Parcelable {
 
     public static final Creator<DownloadableSubscription> CREATOR =
@@ -46,11 +45,12 @@
     /**
      * Activation code. May be null for subscriptions which are not based on activation codes, e.g.
      * to download a default subscription assigned to this device.
+     * Should use getEncodedActivationCode() instead.
      * @hide
-     *
-     * TODO(b/35851809): Make this a SystemApi.
+     * @deprecated - Do not use. This will be private. Use getEncodedActivationCode() instead.
      */
     @Nullable
+    @Deprecated
     public final String encodedActivationCode;
 
     @Nullable private String confirmationCode;
@@ -58,8 +58,16 @@
     // see getCarrierName and setCarrierName
     @Nullable
     private String carrierName;
+
     // see getAccessRules and setAccessRules
-    private UiccAccessRule[] accessRules;
+    @Nullable
+    private List<UiccAccessRule> accessRules;
+
+    /** Gets the activation code. */
+    @Nullable
+    public String getEncodedActivationCode() {
+        return encodedActivationCode;
+    }
 
     /** @hide */
     private DownloadableSubscription(String encodedActivationCode) {
@@ -70,7 +78,59 @@
         encodedActivationCode = in.readString();
         confirmationCode = in.readString();
         carrierName = in.readString();
-        accessRules = in.createTypedArray(UiccAccessRule.CREATOR);
+        accessRules = new ArrayList<UiccAccessRule>();
+        in.readTypedList(accessRules, UiccAccessRule.CREATOR);
+    }
+
+    private DownloadableSubscription(String encodedActivationCode, String confirmationCode,
+            String carrierName, List<UiccAccessRule> accessRules) {
+        this.encodedActivationCode = encodedActivationCode;
+        this.confirmationCode = confirmationCode;
+        this.carrierName = carrierName;
+        this.accessRules = accessRules;
+    }
+
+    /** @hide */
+    @SystemApi
+    public static final class Builder {
+        @Nullable private String encodedActivationCode;
+        @Nullable private String confirmationCode;
+        @Nullable private String carrierName;
+        List<UiccAccessRule> accessRules;
+
+        public Builder() {}
+
+        public Builder(DownloadableSubscription baseSubscription) {
+            encodedActivationCode = baseSubscription.getEncodedActivationCode();
+            confirmationCode = baseSubscription.getConfirmationCode();
+            carrierName = baseSubscription.getCarrierName();
+            accessRules = baseSubscription.getAccessRules();
+        }
+
+        public DownloadableSubscription build() {
+            return new DownloadableSubscription(encodedActivationCode, confirmationCode,
+                    carrierName, accessRules);
+        }
+
+        public Builder setEncodedActivationCode(String value) {
+            encodedActivationCode = value;
+            return this;
+        }
+
+        public Builder setConfirmationCode(String value) {
+            confirmationCode = value;
+            return this;
+        }
+
+        public Builder setCarrierName(String value) {
+            carrierName = value;
+            return this;
+        }
+
+        public Builder setAccessRules(List<UiccAccessRule> value) {
+            accessRules = value;
+            return this;
+        }
     }
 
     /**
@@ -87,7 +147,10 @@
 
     /**
      * Sets the confirmation code.
+     * @hide
+     * @deprecated - Do not use.
      */
+    @Deprecated
     public void setConfirmationCode(String confirmationCode) {
         this.confirmationCode = confirmationCode;
     }
@@ -103,9 +166,9 @@
     /**
      * Set the user-visible carrier name.
      * @hide
-     *
-     * TODO(b/35851809): Make this a SystemApi.
+     * @deprecated - Do not use.
      */
+    @Deprecated
     public void setCarrierName(String carrierName) {
         this.carrierName = carrierName;
     }
@@ -117,44 +180,51 @@
      * those created with {@link #forActivationCode}). May be populated with
      * {@link EuiccManager#getDownloadableSubscriptionMetadata}.
      * @hide
-     *
-     * TODO(b/35851809): Make this a SystemApi.
      */
+    @SystemApi
     @Nullable
     public String getCarrierName() {
         return carrierName;
     }
 
     /**
-     * Returns the {@link UiccAccessRule}s dictating access to this subscription.
+     * Returns the {@link UiccAccessRule}s in list dictating access to this subscription.
      *
      * <p>Only present for downloadable subscriptions that were queried from a server (as opposed to
      * those created with {@link #forActivationCode}). May be populated with
      * {@link EuiccManager#getDownloadableSubscriptionMetadata}.
      * @hide
-     *
-     * TODO(b/35851809): Make this a SystemApi.
      */
-    public UiccAccessRule[] getAccessRules() {
+    @SystemApi
+    public List<UiccAccessRule> getAccessRules() {
         return accessRules;
     }
 
     /**
      * Set the {@link UiccAccessRule}s dictating access to this subscription.
      * @hide
-     *
-     * TODO(b/35851809): Make this a SystemApi.
+     * @deprecated - Do not use.
      */
-    public void setAccessRules(UiccAccessRule[] accessRules) {
+    @Deprecated
+    public void setAccessRules(List<UiccAccessRule> accessRules) {
         this.accessRules = accessRules;
     }
 
+    /**
+     * @hide
+     * @deprecated - Do not use.
+     */
+    @Deprecated
+    public void setAccessRules(UiccAccessRule[] accessRules) {
+        this.accessRules = Arrays.asList(accessRules);
+    }
+
     @Override
     public void writeToParcel(Parcel dest, int flags) {
         dest.writeString(encodedActivationCode);
         dest.writeString(confirmationCode);
         dest.writeString(carrierName);
-        dest.writeTypedArray(accessRules, flags);
+        dest.writeTypedList(accessRules);
     }
 
     @Override
diff --git a/telephony/java/android/telephony/euicc/EuiccCardManager.java b/telephony/java/android/telephony/euicc/EuiccCardManager.java
index a1a6a5a..c3f4007 100644
--- a/telephony/java/android/telephony/euicc/EuiccCardManager.java
+++ b/telephony/java/android/telephony/euicc/EuiccCardManager.java
@@ -17,6 +17,7 @@
 
 import android.annotation.IntDef;
 import android.annotation.Nullable;
+import android.annotation.SystemApi;
 import android.content.Context;
 import android.os.RemoteException;
 import android.os.ServiceManager;
@@ -49,14 +50,14 @@
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import android.annotation.CallbackExecutor;
+import java.util.concurrent.Executor;
 
 /**
  * EuiccCardManager is the application interface to an eSIM card.
- *
  * @hide
- *
- * TODO(b/35851809): Make this a SystemApi.
  */
+@SystemApi
 public class EuiccCardManager {
     private static final String TAG = "EuiccCardManager";
 
@@ -68,6 +69,7 @@
             CANCEL_REASON_TIMEOUT,
             CANCEL_REASON_PPR_NOT_ALLOWED
     })
+    /** @hide */
     public @interface CancelReason {}
 
     /**
@@ -96,6 +98,7 @@
             RESET_OPTION_DELETE_FIELD_LOADED_TEST_PROFILES,
             RESET_OPTION_RESET_DEFAULT_SMDP_ADDRESS
     })
+    /** @hide */
     public @interface ResetOption {}
 
     /** Deletes all operational profiles. */
@@ -143,18 +146,20 @@
     }
 
     /**
-     * Gets all the profiles on eUicc.
+     * Requests all the profiles on eUicc.
      *
      * @param cardId The Id of the eUICC.
+     * @param executor The executor through which the callback should be invode.
      * @param callback The callback to get the result code and all the profiles.
      */
-    public void getAllProfiles(String cardId, ResultCallback<EuiccProfileInfo[]> callback) {
+    public void requestAllProfiles(String cardId, @CallbackExecutor Executor executor,
+            ResultCallback<EuiccProfileInfo[]> callback) {
         try {
             getIEuiccCardController().getAllProfiles(mContext.getOpPackageName(), cardId,
                     new IGetAllProfilesCallback.Stub() {
                         @Override
                         public void onComplete(int resultCode, EuiccProfileInfo[] profiles) {
-                            callback.onComplete(resultCode, profiles);
+                            executor.execute(() -> callback.onComplete(resultCode, profiles));
                         }
                     });
         } catch (RemoteException e) {
@@ -164,19 +169,21 @@
     }
 
     /**
-     * Gets the profile of the given iccid.
+     * Requests the profile of the given iccid.
      *
      * @param cardId The Id of the eUICC.
      * @param iccid The iccid of the profile.
+     * @param executor The executor through which the callback should be invode.
      * @param callback The callback to get the result code and profile.
      */
-    public void getProfile(String cardId, String iccid, ResultCallback<EuiccProfileInfo> callback) {
+    public void requestProfile(String cardId, String iccid, @CallbackExecutor Executor executor,
+            ResultCallback<EuiccProfileInfo> callback) {
         try {
             getIEuiccCardController().getProfile(mContext.getOpPackageName(), cardId, iccid,
                     new IGetProfileCallback.Stub() {
                         @Override
                         public void onComplete(int resultCode, EuiccProfileInfo profile) {
-                            callback.onComplete(resultCode, profile);
+                            executor.execute(() -> callback.onComplete(resultCode, profile));
                         }
                     });
         } catch (RemoteException e) {
@@ -191,16 +198,17 @@
      * @param cardId The Id of the eUICC.
      * @param iccid The iccid of the profile.
      * @param refresh Whether sending the REFRESH command to modem.
+     * @param executor The executor through which the callback should be invode.
      * @param callback The callback to get the result code.
      */
     public void disableProfile(String cardId, String iccid, boolean refresh,
-            ResultCallback<Void> callback) {
+            @CallbackExecutor Executor executor, ResultCallback<Void> callback) {
         try {
             getIEuiccCardController().disableProfile(mContext.getOpPackageName(), cardId, iccid,
                     refresh, new IDisableProfileCallback.Stub() {
                         @Override
                         public void onComplete(int resultCode) {
-                            callback.onComplete(resultCode, null);
+                            executor.execute(() -> callback.onComplete(resultCode, null));
                         }
                     });
         } catch (RemoteException e) {
@@ -216,16 +224,17 @@
      * @param cardId The Id of the eUICC.
      * @param iccid The iccid of the profile to switch to.
      * @param refresh Whether sending the REFRESH command to modem.
+     * @param executor The executor through which the callback should be invode.
      * @param callback The callback to get the result code and the EuiccProfileInfo enabled.
      */
     public void switchToProfile(String cardId, String iccid, boolean refresh,
-            ResultCallback<EuiccProfileInfo> callback) {
+            @CallbackExecutor Executor executor, ResultCallback<EuiccProfileInfo> callback) {
         try {
             getIEuiccCardController().switchToProfile(mContext.getOpPackageName(), cardId, iccid,
                     refresh, new ISwitchToProfileCallback.Stub() {
                         @Override
                         public void onComplete(int resultCode, EuiccProfileInfo profile) {
-                            callback.onComplete(resultCode, profile);
+                            executor.execute(() -> callback.onComplete(resultCode, profile));
                         }
                     });
         } catch (RemoteException e) {
@@ -240,16 +249,17 @@
      * @param cardId The Id of the eUICC.
      * @param iccid The iccid of the profile.
      * @param nickname The nickname of the profile.
+     * @param executor The executor through which the callback should be invode.
      * @param callback The callback to get the result code.
      */
     public void setNickname(String cardId, String iccid, String nickname,
-            ResultCallback<Void> callback) {
+            @CallbackExecutor Executor executor, ResultCallback<Void> callback) {
         try {
             getIEuiccCardController().setNickname(mContext.getOpPackageName(), cardId, iccid,
                     nickname, new ISetNicknameCallback.Stub() {
                         @Override
                         public void onComplete(int resultCode) {
-                            callback.onComplete(resultCode, null);
+                            executor.execute(() -> callback.onComplete(resultCode, null));
                         }
                     });
         } catch (RemoteException e) {
@@ -263,15 +273,17 @@
      *
      * @param cardId The Id of the eUICC.
      * @param iccid The iccid of the profile.
+     * @param executor The executor through which the callback should be invode.
      * @param callback The callback to get the result code.
      */
-    public void deleteProfile(String cardId, String iccid, ResultCallback<Void> callback) {
+    public void deleteProfile(String cardId, String iccid, @CallbackExecutor Executor executor,
+            ResultCallback<Void> callback) {
         try {
             getIEuiccCardController().deleteProfile(mContext.getOpPackageName(), cardId, iccid,
                     new IDeleteProfileCallback.Stub() {
                         @Override
                         public void onComplete(int resultCode) {
-                            callback.onComplete(resultCode, null);
+                            executor.execute(() -> callback.onComplete(resultCode, null));
                         }
                     });
         } catch (RemoteException e) {
@@ -286,15 +298,17 @@
      * @param cardId The Id of the eUICC.
      * @param options Bits of the options of resetting which parts of the eUICC memory. See
      *     EuiccCard for details.
+     * @param executor The executor through which the callback should be invode.
      * @param callback The callback to get the result code.
      */
-    public void resetMemory(String cardId, @ResetOption int options, ResultCallback<Void> callback) {
+    public void resetMemory(String cardId, @ResetOption int options,
+            @CallbackExecutor Executor executor, ResultCallback<Void> callback) {
         try {
             getIEuiccCardController().resetMemory(mContext.getOpPackageName(), cardId, options,
                     new IResetMemoryCallback.Stub() {
                         @Override
                         public void onComplete(int resultCode) {
-                            callback.onComplete(resultCode, null);
+                            executor.execute(() -> callback.onComplete(resultCode, null));
                         }
                     });
         } catch (RemoteException e) {
@@ -304,18 +318,20 @@
     }
 
     /**
-     * Gets the default SM-DP+ address from eUICC.
+     * Requests the default SM-DP+ address from eUICC.
      *
      * @param cardId The Id of the eUICC.
+     * @param executor The executor through which the callback should be invode.
      * @param callback The callback to get the result code and the default SM-DP+ address.
      */
-    public void getDefaultSmdpAddress(String cardId, ResultCallback<String> callback) {
+    public void requestDefaultSmdpAddress(String cardId, @CallbackExecutor Executor executor,
+            ResultCallback<String> callback) {
         try {
             getIEuiccCardController().getDefaultSmdpAddress(mContext.getOpPackageName(), cardId,
                     new IGetDefaultSmdpAddressCallback.Stub() {
                         @Override
                         public void onComplete(int resultCode, String address) {
-                            callback.onComplete(resultCode, address);
+                            executor.execute(() -> callback.onComplete(resultCode, address));
                         }
                     });
         } catch (RemoteException e) {
@@ -325,18 +341,20 @@
     }
 
     /**
-     * Gets the SM-DS address from eUICC.
+     * Requests the SM-DS address from eUICC.
      *
      * @param cardId The Id of the eUICC.
+     * @param executor The executor through which the callback should be invode.
      * @param callback The callback to get the result code and the SM-DS address.
      */
-    public void getSmdsAddress(String cardId, ResultCallback<String> callback) {
+    public void requestSmdsAddress(String cardId, @CallbackExecutor Executor executor,
+            ResultCallback<String> callback) {
         try {
             getIEuiccCardController().getSmdsAddress(mContext.getOpPackageName(), cardId,
                     new IGetSmdsAddressCallback.Stub() {
                         @Override
                         public void onComplete(int resultCode, String address) {
-                            callback.onComplete(resultCode, address);
+                            executor.execute(() -> callback.onComplete(resultCode, address));
                         }
                     });
         } catch (RemoteException e) {
@@ -350,16 +368,18 @@
      *
      * @param cardId The Id of the eUICC.
      * @param defaultSmdpAddress The default SM-DP+ address to set.
+     * @param executor The executor through which the callback should be invode.
      * @param callback The callback to get the result code.
      */
-    public void setDefaultSmdpAddress(String cardId, String defaultSmdpAddress, ResultCallback<Void> callback) {
+    public void setDefaultSmdpAddress(String cardId, String defaultSmdpAddress,
+            @CallbackExecutor Executor executor, ResultCallback<Void> callback) {
         try {
             getIEuiccCardController().setDefaultSmdpAddress(mContext.getOpPackageName(), cardId,
                     defaultSmdpAddress,
                     new ISetDefaultSmdpAddressCallback.Stub() {
                         @Override
                         public void onComplete(int resultCode) {
-                            callback.onComplete(resultCode, null);
+                            executor.execute(() -> callback.onComplete(resultCode, null));
                         }
                     });
         } catch (RemoteException e) {
@@ -369,18 +389,20 @@
     }
 
     /**
-     * Gets Rules Authorisation Table.
+     * Requests Rules Authorisation Table.
      *
      * @param cardId The Id of the eUICC.
+     * @param executor The executor through which the callback should be invode.
      * @param callback the callback to get the result code and the rule authorisation table.
      */
-    public void getRulesAuthTable(String cardId, ResultCallback<EuiccRulesAuthTable> callback) {
+    public void requestRulesAuthTable(String cardId, @CallbackExecutor Executor executor,
+            ResultCallback<EuiccRulesAuthTable> callback) {
         try {
             getIEuiccCardController().getRulesAuthTable(mContext.getOpPackageName(), cardId,
                     new IGetRulesAuthTableCallback.Stub() {
                         @Override
                         public void onComplete(int resultCode, EuiccRulesAuthTable rat) {
-                            callback.onComplete(resultCode, rat);
+                            executor.execute(() -> callback.onComplete(resultCode, rat));
                         }
                     });
         } catch (RemoteException e) {
@@ -390,18 +412,20 @@
     }
 
     /**
-     * Gets the eUICC challenge for new profile downloading.
+     * Requests the eUICC challenge for new profile downloading.
      *
      * @param cardId The Id of the eUICC.
+     * @param executor The executor through which the callback should be invode.
      * @param callback the callback to get the result code and the challenge.
      */
-    public void getEuiccChallenge(String cardId, ResultCallback<byte[]> callback) {
+    public void requestEuiccChallenge(String cardId, @CallbackExecutor Executor executor,
+            ResultCallback<byte[]> callback) {
         try {
             getIEuiccCardController().getEuiccChallenge(mContext.getOpPackageName(), cardId,
                     new IGetEuiccChallengeCallback.Stub() {
                         @Override
                         public void onComplete(int resultCode, byte[] challenge) {
-                            callback.onComplete(resultCode, challenge);
+                            executor.execute(() -> callback.onComplete(resultCode, challenge));
                         }
                     });
         } catch (RemoteException e) {
@@ -411,18 +435,20 @@
     }
 
     /**
-     * Gets the eUICC info1 defined in GSMA RSP v2.0+ for new profile downloading.
+     * Requests the eUICC info1 defined in GSMA RSP v2.0+ for new profile downloading.
      *
      * @param cardId The Id of the eUICC.
+     * @param executor The executor through which the callback should be invode.
      * @param callback the callback to get the result code and the info1.
      */
-    public void getEuiccInfo1(String cardId, ResultCallback<byte[]> callback) {
+    public void requestEuiccInfo1(String cardId, @CallbackExecutor Executor executor,
+            ResultCallback<byte[]> callback) {
         try {
             getIEuiccCardController().getEuiccInfo1(mContext.getOpPackageName(), cardId,
                     new IGetEuiccInfo1Callback.Stub() {
                         @Override
                         public void onComplete(int resultCode, byte[] info) {
-                            callback.onComplete(resultCode, info);
+                            executor.execute(() -> callback.onComplete(resultCode, info));
                         }
                     });
         } catch (RemoteException e) {
@@ -435,15 +461,17 @@
      * Gets the eUICC info2 defined in GSMA RSP v2.0+ for new profile downloading.
      *
      * @param cardId The Id of the eUICC.
+     * @param executor The executor through which the callback should be invode.
      * @param callback the callback to get the result code and the info2.
      */
-    public void getEuiccInfo2(String cardId, ResultCallback<byte[]> callback) {
+    public void requestEuiccInfo2(String cardId, @CallbackExecutor Executor executor,
+            ResultCallback<byte[]> callback) {
         try {
             getIEuiccCardController().getEuiccInfo2(mContext.getOpPackageName(), cardId,
                     new IGetEuiccInfo2Callback.Stub() {
                         @Override
                         public void onComplete(int resultCode, byte[] info) {
-                            callback.onComplete(resultCode, info);
+                            executor.execute(() -> callback.onComplete(resultCode, info));
                         }
                     });
         } catch (RemoteException e) {
@@ -466,12 +494,13 @@
      *     GSMA RSP v2.0+.
      * @param serverCertificate ASN.1 data in byte array indicating SM-DP+ Certificate returned by
      *     SM-DP+ server.
+     * @param executor The executor through which the callback should be invode.
      * @param callback the callback to get the result code and a byte array which represents a
      *     {@code AuthenticateServerResponse} defined in GSMA RSP v2.0+.
      */
     public void authenticateServer(String cardId, String matchingId, byte[] serverSigned1,
             byte[] serverSignature1, byte[] euiccCiPkIdToBeUsed, byte[] serverCertificate,
-            ResultCallback<byte[]> callback) {
+            @CallbackExecutor Executor executor, ResultCallback<byte[]> callback) {
         try {
             getIEuiccCardController().authenticateServer(
                     mContext.getOpPackageName(),
@@ -484,7 +513,7 @@
                     new IAuthenticateServerCallback.Stub() {
                         @Override
                         public void onComplete(int resultCode, byte[] response) {
-                            callback.onComplete(resultCode, response);
+                            executor.execute(() -> callback.onComplete(resultCode, response));
                         }
                     });
         } catch (RemoteException e) {
@@ -505,11 +534,13 @@
      *     SM-DP+ server.
      * @param smdpCertificate ASN.1 data in byte array indicating the SM-DP+ Certificate returned
      *     by SM-DP+ server.
+     * @param executor The executor through which the callback should be invode.
      * @param callback the callback to get the result code and a byte array which represents a
      *     {@code PrepareDownloadResponse} defined in GSMA RSP v2.0+
      */
     public void prepareDownload(String cardId, @Nullable byte[] hashCc, byte[] smdpSigned2,
-            byte[] smdpSignature2, byte[] smdpCertificate, ResultCallback<byte[]> callback) {
+            byte[] smdpSignature2, byte[] smdpCertificate, @CallbackExecutor Executor executor,
+            ResultCallback<byte[]> callback) {
         try {
             getIEuiccCardController().prepareDownload(
                     mContext.getOpPackageName(),
@@ -521,7 +552,7 @@
                     new IPrepareDownloadCallback.Stub() {
                         @Override
                         public void onComplete(int resultCode, byte[] response) {
-                            callback.onComplete(resultCode, response);
+                            executor.execute(() -> callback.onComplete(resultCode, response));
                         }
                     });
         } catch (RemoteException e) {
@@ -535,11 +566,12 @@
      *
      * @param cardId The Id of the eUICC.
      * @param boundProfilePackage the Bound Profile Package data returned by SM-DP+ server.
+     * @param executor The executor through which the callback should be invode.
      * @param callback the callback to get the result code and a byte array which represents a
      *     {@code LoadBoundProfilePackageResponse} defined in GSMA RSP v2.0+.
      */
     public void loadBoundProfilePackage(String cardId, byte[] boundProfilePackage,
-            ResultCallback<byte[]> callback) {
+            @CallbackExecutor Executor executor, ResultCallback<byte[]> callback) {
         try {
             getIEuiccCardController().loadBoundProfilePackage(
                     mContext.getOpPackageName(),
@@ -548,7 +580,7 @@
                     new ILoadBoundProfilePackageCallback.Stub() {
                         @Override
                         public void onComplete(int resultCode, byte[] response) {
-                            callback.onComplete(resultCode, response);
+                            executor.execute(() -> callback.onComplete(resultCode, response));
                         }
                     });
         } catch (RemoteException e) {
@@ -563,11 +595,12 @@
      * @param cardId The Id of the eUICC.
      * @param transactionId the transaction ID returned by SM-DP+ server.
      * @param reason the cancel reason.
+     * @param executor The executor through which the callback should be invode.
      * @param callback the callback to get the result code and an byte[] which represents a
      *     {@code CancelSessionResponse} defined in GSMA RSP v2.0+.
      */
     public void cancelSession(String cardId, byte[] transactionId, @CancelReason int reason,
-            ResultCallback<byte[]> callback) {
+            @CallbackExecutor Executor executor, ResultCallback<byte[]> callback) {
         try {
             getIEuiccCardController().cancelSession(
                     mContext.getOpPackageName(),
@@ -577,7 +610,7 @@
                     new ICancelSessionCallback.Stub() {
                         @Override
                         public void onComplete(int resultCode, byte[] response) {
-                            callback.onComplete(resultCode, response);
+                            executor.execute(() -> callback.onComplete(resultCode, response));
                         }
                     });
         } catch (RemoteException e) {
@@ -591,16 +624,17 @@
      *
      * @param cardId The Id of the eUICC.
      * @param events bits of the event types ({@link EuiccNotification.Event}) to list.
+     * @param executor The executor through which the callback should be invode.
      * @param callback the callback to get the result code and the list of notifications.
      */
     public void listNotifications(String cardId, @EuiccNotification.Event int events,
-            ResultCallback<EuiccNotification[]> callback) {
+            @CallbackExecutor Executor executor, ResultCallback<EuiccNotification[]> callback) {
         try {
             getIEuiccCardController().listNotifications(mContext.getOpPackageName(), cardId, events,
                     new IListNotificationsCallback.Stub() {
                         @Override
                         public void onComplete(int resultCode, EuiccNotification[] notifications) {
-                            callback.onComplete(resultCode, notifications);
+                            executor.execute(() -> callback.onComplete(resultCode, notifications));
                         }
                     });
         } catch (RemoteException e) {
@@ -614,16 +648,17 @@
      *
      * @param cardId The Id of the eUICC.
      * @param events bits of the event types ({@link EuiccNotification.Event}) to list.
+     * @param executor The executor through which the callback should be invode.
      * @param callback the callback to get the result code and the list of notifications.
      */
     public void retrieveNotificationList(String cardId, @EuiccNotification.Event int events,
-            ResultCallback<EuiccNotification[]> callback) {
+            @CallbackExecutor Executor executor, ResultCallback<EuiccNotification[]> callback) {
         try {
             getIEuiccCardController().retrieveNotificationList(mContext.getOpPackageName(), cardId,
                     events, new IRetrieveNotificationListCallback.Stub() {
                         @Override
                         public void onComplete(int resultCode, EuiccNotification[] notifications) {
-                            callback.onComplete(resultCode, notifications);
+                            executor.execute(() -> callback.onComplete(resultCode, notifications));
                         }
                     });
         } catch (RemoteException e) {
@@ -637,16 +672,17 @@
      *
      * @param cardId The Id of the eUICC.
      * @param seqNumber the sequence number of the notification.
+     * @param executor The executor through which the callback should be invode.
      * @param callback the callback to get the result code and the notification.
      */
     public void retrieveNotification(String cardId, int seqNumber,
-            ResultCallback<EuiccNotification> callback) {
+            @CallbackExecutor Executor executor, ResultCallback<EuiccNotification> callback) {
         try {
             getIEuiccCardController().retrieveNotification(mContext.getOpPackageName(), cardId,
                     seqNumber, new IRetrieveNotificationCallback.Stub() {
                         @Override
                         public void onComplete(int resultCode, EuiccNotification notification) {
-                            callback.onComplete(resultCode, notification);
+                            executor.execute(() -> callback.onComplete(resultCode, notification));
                         }
                     });
         } catch (RemoteException e) {
@@ -660,10 +696,11 @@
      *
      * @param cardId The Id of the eUICC.
      * @param seqNumber the sequence number of the notification.
+     * @param executor The executor through which the callback should be invode.
      * @param callback the callback to get the result code.
      */
     public void removeNotificationFromList(String cardId, int seqNumber,
-            ResultCallback<Void> callback) {
+            @CallbackExecutor Executor executor, ResultCallback<Void> callback) {
         try {
             getIEuiccCardController().removeNotificationFromList(
                     mContext.getOpPackageName(),
@@ -672,7 +709,7 @@
                     new IRemoveNotificationFromListCallback.Stub() {
                         @Override
                         public void onComplete(int resultCode) {
-                            callback.onComplete(resultCode, null);
+                            executor.execute(() -> callback.onComplete(resultCode, null));
                         }
                     });
         } catch (RemoteException e) {
diff --git a/telephony/java/android/telephony/euicc/EuiccInfo.java b/telephony/java/android/telephony/euicc/EuiccInfo.java
index 5bfff08..a4adf05 100644
--- a/telephony/java/android/telephony/euicc/EuiccInfo.java
+++ b/telephony/java/android/telephony/euicc/EuiccInfo.java
@@ -23,9 +23,6 @@
  * Information about an eUICC chip/device.
  *
  * @see EuiccManager#getEuiccInfo
- * @hide
- *
- * TODO(b/35851809): Make this public.
  */
 // WARNING: Do not add any privacy-sensitive fields to this class (such as an eUICC identifier)!
 // This API is accessible to all applications. Privacy-sensitive fields should be returned in their
@@ -45,12 +42,17 @@
                 }
             };
 
+    @Nullable
+    private final String osVersion;
+
     /**
-     * Version of the operating system running on the eUICC. This field is hardware-specific and is
-     * not guaranteed to match any particular format.
+     * Gets the version of the operating system running on the eUICC. This field is
+     * hardware-specific and is not guaranteed to match any particular format.
      */
     @Nullable
-    public final String osVersion;
+    public String getOsVersion() {
+        return osVersion;
+    }
 
     public EuiccInfo(@Nullable String osVersion) {
         this.osVersion = osVersion;
diff --git a/telephony/java/android/telephony/euicc/EuiccManager.java b/telephony/java/android/telephony/euicc/EuiccManager.java
index 7f913ce..1637c55 100644
--- a/telephony/java/android/telephony/euicc/EuiccManager.java
+++ b/telephony/java/android/telephony/euicc/EuiccManager.java
@@ -42,9 +42,6 @@
  * {@link Context#getSystemService(String)} and {@link Context#EUICC_SERVICE}.
  *
  * <p>See {@link #isEnabled} before attempting to use these APIs.
- *
- * TODO(b/35851809): Make this public.
- * @hide
  */
 public class EuiccManager {
 
@@ -56,6 +53,8 @@
      *
      * <p>The activity will immediately finish with {@link android.app.Activity#RESULT_CANCELED} if
      * {@link #isEnabled} is false.
+     *
+     * This is ued by non-LPA app to bring up LUI.
      */
     @SdkConstant(SdkConstant.SdkConstantType.ACTIVITY_INTENT_ACTION)
     public static final String ACTION_MANAGE_EMBEDDED_SUBSCRIPTIONS =
@@ -69,8 +68,10 @@
      *
      * <p class="note">This is a protected intent that can only be sent
      * by the system.
-     * TODO(b/35851809): Make this a SystemApi.
+     *
+     * @hide
      */
+    @SystemApi
     @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String ACTION_OTA_STATUS_CHANGED =
             "android.telephony.euicc.action.OTA_STATUS_CHANGED";
@@ -78,12 +79,10 @@
     /**
      * Broadcast Action: The action sent to carrier app so it knows the carrier setup is not
      * completed.
-     *
-     * TODO(b/35851809): Make this a public API.
      */
     @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String ACTION_NOTIFY_CARRIER_SETUP =
-            "android.telephony.euicc.action.NOTIFY_CARRIER_SETUP";
+    public static final String ACTION_NOTIFY_CARRIER_SETUP_INCOMPLETE =
+            "android.telephony.euicc.action.NOTIFY_CARRIER_SETUP_INCOMPLETE";
 
     /**
      * Intent action to provision an embedded subscription.
@@ -95,8 +94,9 @@
      * <p>The activity will immediately finish with {@link android.app.Activity#RESULT_CANCELED} if
      * {@link #isEnabled} is false.
      *
-     * TODO(b/35851809): Make this a SystemApi.
+     * @hide
      */
+    @SystemApi
     @SdkConstant(SdkConstant.SdkConstantType.ACTIVITY_INTENT_ACTION)
     public static final String ACTION_PROVISION_EMBEDDED_SUBSCRIPTION =
             "android.telephony.euicc.action.PROVISION_EMBEDDED_SUBSCRIPTION";
@@ -143,9 +143,8 @@
      * Key for an extra set on {@link #getDownloadableSubscriptionMetadata} PendingIntent result
      * callbacks providing the downloadable subscription metadata.
      * @hide
-     *
-     * TODO(b/35851809): Make this a SystemApi.
      */
+    @SystemApi
     public static final String EXTRA_EMBEDDED_SUBSCRIPTION_DOWNLOADABLE_SUBSCRIPTION =
             "android.telephony.euicc.extra.EMBEDDED_SUBSCRIPTION_DOWNLOADABLE_SUBSCRIPTION";
 
@@ -153,9 +152,8 @@
      * Key for an extra set on {@link #getDefaultDownloadableSubscriptionList} PendingIntent result
      * callbacks providing the list of available downloadable subscriptions.
      * @hide
-     *
-     * TODO(b/35851809): Make this a SystemApi.
      */
+    @SystemApi
     public static final String EXTRA_EMBEDDED_SUBSCRIPTION_DOWNLOADABLE_SUBSCRIPTIONS =
             "android.telephony.euicc.extra.EMBEDDED_SUBSCRIPTION_DOWNLOADABLE_SUBSCRIPTIONS";
 
@@ -201,6 +199,7 @@
      * Euicc OTA update status which can be got by {@link #getOtaStatus}
      * @hide
      */
+    @SystemApi
     @Retention(RetentionPolicy.SOURCE)
     @IntDef(prefix = {"EUICC_OTA_"}, value = {
             EUICC_OTA_IN_PROGRESS,
@@ -215,15 +214,37 @@
     /**
      * An OTA is in progress. During this time, the eUICC is not available and the user may lose
      * network access.
+     * @hide
      */
+    @SystemApi
     public static final int EUICC_OTA_IN_PROGRESS = 1;
-    /** The OTA update failed. */
+
+    /**
+     * The OTA update failed.
+     * @hide
+     */
+    @SystemApi
     public static final int EUICC_OTA_FAILED = 2;
-    /** The OTA update finished successfully. */
+
+    /**
+     * The OTA update finished successfully.
+     * @hide
+     */
+    @SystemApi
     public static final int EUICC_OTA_SUCCEEDED = 3;
-    /** The OTA update not needed since current eUICC OS is latest. */
+
+    /**
+     * The OTA update not needed since current eUICC OS is latest.
+     * @hide
+     */
+    @SystemApi
     public static final int EUICC_OTA_NOT_NEEDED = 4;
-    /** The OTA status is unavailable since eUICC service is unavailable. */
+
+    /**
+     * The OTA status is unavailable since eUICC service is unavailable.
+     * @hide
+     */
+    @SystemApi
     public static final int EUICC_OTA_STATUS_UNAVAILABLE = 5;
 
     private final Context mContext;
@@ -276,8 +297,10 @@
      *
      * @return the status of eUICC OTA. If {@link #isEnabled()} is false or the eUICC is not ready,
      *     {@link OtaStatus#EUICC_OTA_STATUS_UNAVAILABLE} will be returned.
-     * TODO(b/35851809): Make this a SystemApi.
+     *
+     * @hide
      */
+    @SystemApi
     public int getOtaStatus() {
         if (!isEnabled()) {
             return EUICC_OTA_STATUS_UNAVAILABLE;
@@ -292,7 +315,7 @@
     /**
      * Attempt to download the given {@link DownloadableSubscription}.
      *
-     * <p>Requires the {@link android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS} permission,
+     * <p>Requires the {@code android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS} permission,
      * or the calling app must be authorized to manage both the currently-active subscription and
      * the subscription to be downloaded according to the subscription metadata. Without the former,
      * an {@link #EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR} will be returned in the callback
@@ -354,14 +377,16 @@
      *
      * <p>To be called by the LUI upon completion of a resolvable error flow.
      *
+     * <p>Requires that the calling app has the
+     * {@link android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS} permission.
+     *
      * @param resolutionIntent The original intent used to start the LUI.
      * @param resolutionExtras Resolution-specific extras depending on the result of the resolution.
      *     For example, this may indicate whether the user has consented or may include the input
      *     they provided.
      * @hide
-     *
-     * TODO(b/35851809): Make this a SystemApi.
      */
+    @SystemApi
     public void continueOperation(Intent resolutionIntent, Bundle resolutionExtras) {
         if (!isEnabled()) {
             PendingIntent callbackIntent =
@@ -395,9 +420,8 @@
      * @param subscription the subscription which needs metadata filled in
      * @param callbackIntent a PendingIntent to launch when the operation completes.
      * @hide
-     *
-     * TODO(b/35851809): Make this a SystemApi.
      */
+    @SystemApi
     public void getDownloadableSubscriptionMetadata(
             DownloadableSubscription subscription, PendingIntent callbackIntent) {
         if (!isEnabled()) {
@@ -426,9 +450,8 @@
      *
      * @param callbackIntent a PendingIntent to launch when the operation completes.
      * @hide
-     *
-     * TODO(b/35851809): Make this a SystemApi.
      */
+    @SystemApi
     public void getDefaultDownloadableSubscriptionList(PendingIntent callbackIntent) {
         if (!isEnabled()) {
             sendUnavailableError(callbackIntent);
@@ -468,7 +491,7 @@
      *
      * <p>Requires that the calling app has carrier privileges according to the metadata of the
      * profile to be deleted, or the
-     * {@link android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS} permission.
+     * {@code android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS} permission.
      *
      * @param subscriptionId the ID of the subscription to delete.
      * @param callbackIntent a PendingIntent to launch when the operation completes.
@@ -489,7 +512,7 @@
     /**
      * Switch to (enable) the given subscription.
      *
-     * <p>Requires the {@link android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS} permission,
+     * <p>Requires the {@code android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS} permission,
      * or the calling app must be authorized to manage both the currently-active subscription and
      * the subscription to be enabled according to the subscription metadata. Without the former,
      * an {@link #EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR} will be returned in the callback
@@ -599,11 +622,7 @@
         }
     }
 
-    /**
-     * @hide
-     */
-    @TestApi
-    protected IEuiccController getIEuiccController() {
+    private static IEuiccController getIEuiccController() {
         return IEuiccController.Stub.asInterface(ServiceManager.getService("econtroller"));
     }
 }
diff --git a/telephony/java/android/telephony/euicc/EuiccNotification.java b/telephony/java/android/telephony/euicc/EuiccNotification.java
index ef3c1ce..43a7707 100644
--- a/telephony/java/android/telephony/euicc/EuiccNotification.java
+++ b/telephony/java/android/telephony/euicc/EuiccNotification.java
@@ -17,6 +17,7 @@
 
 import android.annotation.IntDef;
 import android.annotation.Nullable;
+import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -31,10 +32,9 @@
  * disabling, or deleting).
  *
  * @hide
- *
- * TODO(b/35851809): Make this a @SystemApi.
  */
-public class EuiccNotification implements Parcelable {
+@SystemApi
+public final class EuiccNotification implements Parcelable {
     /** Event */
     @Retention(RetentionPolicy.SOURCE)
     @IntDef(flag = true, prefix = { "EVENT_" }, value = {
@@ -43,6 +43,7 @@
             EVENT_DISABLE,
             EVENT_DELETE
     })
+    /** @hide */
     public @interface Event {}
 
     /** A profile is downloaded and installed. */
@@ -57,7 +58,7 @@
     /** A profile is deleted. */
     public static final int EVENT_DELETE = 1 << 3;
 
-    /** Value of the bits of all above events */
+    /** Value of the bits of all the events including install, enable, disable and delete. */
     @Event
     public static final int ALL_EVENTS =
             EVENT_INSTALL | EVENT_ENABLE | EVENT_DISABLE | EVENT_DELETE;
diff --git a/telephony/java/android/telephony/euicc/EuiccRulesAuthTable.java b/telephony/java/android/telephony/euicc/EuiccRulesAuthTable.java
index 7efe043..67ae983 100644
--- a/telephony/java/android/telephony/euicc/EuiccRulesAuthTable.java
+++ b/telephony/java/android/telephony/euicc/EuiccRulesAuthTable.java
@@ -16,6 +16,7 @@
 package android.telephony.euicc;
 
 import android.annotation.IntDef;
+import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.service.carrier.CarrierIdentifier;
@@ -27,20 +28,21 @@
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.List;
 
 /**
  * This represents the RAT (Rules Authorisation Table) stored on eUICC.
- *
  * @hide
- *
- * TODO(b/35851809): Make this a @SystemApi.
  */
+@SystemApi
 public final class EuiccRulesAuthTable implements Parcelable {
     /** Profile policy rule flags */
     @Retention(RetentionPolicy.SOURCE)
     @IntDef(flag = true, prefix = { "POLICY_RULE_FLAG_" }, value = {
             POLICY_RULE_FLAG_CONSENT_REQUIRED
     })
+    /** @hide */
     public @interface PolicyRuleFlag {}
 
     /** User consent is required to install the profile. */
@@ -89,12 +91,14 @@
          * @throws ArrayIndexOutOfBoundsException If the {@code mPosition} is larger than the size
          *     this table.
          */
-        public Builder add(int policyRules, CarrierIdentifier[] carrierId, int policyRuleFlags) {
+        public Builder add(int policyRules, List<CarrierIdentifier> carrierId, int policyRuleFlags) {
             if (mPosition >= mPolicyRules.length) {
                 throw new ArrayIndexOutOfBoundsException(mPosition);
             }
             mPolicyRules[mPosition] = policyRules;
-            mCarrierIds[mPosition] = carrierId;
+            if (carrierId != null && carrierId.size() > 0) {
+                mCarrierIds[mPosition] = carrierId.toArray(new CarrierIdentifier[carrierId.size()]);
+            }
             mPolicyRuleFlags[mPosition] = policyRuleFlags;
             mPosition++;
             return this;
diff --git a/tests/ActivityManagerPerfTests/test-app/AndroidManifest.xml b/tests/ActivityManagerPerfTests/test-app/AndroidManifest.xml
index ec5a9c6..23a151c 100644
--- a/tests/ActivityManagerPerfTests/test-app/AndroidManifest.xml
+++ b/tests/ActivityManagerPerfTests/test-app/AndroidManifest.xml
@@ -32,5 +32,8 @@
                 <category android:name="android.intent.category.DEFAULT" />
             </intent-filter>
         </receiver>
+        <service
+                android:name=".TestService"
+                android:exported="true" />
     </application>
 </manifest>
diff --git a/tests/ActivityManagerPerfTests/test-app/src/com/android/frameworks/perftests/amteststestapp/TestActivity.java b/tests/ActivityManagerPerfTests/test-app/src/com/android/frameworks/perftests/amteststestapp/TestActivity.java
index 1f06121..4e7bb4c 100644
--- a/tests/ActivityManagerPerfTests/test-app/src/com/android/frameworks/perftests/amteststestapp/TestActivity.java
+++ b/tests/ActivityManagerPerfTests/test-app/src/com/android/frameworks/perftests/amteststestapp/TestActivity.java
@@ -18,7 +18,6 @@
 
 import android.app.Activity;
 import android.os.Looper;
-import android.os.MessageQueue;
 
 import com.android.frameworks.perftests.am.util.Constants;
 import com.android.frameworks.perftests.am.util.Utils;
diff --git a/tests/ActivityManagerPerfTests/test-app/src/com/android/frameworks/perftests/amteststestapp/TestService.java b/tests/ActivityManagerPerfTests/test-app/src/com/android/frameworks/perftests/amteststestapp/TestService.java
new file mode 100644
index 0000000..b6534fc
--- /dev/null
+++ b/tests/ActivityManagerPerfTests/test-app/src/com/android/frameworks/perftests/amteststestapp/TestService.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.android.frameworks.perftests.amteststestapp;
+
+import android.app.Service;
+import android.content.Intent;
+import android.os.Binder;
+import android.os.IBinder;
+
+import com.android.frameworks.perftests.am.util.Constants;
+import com.android.frameworks.perftests.am.util.Utils;
+
+public class TestService extends Service {
+    @Override
+    public IBinder onBind(Intent intent) {
+        return new Binder();
+    }
+
+    @Override
+    public int onStartCommand(Intent intent, int flags, int startId) {
+        Utils.sendTime(intent, Constants.TYPE_SERVICE_START);
+        return super.onStartCommand(intent, flags, startId);
+    }
+}
diff --git a/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/tests/BasePerfTest.java b/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/tests/BasePerfTest.java
index 661abe9..cf175e0 100644
--- a/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/tests/BasePerfTest.java
+++ b/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/tests/BasePerfTest.java
@@ -16,8 +16,11 @@
 
 package com.android.frameworks.perftests.am.tests;
 
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.IBinder;
 import android.perftests.utils.ManualBenchmarkState;
 import android.perftests.utils.PerfManualStatusReporter;
 import android.support.test.InstrumentationRegistry;
@@ -26,13 +29,17 @@
 import com.android.frameworks.perftests.am.util.TimeReceiver;
 
 import org.junit.After;
+import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Rule;
 
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
 import java.util.function.LongSupplier;
 
 public class BasePerfTest {
     private static final String TAG = BasePerfTest.class.getSimpleName();
+    private static final long AWAIT_SERVICE_CONNECT_MS = 2000;
 
     private TimeReceiver mTimeReceiver;
 
@@ -52,14 +59,70 @@
         TargetPackageUtils.killTargetPackage(mContext);
     }
 
-    protected Intent createIntent(String action) {
+    protected void addReceivedTimeNs(String type) {
+        mTimeReceiver.addTimeForTypeToQueue(type, System.nanoTime());
+    }
+
+    protected Intent createServiceIntent() {
+        final Intent intent = new Intent();
+        intent.setClassName(TargetPackageUtils.PACKAGE_NAME,
+                TargetPackageUtils.SERVICE_NAME);
+        putTimeReceiverBinderExtra(intent);
+        return intent;
+    }
+
+    protected ServiceConnection bindAndWaitForConnectedService() {
+        return bindAndWaitForConnectedService(0);
+    }
+
+    protected ServiceConnection bindAndWaitForConnectedService(int flags) {
+        CountDownLatch countDownLatch = new CountDownLatch(1);
+        final ServiceConnection serviceConnection = new ServiceConnection() {
+            @Override
+            public void onServiceConnected(ComponentName name, IBinder service) {
+                countDownLatch.countDown();
+            }
+
+            @Override
+            public void onServiceDisconnected(ComponentName name) {
+            }
+        };
+
+        final Intent intent = createServiceIntent();
+        final boolean success = mContext.bindService(intent, serviceConnection,
+                Context.BIND_AUTO_CREATE | flags);
+        Assert.assertTrue("Could not bind to service", success);
+
+        try {
+            boolean connectedSuccess = countDownLatch.await(AWAIT_SERVICE_CONNECT_MS,
+                    TimeUnit.MILLISECONDS);
+            Assert.assertTrue("Timeout when waiting for ServiceConnection.onServiceConnected()",
+                    connectedSuccess);
+        } catch (InterruptedException e) {
+            throw new RuntimeException(e);
+        }
+
+        return serviceConnection;
+    }
+
+    protected void unbindFromService(ServiceConnection serviceConnection) {
+        if (serviceConnection != null) {
+            mContext.unbindService(serviceConnection);
+        }
+    }
+
+    protected Intent createBroadcastIntent(String action) {
         final Intent intent = new Intent(action);
         intent.addFlags(
                 Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND | Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
-        intent.putExtras(mTimeReceiver.createReceiveTimeExtraBinder());
+        putTimeReceiverBinderExtra(intent);
         return intent;
     }
 
+    protected void putTimeReceiverBinderExtra(Intent intent) {
+        intent.putExtras(mTimeReceiver.createReceiveTimeExtraBinder());
+    }
+
     private void setUpIteration() {
         mTimeReceiver.clear();
         TargetPackageUtils.killTargetPackage(mContext);
diff --git a/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/tests/BroadcastPerfTest.java b/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/tests/BroadcastPerfTest.java
index 795f498..f7dab03 100644
--- a/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/tests/BroadcastPerfTest.java
+++ b/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/tests/BroadcastPerfTest.java
@@ -33,7 +33,8 @@
         runPerfFunction(() -> {
             startTargetPackage();
 
-            final Intent intent = createIntent(Constants.ACTION_BROADCAST_MANIFEST_RECEIVE);
+            final Intent intent = createBroadcastIntent(
+                    Constants.ACTION_BROADCAST_MANIFEST_RECEIVE);
 
             final long startTime = System.nanoTime();
 
@@ -48,7 +49,8 @@
     @Test
     public void manifestBroadcastNotRunning() {
         runPerfFunction(() -> {
-            final Intent intent = createIntent(Constants.ACTION_BROADCAST_MANIFEST_RECEIVE);
+            final Intent intent = createBroadcastIntent(
+                    Constants.ACTION_BROADCAST_MANIFEST_RECEIVE);
 
             final long startTime = System.nanoTime();
 
@@ -65,7 +67,8 @@
         runPerfFunction(() -> {
             startTargetPackage();
 
-            final Intent intent = createIntent(Constants.ACTION_BROADCAST_REGISTERED_RECEIVE);
+            final Intent intent = createBroadcastIntent(
+                    Constants.ACTION_BROADCAST_REGISTERED_RECEIVE);
 
             final long startTime = System.nanoTime();
 
diff --git a/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/tests/ServiceBindPerfTest.java b/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/tests/ServiceBindPerfTest.java
new file mode 100644
index 0000000..6d2935a
--- /dev/null
+++ b/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/tests/ServiceBindPerfTest.java
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.android.frameworks.perftests.am.tests;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.IBinder;
+import android.support.test.filters.LargeTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import com.android.frameworks.perftests.am.util.Constants;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@LargeTest
+public class ServiceBindPerfTest extends BasePerfTest {
+    /**
+     * Create and return a ServiceConnection that will add the current time with type
+     * Constants.TYPE_SERVICE_CONNECTED.
+     */
+    private ServiceConnection createServiceConnectionReportTime() {
+        return new ServiceConnection() {
+            @Override
+            public void onServiceConnected(ComponentName name, IBinder service) {
+                addReceivedTimeNs(Constants.TYPE_SERVICE_CONNECTED);
+            }
+
+            @Override
+            public void onServiceDisconnected(ComponentName name) {
+            }
+        };
+    }
+
+    /**
+     * Try to bind to the service with the input parameters, throwing a RuntimeException with the
+     * errorMessage on failure.
+     */
+    private void bindService(Intent intent, ServiceConnection serviceConnection, int flags) {
+        final boolean success = mContext.bindService(intent, serviceConnection, flags);
+        Assert.assertTrue("Could not bind to service", success);
+    }
+
+    /**
+     * Benchmark time from Context.bindService() to Service.onBind() when target package is not
+     * running.
+     */
+    @Test
+    public void bindServiceNotRunning() {
+        runPerfFunction(() -> {
+            final Intent intent = createServiceIntent();
+            final ServiceConnection serviceConnection = createServiceConnectionReportTime();
+
+            final long startTimeNs = System.nanoTime();
+            bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
+            try {
+                final long endTimeNs = getReceivedTimeNs(Constants.TYPE_SERVICE_CONNECTED);
+                return endTimeNs - startTimeNs;
+            } finally {
+                unbindFromService(serviceConnection);
+            }
+        });
+    }
+
+    /**
+     * Benchmark time from Context.bindService() to Service.onBind() when target package is running.
+     */
+    @Test
+    public void bindServiceRunning() {
+        runPerfFunction(() -> {
+            startTargetPackage();
+
+            final Intent intent = createServiceIntent();
+            final ServiceConnection serviceConnection = createServiceConnectionReportTime();
+
+            final long startTimeNs = System.nanoTime();
+            bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
+            try {
+                final long endTimeNs = getReceivedTimeNs(Constants.TYPE_SERVICE_CONNECTED);
+                return endTimeNs - startTimeNs;
+            } finally {
+                unbindFromService(serviceConnection);
+            }
+        });
+    }
+
+    /**
+     * Benchmark time from Context.bindService() to Service.onBind() when service is already bound
+     * to.
+     */
+    @Test
+    public void bindServiceAlreadyBound() {
+        runPerfFunction(() -> {
+            startTargetPackage();
+
+            final Intent intent = createServiceIntent();
+            final ServiceConnection alreadyBoundServiceConnection = bindAndWaitForConnectedService();
+
+            try {
+                final ServiceConnection serviceConnection = createServiceConnectionReportTime();
+
+                final long startTimeNs = System.nanoTime();
+                try {
+                    bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
+                    final long endTimeNs = getReceivedTimeNs(Constants.TYPE_SERVICE_CONNECTED);
+                    return endTimeNs - startTimeNs;
+                } finally {
+                    unbindFromService(serviceConnection);
+                }
+            } finally {
+                unbindFromService(alreadyBoundServiceConnection);
+            }
+        });
+    }
+
+    /**
+     * Benchmark time from Context.bindService() (without BIND_ALLOW_OOM_MANAGEMENT) to
+     * Service.onBind() when service is already bound to with BIND_ALLOW_OOM_MANAGEMENT.
+     */
+    @Test
+    public void bindServiceAllowOomManagement() {
+        runPerfFunction(() -> {
+            final Intent intentNoOom = createServiceIntent();
+            final ServiceConnection serviceConnectionOom = bindAndWaitForConnectedService(
+                    Context.BIND_ALLOW_OOM_MANAGEMENT);
+
+            try {
+                final ServiceConnection serviceConnectionNoOom =
+                        createServiceConnectionReportTime();
+                try {
+                    final long startTimeNs = System.nanoTime();
+                    bindService(intentNoOom, serviceConnectionNoOom, Context.BIND_AUTO_CREATE);
+                    final long endTimeNs = getReceivedTimeNs(Constants.TYPE_SERVICE_CONNECTED);
+
+                    return endTimeNs - startTimeNs;
+                } finally {
+                    unbindFromService(serviceConnectionNoOom);
+                }
+            } finally {
+                unbindFromService(serviceConnectionOom);
+            }
+        });
+    }
+}
diff --git a/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/tests/ServiceStartPerfTest.java b/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/tests/ServiceStartPerfTest.java
new file mode 100644
index 0000000..626ee02
--- /dev/null
+++ b/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/tests/ServiceStartPerfTest.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.android.frameworks.perftests.am.tests;
+
+import android.content.ComponentName;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.support.test.filters.LargeTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import com.android.frameworks.perftests.am.util.Constants;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@LargeTest
+public class ServiceStartPerfTest extends BasePerfTest {
+
+    /**
+     * Tries to start the service with the given intent, throwing a RuntimeException with the
+     * errorMessage on failure.
+     */
+    private void startService(Intent intent) {
+        final ComponentName componentName = mContext.startService(intent);
+        Assert.assertNotNull("Could not start service", componentName);
+    }
+
+    /**
+     * Benchmark time from Context.startService() to Service.onStartCommand() when target process is
+     * not running.
+     */
+    @Test
+    public void startServiceNotRunning() {
+        runPerfFunction(() -> {
+            final Intent intent = createServiceIntent();
+
+            final long startTimeNs = System.nanoTime();
+
+            startService(intent);
+
+            final long endTimeNs = getReceivedTimeNs(Constants.TYPE_SERVICE_START);
+            return endTimeNs - startTimeNs;
+        });
+    }
+
+    /**
+     * Benchmark time from Context.startService() to Service.onStartCommand() when target process is
+     * running.
+     */
+    @Test
+    public void startServiceProcessRunning() {
+        runPerfFunction(() -> {
+            startTargetPackage();
+
+            final Intent intent = createServiceIntent();
+
+            final long startTimeNs = System.nanoTime();
+            startService(intent);
+            final long endTimeNs = getReceivedTimeNs(Constants.TYPE_SERVICE_START);
+
+            return endTimeNs - startTimeNs;
+        });
+    }
+
+    /**
+     * Benchmark time from Context.startService() to Service.onStartCommand() when service is
+     * already bound to.
+     */
+    @Test
+    public void startServiceAlreadyBound() {
+        runPerfFunction(() -> {
+            final ServiceConnection alreadyBoundServiceConnection =
+                    bindAndWaitForConnectedService();
+            try {
+                final Intent intent = createServiceIntent();
+
+                final long startTimeNs = System.nanoTime();
+                startService(intent);
+                final long endTimeNs = getReceivedTimeNs(Constants.TYPE_SERVICE_START);
+
+                return endTimeNs - startTimeNs;
+            } finally {
+                unbindFromService(alreadyBoundServiceConnection);
+            }
+        });
+    }
+
+    /**
+     * Benchmark time from Context.startService() with FLAG_GRANT_READ_URI_PERMISSION to
+     * Service.onStartCommand() when target process is running.
+     */
+    @Test
+    public void startServiceProcessRunningReadUriPermission() {
+        runPerfFunction(() -> {
+            final ServiceConnection alreadyBoundServiceConnection =
+                    bindAndWaitForConnectedService();
+            try {
+                final Intent intent = createServiceIntent();
+                intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+
+                final long startTimeNs = System.nanoTime();
+                startService(intent);
+                final long endTimeNs = getReceivedTimeNs(Constants.TYPE_SERVICE_START);
+
+                return endTimeNs - startTimeNs;
+            } finally {
+                unbindFromService(alreadyBoundServiceConnection);
+            }
+        });
+    }
+}
diff --git a/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/util/TargetPackageUtils.java b/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/util/TargetPackageUtils.java
index 26a8e7b..3db8abc 100644
--- a/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/util/TargetPackageUtils.java
+++ b/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/util/TargetPackageUtils.java
@@ -27,6 +27,7 @@
 
     public static final String PACKAGE_NAME = "com.android.frameworks.perftests.amteststestapp";
     public static final String ACTIVITY_NAME = PACKAGE_NAME + ".TestActivity";
+    public static final String SERVICE_NAME = PACKAGE_NAME + ".TestService";
 
     private static final long WAIT_TIME_MS = 100L;
 
diff --git a/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/util/TimeReceiver.java b/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/util/TimeReceiver.java
index 9cf6ee7..a86a5c7 100644
--- a/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/util/TimeReceiver.java
+++ b/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/util/TimeReceiver.java
@@ -45,20 +45,23 @@
         }
     }
 
+    public void addTimeForTypeToQueue(String type, long timeNs) {
+        if (type == null) {
+            throw new IllegalArgumentException("type is null when adding time to queue");
+        }
+        if (timeNs < 0) {
+            throw new RuntimeException(
+                    "time is negative/non-existant (" + timeNs + ") when adding time to queue");
+        }
+        mQueue.add(new ReceivedMessage(type, timeNs));
+    }
+
     public Bundle createReceiveTimeExtraBinder() {
         Bundle extras = new Bundle();
         extras.putBinder(Constants.EXTRA_RECEIVER_CALLBACK, new ITimeReceiverCallback.Stub() {
             @Override
             public void sendTime(String type, long timeNs) throws RemoteException {
-                if (type == null) {
-                    throw new RuntimeException("receivedType is null");
-                }
-                if (timeNs < 0) {
-                    throw new RuntimeException(
-                            "receivedTime is negative/non-existant: " + timeNs);
-                }
-                Log.i(TAG, type + " " + timeNs);
-                mQueue.add(new ReceivedMessage(type, timeNs));
+                addTimeForTypeToQueue(type, timeNs);
             }
         });
         return extras;
diff --git a/tests/ActivityManagerPerfTests/utils/src/com/android/frameworks/perftests/am/util/Constants.java b/tests/ActivityManagerPerfTests/utils/src/com/android/frameworks/perftests/am/util/Constants.java
index f35c2fd..ffb3f84 100644
--- a/tests/ActivityManagerPerfTests/utils/src/com/android/frameworks/perftests/am/util/Constants.java
+++ b/tests/ActivityManagerPerfTests/utils/src/com/android/frameworks/perftests/am/util/Constants.java
@@ -19,6 +19,9 @@
 public class Constants {
     public static final String TYPE_TARGET_PACKAGE_START = "target_package_start";
     public static final String TYPE_BROADCAST_RECEIVE = "broadcast_receive";
+    public static final String TYPE_SERVICE_BIND = "service_bind";
+    public static final String TYPE_SERVICE_START = "service_start";
+    public static final String TYPE_SERVICE_CONNECTED = "service_connection_connect";
 
     public static final String ACTION_BROADCAST_MANIFEST_RECEIVE =
             "com.android.frameworks.perftests.ACTION_BROADCAST_MANIFEST_RECEIVE";
diff --git a/tests/FrameworkPerf/AndroidManifest.xml b/tests/FrameworkPerf/AndroidManifest.xml
index d62ef9e..2591aaf 100644
--- a/tests/FrameworkPerf/AndroidManifest.xml
+++ b/tests/FrameworkPerf/AndroidManifest.xml
@@ -1,6 +1,5 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
         package="com.android.frameworkperf">
-    <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
     <uses-permission android:name="android.permission.WAKE_LOCK" />
     <uses-sdk android:minSdkVersion="5" />
 
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/DrawIntoHwBitmapActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/DrawIntoHwBitmapActivity.java
index faabdfc..af8e10b 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/DrawIntoHwBitmapActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/DrawIntoHwBitmapActivity.java
@@ -27,6 +27,7 @@
 import android.graphics.Color;
 import android.graphics.GraphicBuffer;
 import android.graphics.Paint;
+import android.graphics.Picture;
 import android.graphics.PixelFormat;
 import android.graphics.SurfaceTexture;
 import android.os.Bundle;
@@ -47,10 +48,8 @@
     }
 
     Bitmap createBitmap() {
-        RenderNode node = RenderNode.create("HwuiCanvas", null);
-        node.setLeftTopRightBottom(0, 0, 500, 500);
-        node.setClipToBounds(false);
-        DisplayListCanvas canvas = node.start(500, 500);
+        Picture picture = new Picture();
+        Canvas canvas = picture.beginRecording(500, 500);
         Paint p = new Paint();
         p.setColor(Color.BLACK);
         p.setTextSize(20 * getResources().getDisplayMetrics().density);
@@ -59,7 +58,7 @@
         canvas.drawRect(0, 0, 500, 100, p);
         p.setColor(Color.BLACK);
         canvas.drawText("Hello, World!", 0, 90, p);
-        node.end(canvas);
-        return ThreadedRenderer.createHardwareBitmap(node, 500, 500);
+        picture.endRecording();
+        return Bitmap.createBitmap(picture);
     }
 }
diff --git a/tests/OneMedia/AndroidManifest.xml b/tests/OneMedia/AndroidManifest.xml
index 8697f1b..c6824ec 100644
--- a/tests/OneMedia/AndroidManifest.xml
+++ b/tests/OneMedia/AndroidManifest.xml
@@ -5,7 +5,6 @@
     android:versionName="1.0" >
 
     <uses-sdk android:minSdkVersion="19"/>
-    <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
     <uses-permission android:name="android.permission.INTERNET" />
     <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
 
diff --git a/tools/sdkparcelables/src/com/android/sdkparcelables/ParcelableDetector.kt b/tools/sdkparcelables/src/com/android/sdkparcelables/ParcelableDetector.kt
index d6a0a45..45027b5 100644
--- a/tools/sdkparcelables/src/com/android/sdkparcelables/ParcelableDetector.kt
+++ b/tools/sdkparcelables/src/com/android/sdkparcelables/ParcelableDetector.kt
@@ -27,6 +27,8 @@
             impl.build()
             return impl.parcelables
         }
+
+        const val PARCELABLE_CLASS = "android/os/Parcelable"
     }
 
     private class Impl(val ancestors: Map<String, Ancestors>) {
@@ -35,7 +37,7 @@
 
         fun build() {
             val classList = ancestors.keys
-            classList.filterTo(parcelables, this::isParcelable)
+            classList.filterTo(parcelables, { (it != PARCELABLE_CLASS) && isParcelable(it) })
             parcelables.sort()
         }
 
@@ -44,7 +46,7 @@
                 return false
             }
 
-            if (c == "android/os/Parcelable") {
+            if (c == PARCELABLE_CLASS) {
                 return true
             }
 
diff --git a/tools/sdkparcelables/tests/com/android/sdkparcelables/ParcelableDetectorTest.kt b/tools/sdkparcelables/tests/com/android/sdkparcelables/ParcelableDetectorTest.kt
index c9bcbc9..f08173d 100644
--- a/tools/sdkparcelables/tests/com/android/sdkparcelables/ParcelableDetectorTest.kt
+++ b/tools/sdkparcelables/tests/com/android/sdkparcelables/ParcelableDetectorTest.kt
@@ -28,7 +28,7 @@
 
         val parcelables = ParcelableDetector.ancestorsToParcelables(ancestorMap)
 
-        assertEquals(parcelables, listOf("android/os/Parcelable", "android/test/Parcelable"))
+        assertEquals(parcelables, listOf("android/test/Parcelable"))
     }
 
     @Test
@@ -39,7 +39,7 @@
 
         val parcelables = ParcelableDetector.ancestorsToParcelables(ancestorMap)
 
-        assertEquals(parcelables, listOf("android/os/Parcelable", "android/test/Parcelable"))
+        assertEquals(parcelables, listOf("android/test/Parcelable"))
     }
 
     @Test
@@ -51,7 +51,7 @@
 
         val parcelables = ParcelableDetector.ancestorsToParcelables(ancestorMap)
 
-        assertEquals(parcelables, listOf("android/os/Parcelable", "android/test/Parcelable", "android/test/SuperParcelable"))
+        assertEquals(parcelables, listOf("android/test/Parcelable", "android/test/SuperParcelable"))
     }
 
     @Test
@@ -63,7 +63,7 @@
 
         val parcelables = ParcelableDetector.ancestorsToParcelables(ancestorMap)
 
-        assertEquals(parcelables, listOf("android/os/Parcelable", "android/test/IParcelable", "android/test/Parcelable"))
+        assertEquals(parcelables, listOf("android/test/IParcelable", "android/test/Parcelable"))
     }
 
 }
diff --git a/wifi/java/android/net/wifi/rtt/RangingResult.java b/wifi/java/android/net/wifi/rtt/RangingResult.java
index 201833b..f7c8567 100644
--- a/wifi/java/android/net/wifi/rtt/RangingResult.java
+++ b/wifi/java/android/net/wifi/rtt/RangingResult.java
@@ -59,6 +59,19 @@
      */
     public static final int STATUS_FAIL = 1;
 
+    /**
+     * Individual range request status, {@link #getStatus()}. Indicates that the ranging operation
+     * failed because the specified peer does not support IEEE 802.11mc RTT operations. Support by
+     * an Access Point can be confirmed using
+     * {@link android.net.wifi.ScanResult#is80211mcResponder()}.
+     * <p>
+     * On such a failure, the individual result fields of {@link RangingResult} such as
+     * {@link RangingResult#getDistanceMm()} are invalid.
+     *
+     * @hide
+     */
+    public static final int STATUS_RESPONDER_DOES_NOT_SUPPORT_IEEE80211MC = 2;
+
     private final int mStatus;
     private final MacAddress mMac;
     private final PeerHandle mPeerHandle;