PPR1.180219.001_AOSP_Merge

Conflicts:
	core/res/res/values/config.xml
	core/res/res/values/symbols.xml
	packages/SystemUI/res/values/config.xml
	packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
	packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
	telecomm/java/android/telecom/Call.java
	telecomm/java/android/telecom/Connection.java
	telecomm/java/android/telecom/ConnectionService.java

Change-Id: I524d38a61608069028b3496a189118d8eff75f4b
diff --git a/Android.bp b/Android.bp
index cbc427a..b14f15e 100755
--- a/Android.bp
+++ b/Android.bp
@@ -249,8 +249,7 @@
         "core/java/android/os/storage/IStorageEventListener.aidl",
         "core/java/android/os/storage/IStorageShutdownObserver.aidl",
         "core/java/android/os/storage/IObbActionListener.aidl",
-        "core/java/android/security/IConfirmationPromptCallback.aidl",
-        "core/java/android/security/IKeystoreService.aidl",
+        ":keystore_aidl",
         "core/java/android/security/keymaster/IKeyAttestationApplicationIdProvider.aidl",
         "core/java/android/service/autofill/IAutoFillService.aidl",
         "core/java/android/service/autofill/IAutofillFieldClassificationService.aidl",
@@ -373,7 +372,6 @@
         "core/java/com/android/internal/appwidget/IAppWidgetHost.aidl",
         "core/java/com/android/internal/backup/IBackupTransport.aidl",
         "core/java/com/android/internal/backup/IObbBackupService.aidl",
-        "core/java/com/android/internal/car/ICarServiceHelper.aidl",
         "core/java/com/android/internal/inputmethod/IInputContentUriToken.aidl",
         "core/java/com/android/internal/net/INetworkWatchlistManager.aidl",
         "core/java/com/android/internal/policy/IKeyguardDrawnCallback.aidl",
@@ -427,6 +425,7 @@
         "media/java/android/media/IAudioFocusDispatcher.aidl",
         "media/java/android/media/IAudioRoutesObserver.aidl",
         "media/java/android/media/IAudioService.aidl",
+        "media/java/android/media/IAudioServerStateDispatcher.aidl",
         "media/java/android/media/IMediaHTTPConnection.aidl",
         "media/java/android/media/IMediaHTTPService.aidl",
         "media/java/android/media/IMediaResourceMonitor.aidl",
@@ -580,7 +579,6 @@
         "wifi/java/android/net/wifi/rtt/IWifiRttManager.aidl",
         "wifi/java/android/net/wifi/hotspot2/IProvisioningCallback.aidl",
         "wifi/java/android/net/wifi/IWifiScanner.aidl",
-        "wifi/java/android/net/wifi/IRttManager.aidl",
         "packages/services/PacProcessor/com/android/net/IProxyService.aidl",
         "packages/services/Proxy/com/android/net/IProxyCallback.aidl",
         "packages/services/Proxy/com/android/net/IProxyPortListener.aidl",
@@ -645,6 +643,7 @@
             "system/netd/server/binder",
             "system/vold/binder",
             "system/bt/binder",
+            "system/security/keystore/binder",
         ],
     },
 
@@ -673,8 +672,9 @@
         "android.hardware.tv.input-V1.0-java-constants",
         "android.hardware.usb-V1.0-java-constants",
         "android.hardware.usb-V1.1-java-constants",
-        "android.hardware.vibrator-V1.0-java-constants",
-        "android.hardware.vibrator-V1.1-java-constants",
+        "android.hardware.vibrator-V1.0-java",
+        "android.hardware.vibrator-V1.1-java",
+        "android.hardware.vibrator-V1.2-java",
         "android.hardware.wifi-V1.0-java-constants",
         "android.hardware.radio-V1.0-java",
         "android.hardware.usb.gadget-V1.0-java",
diff --git a/Android.mk b/Android.mk
index a78a01a..58e21ff 100755
--- 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 $$< $$@
@@ -793,6 +793,8 @@
     $(call all-proto-files-under, core/proto) \
     $(call all-proto-files-under, libs/incident/proto) \
     $(call all-proto-files-under, cmds/statsd/src)
+# b/72714520
+LOCAL_ERROR_PRONE_FLAGS := -Xep:MissingOverride:OFF
 include $(BUILD_HOST_JAVA_LIBRARY)
 
 # ====  java proto device library (for test only)  ==============================
@@ -804,7 +806,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/PREUPLOAD.cfg b/PREUPLOAD.cfg
index 711c12d..2a67b75 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -1,6 +1,7 @@
 [Hook Scripts]
 checkstyle_hook = ${REPO_ROOT}/prebuilts/checkstyle/checkstyle.py --sha ${PREUPLOAD_COMMIT}
                   -fw core/java/android/
+                      graphics/java/android
                       core/tests/coretests/src/android/
                       packages/PrintRecommendationService/
                       packages/PrintSpooler/
diff --git a/apct-tests/perftests/core/src/android/app/PendingIntentPerfTest.java b/apct-tests/perftests/core/src/android/app/PendingIntentPerfTest.java
new file mode 100644
index 0000000..f8fd51d
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/app/PendingIntentPerfTest.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package android.app;
+
+import android.content.Context;
+import android.content.Intent;
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+import android.perftests.utils.StubActivity;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.LargeTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+// Due to b/71353150, you might get "java.lang.AssertionError: Binder ProxyMap has too many
+// entries", but it's flaky. Adding "Runtime.getRuntime().gc()" between each iteration solves
+// the problem, but it doesn't seem like it's currently needed.
+
+@RunWith(AndroidJUnit4.class)
+@LargeTest
+public class PendingIntentPerfTest {
+
+    private Context mContext;
+
+    @Rule
+    public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+
+    private Intent mIntent;
+
+    @Before
+    public void setUp() {
+        mContext = InstrumentationRegistry.getTargetContext();
+        mIntent = StubActivity.createLaunchIntent(mContext);
+    }
+
+    /**
+     * Benchmark time to create a PendingIntent.
+     */
+    @Test
+    public void create() {
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            state.pauseTiming();
+            state.resumeTiming();
+
+            final PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0, mIntent,
+                    0);
+
+            state.pauseTiming();
+            pendingIntent.cancel();
+            state.resumeTiming();
+        }
+    }
+
+    /**
+     * Benchmark time to create a PendingIntent with FLAG_CANCEL_CURRENT, already having an active
+     * PendingIntent.
+     */
+    @Test
+    public void createWithCancelFlag() {
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            state.pauseTiming();
+            final PendingIntent previousPendingIntent = PendingIntent.getActivity(mContext, 0,
+                    mIntent, 0);
+            state.resumeTiming();
+
+            final PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0, mIntent,
+                    PendingIntent.FLAG_CANCEL_CURRENT);
+
+            state.pauseTiming();
+            pendingIntent.cancel();
+            state.resumeTiming();
+        }
+    }
+
+    /**
+     * Benchmark time to create a PendingIntent with FLAG_UPDATE_CURRENT, already having an active
+     * PendingIntent.
+     */
+    @Test
+    public void createWithUpdateFlag() {
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            state.pauseTiming();
+            final PendingIntent previousPendingIntent = PendingIntent.getActivity(mContext, 0,
+                    mIntent, 0);
+            state.resumeTiming();
+
+            final PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0, mIntent,
+                    PendingIntent.FLAG_UPDATE_CURRENT);
+
+            state.pauseTiming();
+            previousPendingIntent.cancel();
+            pendingIntent.cancel();
+            state.resumeTiming();
+        }
+    }
+
+    /**
+     * Benchmark time to cancel a PendingIntent.
+     */
+    @Test
+    public void cancel() {
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            state.pauseTiming();
+            final PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0,
+                    mIntent, 0);
+            state.resumeTiming();
+
+            pendingIntent.cancel();
+        }
+    }
+}
+
diff --git a/apct-tests/perftests/core/src/android/text/StaticLayoutMultithreadPerfTest.java b/apct-tests/perftests/core/src/android/text/StaticLayoutMultithreadPerfTest.java
new file mode 100644
index 0000000..60c6d89
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/text/StaticLayoutMultithreadPerfTest.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package android.text;
+
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+
+import android.support.test.filters.LargeTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Random;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.TimeUnit;
+
+@LargeTest
+@RunWith(AndroidJUnit4.class)
+public class StaticLayoutMultithreadPerfTest {
+    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;
+
+    private static TextPaint PAINT = new TextPaint();
+    private static final int TEXT_WIDTH = WORDS_IN_LINE * WORD_LENGTH * (int) PAINT.getTextSize();
+
+    public StaticLayoutMultithreadPerfTest() {}
+
+    @Rule
+    public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+
+    private CountDownLatch mStartLatch;
+    private AtomicBoolean mThreadState;  // True for running, False for stopped.
+
+    private static final long TIMEOUT_MS = 5000;
+
+    private Thread[] startBackgroundThread(int numOfThreads) {
+        mStartLatch = new CountDownLatch(numOfThreads);
+        mThreadState = new AtomicBoolean(true);
+
+        Thread[] threads = new Thread[numOfThreads];
+        for (int i = 0; i < numOfThreads; ++i) {
+            final int seed = i + 1;
+            threads[i] = new Thread(new Runnable() {
+                @Override
+                public void run() {
+                    final TextPerfUtils util = new TextPerfUtils();
+                    util.resetRandom(seed);
+
+                    mStartLatch.countDown();
+                    while (mThreadState.get()) {
+                        final CharSequence text = util.nextRandomParagraph(
+                                WORD_LENGTH, NO_STYLE_TEXT);
+                        StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH)
+                                .build();
+                    }
+                }
+            });
+        }
+
+        for (int i = 0; i < numOfThreads; ++i) {
+            threads[i].start();
+        }
+
+        try {
+            mStartLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS);
+        } catch (InterruptedException e) {
+            throw new RuntimeException(e);
+        }
+        return threads;
+    }
+
+    private void finishThreads(Thread[] threads) {
+        mThreadState.set(false);
+        for (Thread thread : threads) {
+            try {
+                thread.join();
+            } catch (InterruptedException e) {
+                throw new RuntimeException(e);
+            }
+        }
+        mStartLatch = null;
+        mThreadState = null;
+    }
+
+    private void runRandomTest(int numOfTotalThreads) {
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        final TextPerfUtils util = new TextPerfUtils();
+        Thread[] threads = startBackgroundThread(numOfTotalThreads - 1);
+        while (state.keepRunning()) {
+            state.pauseTiming();
+            final CharSequence text = util.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT);
+            state.resumeTiming();
+
+            StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH)
+                    .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NONE)
+                    .setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE)
+                    .build();
+        }
+        finishThreads(threads);
+    }
+
+    @Test
+    public void testCreate_RandomText_Thread_1() {
+        runRandomTest(1);
+    }
+
+    @Test
+    public void testCreate_RandomText_Thread_2() {
+        runRandomTest(2);
+    }
+
+    @Test
+    public void testCreate_RandomText_Thread_4() {
+        runRandomTest(4);
+    }
+}
diff --git a/apct-tests/perftests/utils/src/android/perftests/utils/StubActivity.java b/apct-tests/perftests/utils/src/android/perftests/utils/StubActivity.java
index 6012f4b1..8f03f7e 100644
--- a/apct-tests/perftests/utils/src/android/perftests/utils/StubActivity.java
+++ b/apct-tests/perftests/utils/src/android/perftests/utils/StubActivity.java
@@ -17,6 +17,14 @@
 package android.perftests.utils;
 
 import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
 
 public class StubActivity extends Activity {
-}
\ No newline at end of file
+    public static Intent createLaunchIntent(Context context) {
+        final Intent intent = new Intent();
+        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        intent.setClass(context, StubActivity.class);
+        return intent;
+    }
+}
diff --git a/api/current.txt b/api/current.txt
index 3c3cfcc..83a4560 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -1468,6 +1468,7 @@
     field public static final deprecated int unfocusedMonthDateColor = 16843588; // 0x1010344
     field public static final int unselectedAlpha = 16843278; // 0x101020e
     field public static final int updatePeriodMillis = 16843344; // 0x1010250
+    field public static final int urlBarResourceId = 16844164; // 0x1010584
     field public static final int use32bitAbi = 16844053; // 0x1010515
     field public static final int useDefaultMargins = 16843641; // 0x1010379
     field public static final int useIntrinsicSizeAsMinimum = 16843536; // 0x1010310
@@ -2215,34 +2216,34 @@
     field public static final int Theme_DeviceDefault_Wallpaper = 16974140; // 0x103013c
     field public static final int Theme_DeviceDefault_Wallpaper_NoTitleBar = 16974141; // 0x103013d
     field public static final int Theme_Dialog = 16973835; // 0x103000b
-    field public static final int Theme_Holo = 16973931; // 0x103006b
-    field public static final int Theme_Holo_Dialog = 16973935; // 0x103006f
-    field public static final int Theme_Holo_DialogWhenLarge = 16973943; // 0x1030077
-    field public static final int Theme_Holo_DialogWhenLarge_NoActionBar = 16973944; // 0x1030078
-    field public static final int Theme_Holo_Dialog_MinWidth = 16973936; // 0x1030070
-    field public static final int Theme_Holo_Dialog_NoActionBar = 16973937; // 0x1030071
-    field public static final int Theme_Holo_Dialog_NoActionBar_MinWidth = 16973938; // 0x1030072
-    field public static final int Theme_Holo_InputMethod = 16973951; // 0x103007f
-    field public static final int Theme_Holo_Light = 16973934; // 0x103006e
-    field public static final int Theme_Holo_Light_DarkActionBar = 16974105; // 0x1030119
-    field public static final int Theme_Holo_Light_Dialog = 16973939; // 0x1030073
-    field public static final int Theme_Holo_Light_DialogWhenLarge = 16973945; // 0x1030079
-    field public static final int Theme_Holo_Light_DialogWhenLarge_NoActionBar = 16973946; // 0x103007a
-    field public static final int Theme_Holo_Light_Dialog_MinWidth = 16973940; // 0x1030074
-    field public static final int Theme_Holo_Light_Dialog_NoActionBar = 16973941; // 0x1030075
-    field public static final int Theme_Holo_Light_Dialog_NoActionBar_MinWidth = 16973942; // 0x1030076
-    field public static final int Theme_Holo_Light_NoActionBar = 16974064; // 0x10300f0
-    field public static final int Theme_Holo_Light_NoActionBar_Fullscreen = 16974065; // 0x10300f1
-    field public static final int Theme_Holo_Light_NoActionBar_Overscan = 16974302; // 0x10301de
-    field public static final int Theme_Holo_Light_NoActionBar_TranslucentDecor = 16974306; // 0x10301e2
-    field public static final int Theme_Holo_Light_Panel = 16973948; // 0x103007c
-    field public static final int Theme_Holo_NoActionBar = 16973932; // 0x103006c
-    field public static final int Theme_Holo_NoActionBar_Fullscreen = 16973933; // 0x103006d
-    field public static final int Theme_Holo_NoActionBar_Overscan = 16974301; // 0x10301dd
-    field public static final int Theme_Holo_NoActionBar_TranslucentDecor = 16974305; // 0x10301e1
-    field public static final int Theme_Holo_Panel = 16973947; // 0x103007b
-    field public static final int Theme_Holo_Wallpaper = 16973949; // 0x103007d
-    field public static final int Theme_Holo_Wallpaper_NoTitleBar = 16973950; // 0x103007e
+    field public static final deprecated int Theme_Holo = 16973931; // 0x103006b
+    field public static final deprecated int Theme_Holo_Dialog = 16973935; // 0x103006f
+    field public static final deprecated int Theme_Holo_DialogWhenLarge = 16973943; // 0x1030077
+    field public static final deprecated int Theme_Holo_DialogWhenLarge_NoActionBar = 16973944; // 0x1030078
+    field public static final deprecated int Theme_Holo_Dialog_MinWidth = 16973936; // 0x1030070
+    field public static final deprecated int Theme_Holo_Dialog_NoActionBar = 16973937; // 0x1030071
+    field public static final deprecated int Theme_Holo_Dialog_NoActionBar_MinWidth = 16973938; // 0x1030072
+    field public static final deprecated int Theme_Holo_InputMethod = 16973951; // 0x103007f
+    field public static final deprecated int Theme_Holo_Light = 16973934; // 0x103006e
+    field public static final deprecated int Theme_Holo_Light_DarkActionBar = 16974105; // 0x1030119
+    field public static final deprecated int Theme_Holo_Light_Dialog = 16973939; // 0x1030073
+    field public static final deprecated int Theme_Holo_Light_DialogWhenLarge = 16973945; // 0x1030079
+    field public static final deprecated int Theme_Holo_Light_DialogWhenLarge_NoActionBar = 16973946; // 0x103007a
+    field public static final deprecated int Theme_Holo_Light_Dialog_MinWidth = 16973940; // 0x1030074
+    field public static final deprecated int Theme_Holo_Light_Dialog_NoActionBar = 16973941; // 0x1030075
+    field public static final deprecated int Theme_Holo_Light_Dialog_NoActionBar_MinWidth = 16973942; // 0x1030076
+    field public static final deprecated int Theme_Holo_Light_NoActionBar = 16974064; // 0x10300f0
+    field public static final deprecated int Theme_Holo_Light_NoActionBar_Fullscreen = 16974065; // 0x10300f1
+    field public static final deprecated int Theme_Holo_Light_NoActionBar_Overscan = 16974302; // 0x10301de
+    field public static final deprecated int Theme_Holo_Light_NoActionBar_TranslucentDecor = 16974306; // 0x10301e2
+    field public static final deprecated int Theme_Holo_Light_Panel = 16973948; // 0x103007c
+    field public static final deprecated int Theme_Holo_NoActionBar = 16973932; // 0x103006c
+    field public static final deprecated int Theme_Holo_NoActionBar_Fullscreen = 16973933; // 0x103006d
+    field public static final deprecated int Theme_Holo_NoActionBar_Overscan = 16974301; // 0x10301dd
+    field public static final deprecated int Theme_Holo_NoActionBar_TranslucentDecor = 16974305; // 0x10301e1
+    field public static final deprecated int Theme_Holo_Panel = 16973947; // 0x103007b
+    field public static final deprecated int Theme_Holo_Wallpaper = 16973949; // 0x103007d
+    field public static final deprecated int Theme_Holo_Wallpaper_NoTitleBar = 16973950; // 0x103007e
     field public static final int Theme_InputMethod = 16973908; // 0x1030054
     field public static final int Theme_Light = 16973836; // 0x103000c
     field public static final int Theme_Light_NoTitleBar = 16973837; // 0x103000d
@@ -3695,7 +3696,7 @@
     method public boolean onCreateOptionsMenu(android.view.Menu);
     method public boolean onCreatePanelMenu(int, android.view.Menu);
     method public android.view.View onCreatePanelView(int);
-    method public boolean onCreateThumbnail(android.graphics.Bitmap, android.graphics.Canvas);
+    method public deprecated boolean onCreateThumbnail(android.graphics.Bitmap, android.graphics.Canvas);
     method public android.view.View onCreateView(java.lang.String, android.content.Context, android.util.AttributeSet);
     method public android.view.View onCreateView(android.view.View, java.lang.String, android.content.Context, android.util.AttributeSet);
     method protected void onDestroy();
@@ -6493,7 +6494,6 @@
     method public boolean isNetworkLoggingEnabled(android.content.ComponentName);
     method public boolean isOverrideApnEnabled(android.content.ComponentName);
     method public boolean isPackageSuspended(android.content.ComponentName, java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException;
-    method public boolean isPrintingEnabled();
     method public boolean isProfileOwnerApp(java.lang.String);
     method public boolean isProvisioningAllowed(java.lang.String);
     method public boolean isResetPasswordTokenActive(android.content.ComponentName);
@@ -6566,7 +6566,6 @@
     method public boolean setPermittedAccessibilityServices(android.content.ComponentName, java.util.List<java.lang.String>);
     method public boolean setPermittedCrossProfileNotificationListeners(android.content.ComponentName, java.util.List<java.lang.String>);
     method public boolean setPermittedInputMethods(android.content.ComponentName, java.util.List<java.lang.String>);
-    method public void setPrintingEnabled(android.content.ComponentName, boolean);
     method public void setProfileEnabled(android.content.ComponentName);
     method public void setProfileName(android.content.ComponentName, java.lang.String);
     method public void setRecommendedGlobalProxy(android.content.ComponentName, android.net.ProxyInfo);
@@ -6707,6 +6706,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
   }
@@ -6741,6 +6741,8 @@
     field public static final int TAG_APP_PROCESS_START = 210005; // 0x33455
     field public static final int TAG_CERT_AUTHORITY_INSTALLED = 210029; // 0x3346d
     field public static final int TAG_CERT_AUTHORITY_REMOVED = 210030; // 0x3346e
+    field public static final int TAG_CERT_VALIDATION_FAILURE = 210033; // 0x33471
+    field public static final int TAG_CRYPTO_SELF_TEST_COMPLETED = 210031; // 0x3346f
     field public static final int TAG_KEYGUARD_DISABLED_FEATURES_SET = 210021; // 0x33465
     field public static final int TAG_KEYGUARD_DISMISSED = 210006; // 0x33456
     field public static final int TAG_KEYGUARD_DISMISS_AUTH_ATTEMPT = 210007; // 0x33457
@@ -6748,6 +6750,7 @@
     field public static final int TAG_KEY_DESTRUCTION = 210026; // 0x3346a
     field public static final int TAG_KEY_GENERATED = 210024; // 0x33468
     field public static final int TAG_KEY_IMPORT = 210025; // 0x33469
+    field public static final int TAG_KEY_INTEGRITY_VIOLATION = 210032; // 0x33470
     field public static final int TAG_LOGGING_STARTED = 210011; // 0x3345b
     field public static final int TAG_LOGGING_STOPPED = 210012; // 0x3345c
     field public static final int TAG_LOG_BUFFER_SIZE_CRITICAL = 210015; // 0x3345f
@@ -6874,6 +6877,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 +9445,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 +11271,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";
@@ -12549,6 +12555,7 @@
     method public abstract void onUpgrade(android.database.sqlite.SQLiteDatabase, int, int);
     method public void setIdleConnectionTimeout(long);
     method public void setLookasideConfig(int, int);
+    method public void setOpenParams(android.database.sqlite.SQLiteDatabase.OpenParams);
     method public void setWriteAheadLoggingEnabled(boolean);
   }
 
@@ -14605,7 +14612,7 @@
     method public final android.graphics.Rect copyBounds();
     method public static android.graphics.drawable.Drawable createFromPath(java.lang.String);
     method public static android.graphics.drawable.Drawable createFromResourceStream(android.content.res.Resources, android.util.TypedValue, java.io.InputStream, java.lang.String);
-    method public static android.graphics.drawable.Drawable createFromResourceStream(android.content.res.Resources, android.util.TypedValue, java.io.InputStream, java.lang.String, android.graphics.BitmapFactory.Options);
+    method public static deprecated android.graphics.drawable.Drawable createFromResourceStream(android.content.res.Resources, android.util.TypedValue, java.io.InputStream, java.lang.String, android.graphics.BitmapFactory.Options);
     method public static android.graphics.drawable.Drawable createFromStream(java.io.InputStream, java.lang.String);
     method public static android.graphics.drawable.Drawable createFromXml(android.content.res.Resources, org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
     method public static android.graphics.drawable.Drawable createFromXml(android.content.res.Resources, org.xmlpull.v1.XmlPullParser, android.content.res.Resources.Theme) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
@@ -15843,8 +15850,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 +23376,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 +23390,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 +23406,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
@@ -26750,7 +26756,7 @@
     field public static final deprecated java.lang.String ACTION_BACKGROUND_DATA_SETTING_CHANGED = "android.net.conn.BACKGROUND_DATA_SETTING_CHANGED";
     field public static final java.lang.String ACTION_CAPTIVE_PORTAL_SIGN_IN = "android.net.conn.CAPTIVE_PORTAL";
     field public static final java.lang.String ACTION_RESTRICT_BACKGROUND_CHANGED = "android.net.conn.RESTRICT_BACKGROUND_CHANGED";
-    field public static final java.lang.String CONNECTIVITY_ACTION = "android.net.conn.CONNECTIVITY_CHANGE";
+    field public static final deprecated java.lang.String CONNECTIVITY_ACTION = "android.net.conn.CONNECTIVITY_CHANGE";
     field public static final deprecated int DEFAULT_NETWORK_PREFERENCE = 1; // 0x1
     field public static final java.lang.String EXTRA_CAPTIVE_PORTAL = "android.net.extra.CAPTIVE_PORTAL";
     field public static final java.lang.String EXTRA_CAPTIVE_PORTAL_URL = "android.net.extra.CAPTIVE_PORTAL_URL";
@@ -27026,6 +27032,7 @@
     field public static final int NET_CAPABILITY_CBS = 5; // 0x5
     field public static final int NET_CAPABILITY_DUN = 2; // 0x2
     field public static final int NET_CAPABILITY_EIMS = 10; // 0xa
+    field public static final int NET_CAPABILITY_FOREGROUND = 19; // 0x13
     field public static final int NET_CAPABILITY_FOTA = 3; // 0x3
     field public static final int NET_CAPABILITY_IA = 7; // 0x7
     field public static final int NET_CAPABILITY_IMS = 4; // 0x4
@@ -27034,6 +27041,7 @@
     field public static final int NET_CAPABILITY_NOT_METERED = 11; // 0xb
     field public static final int NET_CAPABILITY_NOT_RESTRICTED = 13; // 0xd
     field public static final int NET_CAPABILITY_NOT_ROAMING = 18; // 0x12
+    field public static final int NET_CAPABILITY_NOT_SUSPENDED = 21; // 0x15
     field public static final int NET_CAPABILITY_NOT_VPN = 15; // 0xf
     field public static final int NET_CAPABILITY_RCS = 8; // 0x8
     field public static final int NET_CAPABILITY_SUPL = 1; // 0x1
@@ -27990,23 +27998,23 @@
     method public int updateNetwork(android.net.wifi.WifiConfiguration);
     field public static final java.lang.String ACTION_PICK_WIFI_NETWORK = "android.net.wifi.PICK_WIFI_NETWORK";
     field public static final java.lang.String ACTION_REQUEST_SCAN_ALWAYS_AVAILABLE = "android.net.wifi.action.REQUEST_SCAN_ALWAYS_AVAILABLE";
-    field public static final int ERROR_AUTHENTICATING = 1; // 0x1
+    field public static final deprecated int ERROR_AUTHENTICATING = 1; // 0x1
     field public static final deprecated java.lang.String EXTRA_BSSID = "bssid";
     field public static final java.lang.String EXTRA_NETWORK_INFO = "networkInfo";
     field public static final java.lang.String EXTRA_NEW_RSSI = "newRssi";
-    field public static final java.lang.String EXTRA_NEW_STATE = "newState";
+    field public static final deprecated java.lang.String EXTRA_NEW_STATE = "newState";
     field public static final java.lang.String EXTRA_PREVIOUS_WIFI_STATE = "previous_wifi_state";
     field public static final java.lang.String EXTRA_RESULTS_UPDATED = "resultsUpdated";
-    field public static final java.lang.String EXTRA_SUPPLICANT_CONNECTED = "connected";
-    field public static final java.lang.String EXTRA_SUPPLICANT_ERROR = "supplicantError";
+    field public static final deprecated java.lang.String EXTRA_SUPPLICANT_CONNECTED = "connected";
+    field public static final deprecated java.lang.String EXTRA_SUPPLICANT_ERROR = "supplicantError";
     field public static final deprecated java.lang.String EXTRA_WIFI_INFO = "wifiInfo";
     field public static final java.lang.String EXTRA_WIFI_STATE = "wifi_state";
     field public static final java.lang.String NETWORK_IDS_CHANGED_ACTION = "android.net.wifi.NETWORK_IDS_CHANGED";
     field public static final java.lang.String NETWORK_STATE_CHANGED_ACTION = "android.net.wifi.STATE_CHANGE";
     field public static final java.lang.String RSSI_CHANGED_ACTION = "android.net.wifi.RSSI_CHANGED";
     field public static final java.lang.String SCAN_RESULTS_AVAILABLE_ACTION = "android.net.wifi.SCAN_RESULTS";
-    field public static final java.lang.String SUPPLICANT_CONNECTION_CHANGE_ACTION = "android.net.wifi.supplicant.CONNECTION_CHANGE";
-    field public static final java.lang.String SUPPLICANT_STATE_CHANGED_ACTION = "android.net.wifi.supplicant.STATE_CHANGE";
+    field public static final deprecated java.lang.String SUPPLICANT_CONNECTION_CHANGE_ACTION = "android.net.wifi.supplicant.CONNECTION_CHANGE";
+    field public static final deprecated java.lang.String SUPPLICANT_STATE_CHANGED_ACTION = "android.net.wifi.supplicant.STATE_CHANGE";
     field public static final int WIFI_MODE_FULL = 1; // 0x1
     field public static final int WIFI_MODE_FULL_HIGH_PERF = 3; // 0x3
     field public static final int WIFI_MODE_SCAN_ONLY = 2; // 0x2
@@ -28061,20 +28069,21 @@
     method public abstract deprecated void onSucceeded();
   }
 
-  public class WpsInfo implements android.os.Parcelable {
-    ctor public WpsInfo();
-    ctor public WpsInfo(android.net.wifi.WpsInfo);
-    method public int describeContents();
-    method public void writeToParcel(android.os.Parcel, int);
-    field public java.lang.String BSSID;
-    field public static final android.os.Parcelable.Creator<android.net.wifi.WpsInfo> CREATOR;
-    field public static final int DISPLAY = 1; // 0x1
-    field public static final int INVALID = 4; // 0x4
-    field public static final int KEYPAD = 2; // 0x2
-    field public static final int LABEL = 3; // 0x3
-    field public static final int PBC = 0; // 0x0
-    field public java.lang.String pin;
-    field public int setup;
+  public deprecated class WpsInfo implements android.os.Parcelable {
+    ctor public deprecated WpsInfo();
+    ctor public deprecated WpsInfo(android.net.wifi.WpsInfo);
+    method public deprecated int describeContents();
+    method public deprecated java.lang.String toString();
+    method public deprecated void writeToParcel(android.os.Parcel, int);
+    field public deprecated java.lang.String BSSID;
+    field public static final deprecated android.os.Parcelable.Creator<android.net.wifi.WpsInfo> CREATOR;
+    field public static final deprecated int DISPLAY = 1; // 0x1
+    field public static final deprecated int INVALID = 4; // 0x4
+    field public static final deprecated int KEYPAD = 2; // 0x2
+    field public static final deprecated int LABEL = 3; // 0x3
+    field public static final deprecated int PBC = 0; // 0x0
+    field public deprecated java.lang.String pin;
+    field public deprecated int setup;
   }
 
 }
@@ -28500,29 +28509,6 @@
 
 package android.net.wifi.rtt {
 
-  public final class LocationCivic implements android.os.Parcelable {
-    method public int describeContents();
-    method public byte[] getData();
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final android.os.Parcelable.Creator<android.net.wifi.rtt.LocationCivic> CREATOR;
-  }
-
-  public final class LocationConfigurationInformation implements android.os.Parcelable {
-    method public int describeContents();
-    method public double getAltitude();
-    method public int getAltitudeType();
-    method public double getAltitudeUncertainty();
-    method public double getLatitude();
-    method public double getLatitudeUncertainty();
-    method public double getLongitude();
-    method public double getLongitudeUncertainty();
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final int ALTITUDE_IN_FLOORS = 2; // 0x2
-    field public static final int ALTITUDE_IN_METERS = 1; // 0x1
-    field public static final int ALTITUDE_UNKNOWN = 0; // 0x0
-    field public static final android.os.Parcelable.Creator<android.net.wifi.rtt.LocationConfigurationInformation> CREATOR;
-  }
-
   public final class RangingRequest implements android.os.Parcelable {
     method public int describeContents();
     method public static int getMaxPeers();
@@ -28545,14 +28531,13 @@
     method public int getDistanceStdDevMm();
     method public android.net.MacAddress getMacAddress();
     method public android.net.wifi.aware.PeerHandle getPeerHandle();
-    method public long getRangingTimestampUs();
-    method public android.net.wifi.rtt.LocationCivic getReportedLocationCivic();
-    method public android.net.wifi.rtt.LocationConfigurationInformation getReportedLocationConfigurationInformation();
+    method public long getRangingTimestampMillis();
     method public int getRssi();
     method public int getStatus();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.net.wifi.rtt.RangingResult> CREATOR;
     field public static final int STATUS_FAIL = 1; // 0x1
+    field public static final int STATUS_RESPONDER_DOES_NOT_SUPPORT_IEEE80211MC = 2; // 0x2
     field public static final int STATUS_SUCCESS = 0; // 0x0
   }
 
@@ -28566,7 +28551,7 @@
 
   public class WifiRttManager {
     method public boolean isAvailable();
-    method public void startRanging(android.net.wifi.rtt.RangingRequest, android.net.wifi.rtt.RangingResultCallback, android.os.Handler);
+    method public void startRanging(android.net.wifi.rtt.RangingRequest, java.util.concurrent.Executor, android.net.wifi.rtt.RangingResultCallback);
     field public static final java.lang.String ACTION_WIFI_RTT_STATE_CHANGED = "android.net.wifi.rtt.action.WIFI_RTT_STATE_CHANGED";
   }
 
@@ -33027,14 +33012,14 @@
   }
 
   public final class SystemClock {
+    method public static java.time.Clock currentNetworkTimeClock();
+    method public static long currentNetworkTimeMillis();
     method public static long currentThreadTimeMillis();
     method public static long elapsedRealtime();
-    method public static java.time.Clock elapsedRealtimeClock();
     method public static long elapsedRealtimeNanos();
     method public static boolean setCurrentTimeMillis(long);
     method public static void sleep(long);
     method public static long uptimeMillis();
-    method public static java.time.Clock uptimeMillisClock();
   }
 
   public class TestLooperManager {
@@ -33140,6 +33125,7 @@
     field public static final java.lang.String DISALLOW_NETWORK_RESET = "no_network_reset";
     field public static final java.lang.String DISALLOW_OUTGOING_BEAM = "no_outgoing_beam";
     field public static final java.lang.String DISALLOW_OUTGOING_CALLS = "no_outgoing_calls";
+    field public static final java.lang.String DISALLOW_PRINTING = "no_printing";
     field public static final java.lang.String DISALLOW_REMOVE_MANAGED_PROFILE = "no_remove_managed_profile";
     field public static final java.lang.String DISALLOW_REMOVE_USER = "no_remove_user";
     field public static final java.lang.String DISALLOW_SAFE_BOOT = "no_safe_boot";
@@ -36630,6 +36616,7 @@
     field public static final deprecated java.lang.String RADIO_NFC = "nfc";
     field public static final deprecated java.lang.String RADIO_WIFI = "wifi";
     field public static final java.lang.String RINGTONE = "ringtone";
+    field public static final java.lang.String RTT_CALLING_MODE = "rtt_calling_mode";
     field public static final java.lang.String SCREEN_BRIGHTNESS = "screen_brightness";
     field public static final java.lang.String SCREEN_BRIGHTNESS_MODE = "screen_brightness_mode";
     field public static final int SCREEN_BRIGHTNESS_MODE_AUTOMATIC = 1; // 0x1
@@ -36773,6 +36760,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";
@@ -38432,6 +38426,7 @@
     method public boolean isRandomizedEncryptionRequired();
     method public boolean isStrongBoxBacked();
     method public boolean isTrustedUserPresenceRequired();
+    method public boolean isUnlockedDeviceRequired();
     method public boolean isUserAuthenticationRequired();
     method public boolean isUserAuthenticationValidWhileOnBody();
     method public boolean isUserConfirmationRequired();
@@ -38459,6 +38454,7 @@
     method public android.security.keystore.KeyGenParameterSpec.Builder setRandomizedEncryptionRequired(boolean);
     method public android.security.keystore.KeyGenParameterSpec.Builder setSignaturePaddings(java.lang.String...);
     method public android.security.keystore.KeyGenParameterSpec.Builder setTrustedUserPresenceRequired(boolean);
+    method public android.security.keystore.KeyGenParameterSpec.Builder setUnlockedDeviceRequired(boolean);
     method public android.security.keystore.KeyGenParameterSpec.Builder setUserAuthenticationRequired(boolean);
     method public android.security.keystore.KeyGenParameterSpec.Builder setUserAuthenticationValidWhileOnBody(boolean);
     method public android.security.keystore.KeyGenParameterSpec.Builder setUserAuthenticationValidityDurationSeconds(int);
@@ -38550,6 +38546,8 @@
     method public boolean isDigestsSpecified();
     method public boolean isInvalidatedByBiometricEnrollment();
     method public boolean isRandomizedEncryptionRequired();
+    method public boolean isTrustedUserPresenceRequired();
+    method public boolean isUnlockedDeviceRequired();
     method public boolean isUserAuthenticationRequired();
     method public boolean isUserAuthenticationValidWhileOnBody();
     method public boolean isUserConfirmationRequired();
@@ -38568,6 +38566,8 @@
     method public android.security.keystore.KeyProtection.Builder setKeyValidityStart(java.util.Date);
     method public android.security.keystore.KeyProtection.Builder setRandomizedEncryptionRequired(boolean);
     method public android.security.keystore.KeyProtection.Builder setSignaturePaddings(java.lang.String...);
+    method public android.security.keystore.KeyProtection.Builder setTrustedUserPresenceRequired(boolean);
+    method public android.security.keystore.KeyProtection.Builder setUnlockedDeviceRequired(boolean);
     method public android.security.keystore.KeyProtection.Builder setUserAuthenticationRequired(boolean);
     method public android.security.keystore.KeyProtection.Builder setUserAuthenticationValidWhileOnBody(boolean);
     method public android.security.keystore.KeyProtection.Builder setUserAuthenticationValidityDurationSeconds(int);
@@ -38670,14 +38670,14 @@
   }
 
   public final class DateTransformation implements android.os.Parcelable android.service.autofill.Transformation {
-    ctor public DateTransformation(android.view.autofill.AutofillId, java.text.DateFormat);
+    ctor public DateTransformation(android.view.autofill.AutofillId, android.icu.text.DateFormat);
     method public int describeContents();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.service.autofill.DateTransformation> CREATOR;
   }
 
   public final class DateValueSanitizer implements android.os.Parcelable android.service.autofill.Sanitizer {
-    ctor public DateValueSanitizer(java.text.DateFormat);
+    ctor public DateValueSanitizer(android.icu.text.DateFormat);
     method public int describeContents();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.service.autofill.DateValueSanitizer> CREATOR;
@@ -38688,7 +38688,7 @@
   }
 
   public static final class FieldClassification.Match {
-    method public java.lang.String getRemoteId();
+    method public java.lang.String getCategoryId();
     method public float getScore();
   }
 
@@ -38853,6 +38853,7 @@
     method public int describeContents();
     method public java.lang.String getFieldClassificationAlgorithm();
     method public java.lang.String getId();
+    method public static int getMaxCategoryCount();
     method public static int getMaxFieldClassificationIdsSize();
     method public static int getMaxUserDataSize();
     method public static int getMaxValueLength();
@@ -40505,6 +40506,7 @@
   public final class Call {
     method public void answer(int);
     method public void conference(android.telecom.Call);
+    method public void deflect(android.net.Uri);
     method public void disconnect();
     method public java.util.List<java.lang.String> getCannedTextResponses();
     method public java.util.List<android.telecom.Call> getChildren();
@@ -40615,6 +40617,7 @@
     field public static final int CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL = 3072; // 0xc00
     field public static final int CAPABILITY_SUPPORTS_VT_REMOTE_RX = 1024; // 0x400
     field public static final int CAPABILITY_SUPPORTS_VT_REMOTE_TX = 2048; // 0x800
+    field public static final int CAPABILITY_SUPPORT_DEFLECT = 16777216; // 0x1000000
     field public static final int CAPABILITY_SUPPORT_HOLD = 2; // 0x2
     field public static final int CAPABILITY_SWAP_CONFERENCE = 8; // 0x8
     field public static final int PROPERTY_ASSISTED_DIALING_USED = 512; // 0x200
@@ -40625,6 +40628,7 @@
     field public static final int PROPERTY_HAS_CDMA_VOICE_PRIVACY = 128; // 0x80
     field public static final int PROPERTY_HIGH_DEF_AUDIO = 16; // 0x10
     field public static final int PROPERTY_IS_EXTERNAL_CALL = 64; // 0x40
+    field public static final int PROPERTY_RTT = 1024; // 0x400
     field public static final int PROPERTY_SELF_MANAGED = 256; // 0x100
     field public static final int PROPERTY_WIFI = 8; // 0x8
   }
@@ -40718,8 +40722,8 @@
     method public final void setActive();
     method public final void setConferenceableConnections(java.util.List<android.telecom.Connection>);
     method public final void setConnectionCapabilities(int);
-    method public final void setConnectionElapsedTime(long);
     method public final void setConnectionProperties(int);
+    method public final void setConnectionStartElapsedRealTime(long);
     method public final void setConnectionTime(long);
     method public final void setDialing();
     method public final void setDisconnected(android.telecom.DisconnectCause);
@@ -40762,6 +40766,7 @@
     method public void onAnswer();
     method public void onCallAudioStateChanged(android.telecom.CallAudioState);
     method public void onCallEvent(java.lang.String, android.os.Bundle);
+    method public void onDeflect(android.net.Uri);
     method public void onDisconnect();
     method public void onExtrasChanged(android.os.Bundle);
     method public void onHandoverComplete();
@@ -40830,6 +40835,7 @@
     field public static final int CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL = 3072; // 0xc00
     field public static final int CAPABILITY_SUPPORTS_VT_REMOTE_RX = 1024; // 0x400
     field public static final int CAPABILITY_SUPPORTS_VT_REMOTE_TX = 2048; // 0x800
+    field public static final int CAPABILITY_SUPPORT_DEFLECT = 33554432; // 0x2000000
     field public static final int CAPABILITY_SUPPORT_HOLD = 2; // 0x2
     field public static final int CAPABILITY_SWAP_CONFERENCE = 8; // 0x8
     field public static final java.lang.String EVENT_CALL_MERGE_FAILED = "android.telecom.event.CALL_MERGE_FAILED";
@@ -42193,13 +42199,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();
@@ -42584,6 +42593,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 {
@@ -44424,10 +44471,12 @@
 
   public class TypefaceSpan extends android.text.style.MetricAffectingSpan implements android.text.ParcelableSpan {
     ctor public TypefaceSpan(java.lang.String);
+    ctor public TypefaceSpan(android.graphics.Typeface);
     ctor public TypefaceSpan(android.os.Parcel);
     method public int describeContents();
     method public java.lang.String getFamily();
     method public int getSpanTypeId();
+    method public android.graphics.Typeface getTypeface();
     method public void updateDrawState(android.text.TextPaint);
     method public void updateMeasureState(android.text.TextPaint);
     method public void writeToParcel(android.os.Parcel, int);
@@ -44898,6 +44947,7 @@
     method public abstract int getAttributeListValue(int, java.lang.String[], int);
     method public abstract java.lang.String getAttributeName(int);
     method public abstract int getAttributeNameResource(int);
+    method public default java.lang.String getAttributeNamespace(int);
     method public abstract int getAttributeResourceValue(java.lang.String, java.lang.String, int);
     method public abstract int getAttributeResourceValue(int, int);
     method public abstract int getAttributeUnsignedIntValue(java.lang.String, java.lang.String, int);
@@ -48147,8 +48197,6 @@
     method public void notifySubtreeAccessibilityStateChanged(android.view.View, android.view.View, int);
     method public final void offsetDescendantRectToMyCoords(android.view.View, android.graphics.Rect);
     method public final void offsetRectIntoDescendantCoords(android.view.View, android.graphics.Rect);
-    method protected void onDebugDraw(android.graphics.Canvas);
-    method protected void onDebugDrawMargins(android.graphics.Canvas, android.graphics.Paint);
     method public boolean onInterceptHoverEvent(android.view.MotionEvent);
     method public boolean onInterceptTouchEvent(android.view.MotionEvent);
     method protected abstract void onLayout(boolean, int, int, int, int);
@@ -48222,7 +48270,6 @@
     ctor public ViewGroup.LayoutParams(android.content.Context, android.util.AttributeSet);
     ctor public ViewGroup.LayoutParams(int, int);
     ctor public ViewGroup.LayoutParams(android.view.ViewGroup.LayoutParams);
-    method public void onDebugDraw(android.view.View, android.graphics.Canvas, android.graphics.Paint);
     method public void resolveLayoutDirection(int);
     method protected void setBaseAttributes(android.content.res.TypedArray, int, int);
     field public static final deprecated int FILL_PARENT = -1; // 0xffffffff
@@ -48410,6 +48457,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);
@@ -49733,6 +49781,8 @@
     method public boolean isFieldClassificationEnabled();
     method public void notifyValueChanged(android.view.View);
     method public void notifyValueChanged(android.view.View, int, android.view.autofill.AutofillValue);
+    method public void notifyViewClicked(android.view.View);
+    method public void notifyViewClicked(android.view.View, int);
     method public void notifyViewEntered(android.view.View);
     method public void notifyViewEntered(android.view.View, int, android.graphics.Rect);
     method public void notifyViewExited(android.view.View);
@@ -50240,6 +50290,7 @@
     method public default android.view.textclassifier.TextLinks generateLinks(java.lang.CharSequence);
     method public default java.util.Collection<java.lang.String> getEntitiesForPreset(int);
     method public default android.view.textclassifier.logging.Logger getLogger(android.view.textclassifier.logging.Logger.Config);
+    method public default int getMaxGenerateLinksTextLength();
     method public default android.view.textclassifier.TextSelection suggestSelection(java.lang.CharSequence, int, int, android.view.textclassifier.TextSelection.Options);
     method public default android.view.textclassifier.TextSelection suggestSelection(java.lang.CharSequence, int, int);
     method public default android.view.textclassifier.TextSelection suggestSelection(java.lang.CharSequence, int, int, android.os.LocaleList);
@@ -50362,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
@@ -50392,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();
@@ -50416,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
   }
 
 }
@@ -50691,41 +50745,37 @@
   }
 
   public class TracingConfig {
-    ctor public TracingConfig(int);
-    ctor public TracingConfig(int, java.lang.String, int);
-    method public java.lang.String getCustomCategoryPattern();
-    method public int getPresetCategories();
+    method public java.util.List<java.lang.String> getCustomIncludedCategories();
+    method public int getPredefinedCategories();
     method public int getTracingMode();
-    field public static final int CATEGORIES_FRAME_VIEWER = 4; // 0x4
-    field public static final int CATEGORIES_INPUT_LATENCY = 1; // 0x1
-    field public static final int CATEGORIES_JAVASCRIPT_AND_RENDERING = 3; // 0x3
-    field public static final int CATEGORIES_NONE = -1; // 0xffffffff
-    field public static final int CATEGORIES_RENDERING = 2; // 0x2
-    field public static final int CATEGORIES_WEB_DEVELOPER = 0; // 0x0
+    field public static final int CATEGORIES_ALL = 1; // 0x1
+    field public static final int CATEGORIES_ANDROID_WEBVIEW = 2; // 0x2
+    field public static final int CATEGORIES_FRAME_VIEWER = 64; // 0x40
+    field public static final int CATEGORIES_INPUT_LATENCY = 8; // 0x8
+    field public static final int CATEGORIES_JAVASCRIPT_AND_RENDERING = 32; // 0x20
+    field public static final int CATEGORIES_NONE = 0; // 0x0
+    field public static final int CATEGORIES_RENDERING = 16; // 0x10
+    field public static final int CATEGORIES_WEB_DEVELOPER = 4; // 0x4
     field public static final int RECORD_CONTINUOUSLY = 1; // 0x1
-    field public static final int RECORD_TO_CONSOLE = 3; // 0x3
     field public static final int RECORD_UNTIL_FULL = 0; // 0x0
     field public static final int RECORD_UNTIL_FULL_LARGE_BUFFER = 2; // 0x2
   }
 
+  public static class TracingConfig.Builder {
+    ctor public TracingConfig.Builder();
+    method public android.webkit.TracingConfig.Builder addCategories(int...);
+    method public android.webkit.TracingConfig.Builder addCategories(java.lang.String...);
+    method public android.webkit.TracingConfig.Builder addCategories(java.util.Collection<java.lang.String>);
+    method public android.webkit.TracingConfig build();
+    method public android.webkit.TracingConfig.Builder setTracingMode(int);
+  }
+
   public abstract class TracingController {
     ctor public TracingController();
     method public static android.webkit.TracingController getInstance();
     method public abstract boolean isTracing();
-    method public abstract boolean start(android.webkit.TracingConfig);
-    method public abstract boolean stop();
-    method public abstract boolean stopAndFlush(android.webkit.TracingController.TracingOutputStream, android.os.Handler);
-  }
-
-  public static abstract interface TracingController.TracingOutputStream {
-    method public abstract void complete();
-    method public abstract void write(byte[]);
-  }
-
-  public class TracingFileOutputStream implements android.webkit.TracingController.TracingOutputStream {
-    ctor public TracingFileOutputStream(java.lang.String) throws java.io.FileNotFoundException;
-    method public void complete();
-    method public void write(byte[]);
+    method public abstract void start(android.webkit.TracingConfig);
+    method public abstract boolean stop(java.io.OutputStream, java.util.concurrent.Executor);
   }
 
   public final class URLUtil {
diff --git a/api/removed.txt b/api/removed.txt
index 2aab223..55022f3 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -257,6 +257,12 @@
     ctor public RecoverySystem();
   }
 
+  public final class SystemClock {
+    method public static java.time.Clock elapsedRealtimeClock();
+    method public static java.time.Clock uptimeClock();
+    method public static deprecated java.time.Clock uptimeMillisClock();
+  }
+
   public class TestLooperManager {
     method public deprecated android.os.MessageQueue getQueue();
   }
diff --git a/api/system-current.txt b/api/system-current.txt
index 2d3b65a..930224d 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";
@@ -30,8 +31,8 @@
     field public static final java.lang.String BIND_RUNTIME_PERMISSION_PRESENTER_SERVICE = "android.permission.BIND_RUNTIME_PERMISSION_PRESENTER_SERVICE";
     field public static final java.lang.String BIND_SETTINGS_SUGGESTIONS_SERVICE = "android.permission.BIND_SETTINGS_SUGGESTIONS_SERVICE";
     field public static final java.lang.String BIND_TELEPHONY_DATA_SERVICE = "android.permission.BIND_TELEPHONY_DATA_SERVICE";
-    field public static final java.lang.String BIND_TEXTCLASSIFIER_SERVICE = "android.permission.BIND_TEXTCLASSIFIER_SERVICE";
     field public static final java.lang.String BIND_TELEPHONY_NETWORK_SERVICE = "android.permission.BIND_TELEPHONY_NETWORK_SERVICE";
+    field public static final java.lang.String BIND_TEXTCLASSIFIER_SERVICE = "android.permission.BIND_TEXTCLASSIFIER_SERVICE";
     field public static final java.lang.String BIND_TRUST_AGENT = "android.permission.BIND_TRUST_AGENT";
     field public static final java.lang.String BIND_TV_REMOTE_SERVICE = "android.permission.BIND_TV_REMOTE_SERVICE";
     field public static final java.lang.String BLUETOOTH_PRIVILEGED = "android.permission.BLUETOOTH_PRIVILEGED";
@@ -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";
@@ -227,7 +229,6 @@
     method public boolean convertToTranslucent(android.app.Activity.TranslucentConversionListener, android.app.ActivityOptions);
     method public deprecated boolean isBackgroundVisibleBehind();
     method public deprecated void onBackgroundVisibleBehindChanged(boolean);
-    method public void setDisablePreviewScreenshots(boolean);
   }
 
   public static abstract interface Activity.TranslucentConversionListener {
@@ -341,11 +342,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 {
@@ -362,10 +365,12 @@
 
   public final class StatsManager {
     method public boolean addConfiguration(long, byte[], java.lang.String, java.lang.String);
+    method public boolean addConfiguration(long, byte[]);
     method public byte[] getData(long);
     method public byte[] getMetadata();
     method public boolean removeConfiguration(long);
     method public boolean setBroadcastSubscriber(long, long, android.app.PendingIntent);
+    method public boolean setDataFetchOperation(long, android.app.PendingIntent);
     field public static final java.lang.String ACTION_STATSD_STARTED = "android.app.action.STATSD_STARTED";
     field public static final java.lang.String EXTRA_STATS_CONFIG_KEY = "android.app.extra.STATS_CONFIG_KEY";
     field public static final java.lang.String EXTRA_STATS_CONFIG_UID = "android.app.extra.STATS_CONFIG_UID";
@@ -431,6 +436,19 @@
     field public static final int STATE_USER_UNMANAGED = 0; // 0x0
   }
 
+  public class SystemUpdatePolicy implements android.os.Parcelable {
+    method public int describeContents();
+    method public android.app.admin.SystemUpdatePolicy.InstallationOption getInstallationOptionAt(long);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.app.admin.SystemUpdatePolicy> CREATOR;
+    field public static final int TYPE_PAUSE = 4; // 0x4
+  }
+
+  public static class SystemUpdatePolicy.InstallationOption {
+    method public long getEffectiveTime();
+    method public int getType();
+  }
+
 }
 
 package android.app.backup {
@@ -687,6 +705,12 @@
     field public static final java.lang.String SERVICE_INTERFACE = "android.app.usage.CacheQuotaService";
   }
 
+  public static final class UsageEvents.Event {
+    method public int getStandbyBucket();
+    field public static final int NOTIFICATION_SEEN = 10; // 0xa
+    field public static final int STANDBY_BUCKET_CHANGED = 11; // 0xb
+  }
+
   public final class UsageStatsManager {
     method public int getAppStandbyBucket(java.lang.String);
     method public java.util.Map<java.lang.String, java.lang.Integer> getAppStandbyBuckets();
@@ -783,6 +807,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";
@@ -791,7 +816,7 @@
     field public static final java.lang.String STATS_MANAGER = "stats";
     field public static final java.lang.String SYSTEM_UPDATE_SERVICE = "system_update";
     field public static final java.lang.String VR_SERVICE = "vrmanager";
-    field public static final java.lang.String WIFI_RTT_SERVICE = "rttmanager";
+    field public static final deprecated java.lang.String WIFI_RTT_SERVICE = "rttmanager";
     field public static final java.lang.String WIFI_SCANNING_SERVICE = "wifiscanner";
   }
 
@@ -821,6 +846,7 @@
     field public static final java.lang.String ACTION_RESOLVE_INSTANT_APP_PACKAGE = "android.intent.action.RESOLVE_INSTANT_APP_PACKAGE";
     field public static final java.lang.String ACTION_REVIEW_PERMISSIONS = "android.intent.action.REVIEW_PERMISSIONS";
     field public static final deprecated java.lang.String ACTION_SIM_STATE_CHANGED = "android.intent.action.SIM_STATE_CHANGED";
+    field public static final java.lang.String ACTION_SPLIT_CONFIGURATION_CHANGED = "android.intent.action.SPLIT_CONFIGURATION_CHANGED";
     field public static final java.lang.String ACTION_UPGRADE_SETUP = "android.intent.action.UPGRADE_SETUP";
     field public static final java.lang.String ACTION_USER_REMOVED = "android.intent.action.USER_REMOVED";
     field public static final java.lang.String ACTION_VOICE_ASSIST = "android.intent.action.VOICE_ASSIST";
@@ -2510,12 +2536,15 @@
 
   public class AudioManager {
     method public deprecated int abandonAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, android.media.AudioAttributes);
+    method public void clearAudioServerStateCallback();
     method public int dispatchAudioFocusChange(android.media.AudioFocusInfo, int, android.media.audiopolicy.AudioPolicy);
+    method public boolean isAudioServerRunning();
     method public boolean isHdmiSystemAudioSupported();
     method public int registerAudioPolicy(android.media.audiopolicy.AudioPolicy);
     method public int requestAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, android.media.AudioAttributes, int, int) throws java.lang.IllegalArgumentException;
     method public deprecated int requestAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, android.media.AudioAttributes, int, int, android.media.audiopolicy.AudioPolicy) throws java.lang.IllegalArgumentException;
     method public int requestAudioFocus(android.media.AudioFocusRequest, android.media.audiopolicy.AudioPolicy);
+    method public void setAudioServerStateCallback(java.util.concurrent.Executor, android.media.AudioManager.AudioServerStateCallback);
     method public void setFocusRequestResult(android.media.AudioFocusInfo, int, android.media.audiopolicy.AudioPolicy);
     method public void unregisterAudioPolicyAsync(android.media.audiopolicy.AudioPolicy);
     field public static final int AUDIOFOCUS_FLAG_DELAY_OK = 1; // 0x1
@@ -2523,6 +2552,12 @@
     field public static final int AUDIOFOCUS_FLAG_PAUSES_ON_DUCKABLE_LOSS = 2; // 0x2
   }
 
+  public static abstract class AudioManager.AudioServerStateCallback {
+    ctor public AudioManager.AudioServerStateCallback();
+    method public void onAudioServerDown();
+    method public void onAudioServerUp();
+  }
+
   public final class AudioPlaybackConfiguration implements android.os.Parcelable {
     method public int getClientPid();
     method public int getClientUid();
@@ -3091,7 +3126,7 @@
 
 package android.net.wifi {
 
-  public class RttManager {
+  public deprecated class RttManager {
     method public void disableResponder(android.net.wifi.RttManager.ResponderCallback);
     method public void enableResponder(android.net.wifi.RttManager.ResponderCallback);
     method public deprecated android.net.wifi.RttManager.Capabilities getCapabilities();
@@ -3167,22 +3202,22 @@
     field public int supportedType;
   }
 
-  public static class RttManager.ParcelableRttParams implements android.os.Parcelable {
+  public static deprecated class RttManager.ParcelableRttParams implements android.os.Parcelable {
     field public android.net.wifi.RttManager.RttParams[] mParams;
   }
 
-  public static class RttManager.ParcelableRttResults implements android.os.Parcelable {
+  public static deprecated class RttManager.ParcelableRttResults implements android.os.Parcelable {
     ctor public RttManager.ParcelableRttResults(android.net.wifi.RttManager.RttResult[]);
     field public android.net.wifi.RttManager.RttResult[] mResults;
   }
 
-  public static abstract class RttManager.ResponderCallback {
+  public static abstract deprecated class RttManager.ResponderCallback {
     ctor public RttManager.ResponderCallback();
     method public abstract void onResponderEnableFailure(int);
     method public abstract void onResponderEnabled(android.net.wifi.RttManager.ResponderConfig);
   }
 
-  public static class RttManager.ResponderConfig implements android.os.Parcelable {
+  public static deprecated class RttManager.ResponderConfig implements android.os.Parcelable {
     ctor public RttManager.ResponderConfig();
     method public int describeContents();
     method public void writeToParcel(android.os.Parcel, int);
@@ -3195,7 +3230,7 @@
     field public int preamble;
   }
 
-  public static class RttManager.RttCapabilities implements android.os.Parcelable {
+  public static deprecated class RttManager.RttCapabilities implements android.os.Parcelable {
     ctor public RttManager.RttCapabilities();
     field public int bwSupported;
     field public boolean lciSupported;
@@ -3210,13 +3245,13 @@
     field public boolean twoSided11McRttSupported;
   }
 
-  public static abstract interface RttManager.RttListener {
+  public static abstract deprecated interface RttManager.RttListener {
     method public abstract void onAborted();
     method public abstract void onFailure(int, java.lang.String);
     method public abstract void onSuccess(android.net.wifi.RttManager.RttResult[]);
   }
 
-  public static class RttManager.RttParams {
+  public static deprecated class RttManager.RttParams {
     ctor public RttManager.RttParams();
     field public boolean LCIRequest;
     field public boolean LCRRequest;
@@ -3240,7 +3275,7 @@
     field public boolean secure;
   }
 
-  public static class RttManager.RttResult {
+  public static deprecated class RttManager.RttResult {
     ctor public RttManager.RttResult();
     field public android.net.wifi.RttManager.WifiInformationElement LCI;
     field public android.net.wifi.RttManager.WifiInformationElement LCR;
@@ -3277,7 +3312,7 @@
     field public deprecated int tx_rate;
   }
 
-  public static class RttManager.WifiInformationElement {
+  public static deprecated class RttManager.WifiInformationElement {
     ctor public RttManager.WifiInformationElement();
     field public byte[] data;
     field public byte id;
@@ -3489,6 +3524,11 @@
     method public android.net.wifi.rtt.RangingRequest.Builder addResponder(android.net.wifi.rtt.ResponderConfig);
   }
 
+  public final class RangingResult implements android.os.Parcelable {
+    method public byte[] getLci();
+    method public byte[] getLcr();
+  }
+
   public final class ResponderConfig implements android.os.Parcelable {
     ctor public ResponderConfig(android.net.MacAddress, int, boolean, int, int, int, int, int);
     ctor public ResponderConfig(android.net.wifi.aware.PeerHandle, int, boolean, int, int, int, int, int);
@@ -3524,7 +3564,7 @@
 
   public class WifiRttManager {
     method public void cancelRanging(android.os.WorkSource);
-    method public void startRanging(android.os.WorkSource, android.net.wifi.rtt.RangingRequest, android.net.wifi.rtt.RangingResultCallback, android.os.Handler);
+    method public void startRanging(android.os.WorkSource, android.net.wifi.rtt.RangingRequest, java.util.concurrent.Executor, android.net.wifi.rtt.RangingResultCallback);
   }
 
 }
@@ -3570,11 +3610,14 @@
   }
 
   public abstract class HwBinder implements android.os.IHwBinder {
+    ctor public HwBinder();
     method public static final void configureRpcThreadpool(long, boolean);
     method public static void enableInstrumentation();
     method public static final android.os.IHwBinder getService(java.lang.String, java.lang.String) throws java.util.NoSuchElementException, android.os.RemoteException;
     method public static final android.os.IHwBinder getService(java.lang.String, java.lang.String, boolean) throws java.util.NoSuchElementException, android.os.RemoteException;
     method public static final void joinRpcThreadpool();
+    method public abstract void onTransact(int, android.os.HwParcel, android.os.HwParcel, int) throws android.os.RemoteException;
+    method public final void registerService(java.lang.String) throws android.os.RemoteException;
     method public final void transact(int, android.os.HwParcel, android.os.HwParcel, int) throws android.os.RemoteException;
   }
 
@@ -3797,6 +3840,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 {
@@ -4124,6 +4168,9 @@
     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 INSTALL_CARRIER_APP_NOTIFICATION_PERSISTENT = "install_carrier_app_notification_persistent";
+    field public static final java.lang.String INSTALL_CARRIER_APP_NOTIFICATION_SLEEP_MILLIS = "install_carrier_app_notification_sleep_millis";
     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";
@@ -4135,6 +4182,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_FEATURE_FIELD_CLASSIFICATION = "autofill_field_classification";
+    field public static final java.lang.String AUTOFILL_USER_DATA_MAX_CATEGORY_COUNT = "autofill_user_data_max_category_count";
     field public static final java.lang.String AUTOFILL_USER_DATA_MAX_FIELD_CLASSIFICATION_IDS_SIZE = "autofill_user_data_max_field_classification_size";
     field public static final java.lang.String AUTOFILL_USER_DATA_MAX_USER_DATA_SIZE = "autofill_user_data_max_user_data_size";
     field public static final java.lang.String AUTOFILL_USER_DATA_MAX_VALUE_LENGTH = "autofill_user_data_max_value_length";
@@ -4297,6 +4345,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 {
@@ -4897,8 +5064,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>);
@@ -5034,23 +5207,30 @@
     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);
+    ctor public UiccSlotInfo(boolean, boolean, java.lang.String, int, int);
     method public int describeContents();
     method public java.lang.String getCardId();
     method public int getCardStateInfo();
     method public boolean getIsActive();
     method public boolean getIsEuicc();
+    method public int getLogicalSlotIdx();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final int CARD_STATE_INFO_ABSENT = 1; // 0x1
     field public static final int CARD_STATE_INFO_ERROR = 3; // 0x3
     field public static final int CARD_STATE_INFO_PRESENT = 2; // 0x2
     field public static final int CARD_STATE_INFO_RESTRICTED = 4; // 0x4
     field public static final android.os.Parcelable.Creator<android.telephony.UiccSlotInfo> CREATOR;
-    field public final java.lang.String cardId;
-    field public final int cardStateInfo;
-    field public final boolean isActive;
-    field public final boolean isEuicc;
   }
 
   public abstract class VisualVoicemailService extends android.app.Service {
@@ -5147,6 +5327,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 {
@@ -5711,6 +6010,7 @@
     ctor public ImsCallSessionImplBase();
     method public void accept(int, android.telephony.ims.ImsStreamMediaProfile);
     method public void close();
+    method public void deflect(java.lang.String);
     method public void extendToConference(java.lang.String[]);
     method public java.lang.String getCallId();
     method public android.telephony.ims.ImsCallProfile getCallProfile();
diff --git a/api/test-current.txt b/api/test-current.txt
index c30c056..92251f7 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -185,6 +185,7 @@
   public abstract class Context {
     method public android.os.UserHandle getUser();
     method public int getUserId();
+    method public void setAutofillCompatibilityEnabled(boolean);
   }
 
 }
@@ -532,6 +533,7 @@
   }
 
   public static final class Settings.Global extends android.provider.Settings.NameValueTable {
+    field public static final java.lang.String AUTOFILL_COMPAT_ALLOWED_PACKAGES = "autofill_compat_allowed_packages";
     field public static final java.lang.String LOCATION_GLOBAL_KILL_SWITCH = "location_global_kill_switch";
     field public static final java.lang.String LOW_POWER_MODE = "low_power";
     field public static final java.lang.String USE_OPEN_WIFI_PACKAGE = "use_open_wifi_package";
@@ -541,6 +543,7 @@
     field public static final java.lang.String ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED = "accessibility_display_magnification_enabled";
     field public static final java.lang.String AUTOFILL_FEATURE_FIELD_CLASSIFICATION = "autofill_field_classification";
     field public static final java.lang.String AUTOFILL_SERVICE = "autofill_service";
+    field public static final java.lang.String AUTOFILL_USER_DATA_MAX_CATEGORY_COUNT = "autofill_user_data_max_category_count";
     field public static final java.lang.String AUTOFILL_USER_DATA_MAX_FIELD_CLASSIFICATION_IDS_SIZE = "autofill_user_data_max_field_classification_size";
     field public static final java.lang.String AUTOFILL_USER_DATA_MAX_USER_DATA_SIZE = "autofill_user_data_max_user_data_size";
     field public static final java.lang.String AUTOFILL_USER_DATA_MAX_VALUE_LENGTH = "autofill_user_data_max_value_length";
@@ -1038,6 +1041,7 @@
 
   public class AccessibilityNodeInfo implements android.os.Parcelable {
     method public static void setNumInstancesInUseCounter(java.util.concurrent.atomic.AtomicInteger);
+    method public void writeToParcelNoRecycle(android.os.Parcel, int);
   }
 
   public final class AccessibilityWindowInfo implements android.os.Parcelable {
@@ -1046,10 +1050,20 @@
 
 }
 
+package android.view.animation {
+
+  public class AnimationUtils {
+    method public static void lockAnimationClock(long);
+    method public static void unlockAnimationClock();
+  }
+
+}
+
 package android.view.autofill {
 
   public final class AutofillId implements android.os.Parcelable {
     ctor public AutofillId(int);
+    ctor public AutofillId(android.view.autofill.AutofillId, int);
   }
 
 }
@@ -1078,6 +1092,12 @@
     field public static final int MODE_SPINNER = 1; // 0x1
   }
 
+  public final class Magnifier {
+    method public android.graphics.Bitmap getContent();
+    method public static android.graphics.PointF getMagnifierDefaultSize();
+    method public android.graphics.Rect getWindowPositionOnScreen();
+  }
+
   public class NumberPicker extends android.widget.LinearLayout {
     method public java.lang.CharSequence getDisplayedValueForCurrentSelection();
   }
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index 813335a..c04e61b 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -172,6 +172,8 @@
             } else if (opt.equals("--no_window_animation")
                     || opt.equals("--no-window-animation")) {
                 instrument.noWindowAnimation = true;
+            } else if (opt.equals("--no-hidden-api-checks")) {
+                instrument.disableHiddenApiChecks = true;
             } else if (opt.equals("--user")) {
                 instrument.userId = parseUserArg(nextArgRequired());
             } else if (opt.equals("--abi")) {
diff --git a/cmds/am/src/com/android/commands/am/Instrument.java b/cmds/am/src/com/android/commands/am/Instrument.java
index d79b1a6..0dade0b 100644
--- a/cmds/am/src/com/android/commands/am/Instrument.java
+++ b/cmds/am/src/com/android/commands/am/Instrument.java
@@ -73,12 +73,17 @@
     boolean protoFile = false;  // write proto to a file
     String logPath = null;
     public boolean noWindowAnimation = false;
+    public boolean disableHiddenApiChecks = false;
     public String abi = null;
     public int userId = UserHandle.USER_CURRENT;
     public Bundle args = new Bundle();
     // Required
     public String componentNameArg;
 
+    // Disable hidden API checks for the newly started instrumentation.
+    // Must be kept in sync with ActivityManagerService.
+    private static final int INSTRUMENTATION_FLAG_DISABLE_HIDDEN_API_CHECKS = 1 << 0;
+
     /**
      * Construct the instrument command runner.
      */
@@ -475,7 +480,8 @@
             }
 
             // Start the instrumentation
-            if (!mAm.startInstrumentation(cn, profileFile, 0, args, watcher, connection, userId,
+            int flags = disableHiddenApiChecks ? INSTRUMENTATION_FLAG_DISABLE_HIDDEN_API_CHECKS : 0;
+            if (!mAm.startInstrumentation(cn, profileFile, flags, args, watcher, connection, userId,
                         abi)) {
                 throw new AndroidException("INSTRUMENTATION_FAILED: " + cn.flattenToString());
             }
diff --git a/cmds/incident_helper/OWNERS b/cmds/incident_helper/OWNERS
new file mode 100644
index 0000000..1a68a32
--- /dev/null
+++ b/cmds/incident_helper/OWNERS
@@ -0,0 +1,2 @@
+jinyithu@google.com
+kwekua@google.com
diff --git a/cmds/incident_helper/src/parsers/CpuFreqParser.cpp b/cmds/incident_helper/src/parsers/CpuFreqParser.cpp
index 02f1ce7..fde17bd 100644
--- a/cmds/incident_helper/src/parsers/CpuFreqParser.cpp
+++ b/cmds/incident_helper/src/parsers/CpuFreqParser.cpp
@@ -62,15 +62,15 @@
     ProtoOutputStream proto;
 
     long jiffyHz = sysconf(_SC_CLK_TCK);
-    proto.write(CpuFreq::JIFFY_HZ, (int)jiffyHz);
+    proto.write(CpuFreqProto::JIFFY_HZ, (int)jiffyHz);
 
     for (int i=0; i<numCpus; i++) {
-        long long token = proto.start(CpuFreq::CPU_FREQS);
-        proto.write(CpuFreqStats::CPU_NAME, header[i+1]);
+        long long token = proto.start(CpuFreqProto::CPU_FREQS);
+        proto.write(CpuFreqProto::Stats::CPU_NAME, header[i+1]);
         for (vector<pair<int, long long>>::iterator it = cpucores[i].begin(); it != cpucores[i].end(); it++) {
-            long long stateToken = proto.start(CpuFreqStats::TIMES);
-            proto.write(CpuFreqStats::TimeInState::STATE_KHZ, it->first);
-            proto.write(CpuFreqStats::TimeInState::TIME_JIFFY, it->second);
+            long long stateToken = proto.start(CpuFreqProto::Stats::TIMES);
+            proto.write(CpuFreqProto::Stats::TimeInState::STATE_KHZ, it->first);
+            proto.write(CpuFreqProto::Stats::TimeInState::TIME_JIFFY, it->second);
             proto.end(stateToken);
         }
         proto.end(token);
diff --git a/cmds/incident_helper/src/parsers/CpuInfoParser.cpp b/cmds/incident_helper/src/parsers/CpuInfoParser.cpp
index d73de54..b2b431c 100644
--- a/cmds/incident_helper/src/parsers/CpuInfoParser.cpp
+++ b/cmds/incident_helper/src/parsers/CpuInfoParser.cpp
@@ -54,11 +54,11 @@
     bool nextToUsage = false;
 
     ProtoOutputStream proto;
-    Table table(CpuInfo::Task::_FIELD_NAMES, CpuInfo::Task::_FIELD_IDS, CpuInfo::Task::_FIELD_COUNT);
-    table.addEnumTypeMap("s", CpuInfo::Task::_ENUM_STATUS_NAMES,
-            CpuInfo::Task::_ENUM_STATUS_VALUES, CpuInfo::Task::_ENUM_STATUS_COUNT);
-    table.addEnumTypeMap("pcy", CpuInfo::Task::_ENUM_POLICY_NAMES,
-            CpuInfo::Task::_ENUM_POLICY_VALUES, CpuInfo::Task::_ENUM_POLICY_COUNT);
+    Table table(CpuInfoProto::Task::_FIELD_NAMES, CpuInfoProto::Task::_FIELD_IDS, CpuInfoProto::Task::_FIELD_COUNT);
+    table.addEnumTypeMap("s", CpuInfoProto::Task::_ENUM_STATUS_NAMES,
+            CpuInfoProto::Task::_ENUM_STATUS_VALUES, CpuInfoProto::Task::_ENUM_STATUS_COUNT);
+    table.addEnumTypeMap("pcy", CpuInfoProto::Task::_ENUM_POLICY_NAMES,
+            CpuInfoProto::Task::_ENUM_POLICY_VALUES, CpuInfoProto::Task::_ENUM_POLICY_COUNT);
 
     // parse line by line
     while (reader.readLine(&line)) {
@@ -67,33 +67,33 @@
         nline++;
 
         if (stripPrefix(&line, "Tasks:")) {
-            writeSuffixLine(&proto, CpuInfo::TASK_STATS, line, COMMA_DELIMITER,
-                CpuInfo::TaskStats::_FIELD_COUNT,
-                CpuInfo::TaskStats::_FIELD_NAMES,
-                CpuInfo::TaskStats::_FIELD_IDS);
+            writeSuffixLine(&proto, CpuInfoProto::TASK_STATS, line, COMMA_DELIMITER,
+                CpuInfoProto::TaskStats::_FIELD_COUNT,
+                CpuInfoProto::TaskStats::_FIELD_NAMES,
+                CpuInfoProto::TaskStats::_FIELD_IDS);
             continue;
         }
         if (stripPrefix(&line, "Mem:")) {
-            writeSuffixLine(&proto, CpuInfo::MEM, line, COMMA_DELIMITER,
-                CpuInfo::MemStats::_FIELD_COUNT,
-                CpuInfo::MemStats::_FIELD_NAMES,
-                CpuInfo::MemStats::_FIELD_IDS);
+            writeSuffixLine(&proto, CpuInfoProto::MEM, line, COMMA_DELIMITER,
+                CpuInfoProto::MemStats::_FIELD_COUNT,
+                CpuInfoProto::MemStats::_FIELD_NAMES,
+                CpuInfoProto::MemStats::_FIELD_IDS);
             continue;
         }
         if (stripPrefix(&line, "Swap:")) {
-            writeSuffixLine(&proto, CpuInfo::SWAP, line, COMMA_DELIMITER,
-                CpuInfo::MemStats::_FIELD_COUNT,
-                CpuInfo::MemStats::_FIELD_NAMES,
-                CpuInfo::MemStats::_FIELD_IDS);
+            writeSuffixLine(&proto, CpuInfoProto::SWAP, line, COMMA_DELIMITER,
+                CpuInfoProto::MemStats::_FIELD_COUNT,
+                CpuInfoProto::MemStats::_FIELD_NAMES,
+                CpuInfoProto::MemStats::_FIELD_IDS);
             nextToSwap = true;
             continue;
         }
 
         if (nextToSwap) {
-            writeSuffixLine(&proto, CpuInfo::CPU_USAGE, line, DEFAULT_WHITESPACE,
-                CpuInfo::CpuUsage::_FIELD_COUNT,
-                CpuInfo::CpuUsage::_FIELD_NAMES,
-                CpuInfo::CpuUsage::_FIELD_IDS);
+            writeSuffixLine(&proto, CpuInfoProto::CPU_USAGE, line, DEFAULT_WHITESPACE,
+                CpuInfoProto::CpuUsage::_FIELD_COUNT,
+                CpuInfoProto::CpuUsage::_FIELD_NAMES,
+                CpuInfoProto::CpuUsage::_FIELD_IDS);
             nextToUsage = true;
             nextToSwap = false;
             continue;
@@ -138,7 +138,7 @@
             continue;
         }
 
-        long long token = proto.start(CpuInfo::TASKS);
+        long long token = proto.start(CpuInfoProto::TASKS);
         for (int i=0; i<(int)record.size(); i++) {
             if (!table.insertField(&proto, header[i], record[i])) {
                 fprintf(stderr, "[%s]Line %d fails to insert field %s with value %s\n",
diff --git a/cmds/incident_helper/src/parsers/KernelWakesParser.cpp b/cmds/incident_helper/src/parsers/KernelWakesParser.cpp
index cae51ab..28816ea 100644
--- a/cmds/incident_helper/src/parsers/KernelWakesParser.cpp
+++ b/cmds/incident_helper/src/parsers/KernelWakesParser.cpp
@@ -33,7 +33,9 @@
     int nline = 0;
 
     ProtoOutputStream proto;
-    Table table(WakeupSourceProto::_FIELD_NAMES, WakeupSourceProto::_FIELD_IDS, WakeupSourceProto::_FIELD_COUNT);
+    Table table(KernelWakeSourcesProto::WakeupSource::_FIELD_NAMES,
+            KernelWakeSourcesProto::WakeupSource::_FIELD_IDS,
+            KernelWakeSourcesProto::WakeupSource::_FIELD_COUNT);
 
     // parse line by line
     while (reader.readLine(&line)) {
@@ -57,7 +59,7 @@
             continue;
         }
 
-        long long token = proto.start(KernelWakeSources::WAKEUP_SOURCES);
+        long long token = proto.start(KernelWakeSourcesProto::WAKEUP_SOURCES);
         for (int i=0; i<(int)record.size(); i++) {
             if (!table.insertField(&proto, header[i], record[i])) {
                 fprintf(stderr, "[%s]Line %d has bad value %s of %s\n",
diff --git a/cmds/incident_helper/src/parsers/PageTypeInfoParser.cpp b/cmds/incident_helper/src/parsers/PageTypeInfoParser.cpp
index f1b93ff..45a0e7b 100644
--- a/cmds/incident_helper/src/parsers/PageTypeInfoParser.cpp
+++ b/cmds/incident_helper/src/parsers/PageTypeInfoParser.cpp
@@ -33,7 +33,9 @@
     header_t blockHeader;
 
     ProtoOutputStream proto;
-    Table table(BlockProto::_FIELD_NAMES, BlockProto::_FIELD_IDS, BlockProto::_FIELD_COUNT);
+    Table table(PageTypeInfoProto::Block::_FIELD_NAMES,
+            PageTypeInfoProto::Block::_FIELD_IDS,
+            PageTypeInfoProto::Block::_FIELD_COUNT);
 
     while (reader.readLine(&line)) {
         if (line.empty()) {
@@ -44,11 +46,11 @@
 
         if (stripPrefix(&line, "Page block order:")) {
             pageBlockOrder = toInt(line);
-            proto.write(PageTypeInfo::PAGE_BLOCK_ORDER, pageBlockOrder);
+            proto.write(PageTypeInfoProto::PAGE_BLOCK_ORDER, pageBlockOrder);
             continue;
         }
         if (stripPrefix(&line, "Pages per block:")) {
-            proto.write(PageTypeInfo::PAGES_PER_BLOCK, toInt(line));
+            proto.write(PageTypeInfoProto::PAGES_PER_BLOCK, toInt(line));
             continue;
         }
         if (stripPrefix(&line, "Free pages count per migrate type at order")) {
@@ -62,14 +64,14 @@
 
         record_t record = parseRecord(line, COMMA_DELIMITER);
         if (migrateTypeSession && record.size() == 3) {
-            long long token = proto.start(PageTypeInfo::MIGRATE_TYPES);
+            long long token = proto.start(PageTypeInfoProto::MIGRATE_TYPES);
             // expect part 0 starts with "Node"
             if (stripPrefix(&record[0], "Node")) {
-                proto.write(MigrateTypeProto::NODE, toInt(record[0]));
+                proto.write(PageTypeInfoProto::MigrateType::NODE, toInt(record[0]));
             } else return BAD_VALUE;
             // expect part 1 starts with "zone"
             if (stripPrefix(&record[1], "zone")) {
-                proto.write(MigrateTypeProto::ZONE, record[1]);
+                proto.write(PageTypeInfoProto::MigrateType::ZONE, record[1]);
             } else return BAD_VALUE;
             // expect part 2 starts with "type"
             if (stripPrefix(&record[2], "type")) {
@@ -83,22 +85,22 @@
                 int pageCountsSize = pageBlockOrder + 2;
                 if ((int)pageCounts.size() != pageCountsSize) return BAD_VALUE;
 
-                proto.write(MigrateTypeProto::TYPE, pageCounts[0]);
+                proto.write(PageTypeInfoProto::MigrateType::TYPE, pageCounts[0]);
                 for (auto i=1; i<pageCountsSize; i++) {
-                    proto.write(MigrateTypeProto::FREE_PAGES_COUNT, toInt(pageCounts[i]));
+                    proto.write(PageTypeInfoProto::MigrateType::FREE_PAGES_COUNT, toInt(pageCounts[i]));
                 }
             } else return BAD_VALUE;
 
             proto.end(token);
         } else if (!blockHeader.empty() && record.size() == 2) {
-            long long token = proto.start(PageTypeInfo::BLOCKS);
+            long long token = proto.start(PageTypeInfoProto::BLOCKS);
             if (stripPrefix(&record[0], "Node")) {
-                proto.write(BlockProto::NODE, toInt(record[0]));
+                proto.write(PageTypeInfoProto::Block::NODE, toInt(record[0]));
             } else return BAD_VALUE;
 
             if (stripPrefix(&record[1], "zone")) {
                 record_t blockCounts = parseRecord(record[1]);
-                proto.write(BlockProto::ZONE, blockCounts[0]);
+                proto.write(PageTypeInfoProto::Block::ZONE, blockCounts[0]);
 
                 for (size_t i=0; i<blockHeader.size(); i++) {
                     if (!table.insertField(&proto, blockHeader[i], blockCounts[i+1])) {
diff --git a/cmds/incident_helper/src/parsers/ProcrankParser.cpp b/cmds/incident_helper/src/parsers/ProcrankParser.cpp
index a4eb0fd..c1c458e 100644
--- a/cmds/incident_helper/src/parsers/ProcrankParser.cpp
+++ b/cmds/incident_helper/src/parsers/ProcrankParser.cpp
@@ -33,7 +33,7 @@
     int nline = 0;
 
     ProtoOutputStream proto;
-    Table table(ProcessProto::_FIELD_NAMES, ProcessProto::_FIELD_IDS, ProcessProto::_FIELD_COUNT);
+    Table table(ProcrankProto::Process::_FIELD_NAMES, ProcrankProto::Process::_FIELD_IDS, ProcrankProto::Process::_FIELD_COUNT);
     string zram, ram, total;
 
     // parse line by line
@@ -66,7 +66,7 @@
             continue;
         }
 
-        long long token = proto.start(Procrank::PROCESSES);
+        long long token = proto.start(ProcrankProto::PROCESSES);
         for (int i=0; i<(int)record.size(); i++) {
             if (!table.insertField(&proto, header[i], record[i])) {
                 fprintf(stderr, "[%s]Line %d has bad value %s of %s\n",
@@ -77,23 +77,23 @@
     }
 
     // add summary
-    long long token = proto.start(Procrank::SUMMARY);
+    long long token = proto.start(ProcrankProto::SUMMARY);
     if (!total.empty()) {
         record = parseRecord(total);
-        long long token = proto.start(SummaryProto::TOTAL);
+        long long token = proto.start(ProcrankProto::Summary::TOTAL);
         for (int i=(int)record.size(); i>0; i--) {
             table.insertField(&proto, header[header.size() - i].c_str(), record[record.size() - i].c_str());
         }
         proto.end(token);
     }
     if (!zram.empty()) {
-        long long token = proto.start(SummaryProto::ZRAM);
-        proto.write(ZramProto::RAW_TEXT, zram);
+        long long token = proto.start(ProcrankProto::Summary::ZRAM);
+        proto.write(ProcrankProto::Summary::Zram::RAW_TEXT, zram);
         proto.end(token);
     }
     if (!ram.empty()) {
-        long long token = proto.start(SummaryProto::RAM);
-        proto.write(RamProto::RAW_TEXT, ram);
+        long long token = proto.start(ProcrankProto::Summary::RAM);
+        proto.write(ProcrankProto::Summary::Ram::RAW_TEXT, ram);
         proto.end(token);
     }
     proto.end(token);
diff --git a/cmds/incident_helper/src/parsers/PsParser.cpp b/cmds/incident_helper/src/parsers/PsParser.cpp
index e9014ca..420775f 100644
--- a/cmds/incident_helper/src/parsers/PsParser.cpp
+++ b/cmds/incident_helper/src/parsers/PsParser.cpp
@@ -33,12 +33,12 @@
     int diff = 0;
 
     ProtoOutputStream proto;
-    Table table(PsDumpProto::Process::_FIELD_NAMES, PsDumpProto::Process::_FIELD_IDS, PsDumpProto::Process::_FIELD_COUNT);
+    Table table(PsProto::Process::_FIELD_NAMES, PsProto::Process::_FIELD_IDS, PsProto::Process::_FIELD_COUNT);
     const char* pcyNames[] = { "fg", "bg", "ta" };
-    const int pcyValues[] = {PsDumpProto::Process::POLICY_FG, PsDumpProto::Process::POLICY_BG, PsDumpProto::Process::POLICY_TA};
+    const int pcyValues[] = {PsProto::Process::POLICY_FG, PsProto::Process::POLICY_BG, PsProto::Process::POLICY_TA};
     table.addEnumTypeMap("pcy", pcyNames, pcyValues, 3);
     const char* sNames[] = { "D", "R", "S", "T", "t", "X", "Z" };
-    const int sValues[] = {PsDumpProto::Process::STATE_D, PsDumpProto::Process::STATE_R, PsDumpProto::Process::STATE_S, PsDumpProto::Process::STATE_T, PsDumpProto::Process::STATE_TRACING, PsDumpProto::Process::STATE_X, PsDumpProto::Process::STATE_Z};
+    const int sValues[] = {PsProto::Process::STATE_D, PsProto::Process::STATE_R, PsProto::Process::STATE_S, PsProto::Process::STATE_T, PsProto::Process::STATE_TRACING, PsProto::Process::STATE_X, PsProto::Process::STATE_Z};
     table.addEnumTypeMap("s", sNames, sValues, 7);
 
     // Parse line by line
@@ -71,7 +71,7 @@
             continue;
         }
 
-        long long token = proto.start(PsDumpProto::PROCESSES);
+        long long token = proto.start(PsProto::PROCESSES);
         for (int i=0; i<(int)record.size(); i++) {
             if (!table.insertField(&proto, header[i], record[i])) {
                 fprintf(stderr, "[%s]Line %d has bad value %s of %s\n",
diff --git a/cmds/incident_helper/tests/CpuFreqParser_test.cpp b/cmds/incident_helper/tests/CpuFreqParser_test.cpp
index 82deee4..0839a7e 100644
--- a/cmds/incident_helper/tests/CpuFreqParser_test.cpp
+++ b/cmds/incident_helper/tests/CpuFreqParser_test.cpp
@@ -52,14 +52,14 @@
 TEST_F(CpuFreqParserTest, Success) {
     const string testFile = kTestDataPath + "cpufreq.txt";
     CpuFreqParser parser;
-    CpuFreq expected;
+    CpuFreqProto expected;
 
     long jiffyHz = sysconf(_SC_CLK_TCK);
     expected.set_jiffy_hz(jiffyHz);
 
-    CpuFreqStats::TimeInState* state;
+    CpuFreqProto::Stats::TimeInState* state;
 
-    CpuFreqStats* cpu0 = expected.add_cpu_freqs();
+    CpuFreqProto::Stats* cpu0 = expected.add_cpu_freqs();
     cpu0->set_cpu_name("cpu0");
     state = cpu0->add_times();
     state->set_state_khz(307200);
@@ -71,7 +71,7 @@
     state->set_state_khz(768000);
     state->set_time_jiffy(22652);
 
-    CpuFreqStats* cpu1 = expected.add_cpu_freqs();
+    CpuFreqProto::Stats* cpu1 = expected.add_cpu_freqs();
     cpu1->set_cpu_name("cpu1");
     state = cpu1->add_times();
     state->set_state_khz(307200);
@@ -83,7 +83,7 @@
     state->set_state_khz(768000);
     state->set_time_jiffy(22652);
 
-    CpuFreqStats* cpu2 = expected.add_cpu_freqs();
+    CpuFreqProto::Stats* cpu2 = expected.add_cpu_freqs();
     cpu2->set_cpu_name("cpu2");
     state = cpu2->add_times();
     state->set_state_khz(307200);
@@ -98,7 +98,7 @@
     state->set_state_khz(825600);
     state->set_time_jiffy(13173);
 
-    CpuFreqStats* cpu3 = expected.add_cpu_freqs();
+    CpuFreqProto::Stats* cpu3 = expected.add_cpu_freqs();
     cpu3->set_cpu_name("cpu3");
     state = cpu3->add_times();
     state->set_state_khz(307200);
diff --git a/cmds/incident_helper/tests/CpuInfoParser_test.cpp b/cmds/incident_helper/tests/CpuInfoParser_test.cpp
index 8dce53e..2e50d63 100644
--- a/cmds/incident_helper/tests/CpuInfoParser_test.cpp
+++ b/cmds/incident_helper/tests/CpuInfoParser_test.cpp
@@ -52,28 +52,28 @@
 TEST_F(CpuInfoParserTest, Success) {
     const string testFile = kTestDataPath + "cpuinfo.txt";
     CpuInfoParser parser;
-    CpuInfo expected;
+    CpuInfoProto expected;
 
-    CpuInfo::TaskStats* taskStats = expected.mutable_task_stats();
+    CpuInfoProto::TaskStats* taskStats = expected.mutable_task_stats();
     taskStats->set_total(2038);
     taskStats->set_running(1);
     taskStats->set_sleeping(2033);
     taskStats->set_stopped(0);
     taskStats->set_zombie(0);
 
-    CpuInfo::MemStats* mem = expected.mutable_mem();
+    CpuInfoProto::MemStats* mem = expected.mutable_mem();
     mem->set_total(3842668);
     mem->set_used(3761936);
     mem->set_free(80732);
     mem->set_buffers(220188);
 
-    CpuInfo::MemStats* swap = expected.mutable_swap();
+    CpuInfoProto::MemStats* swap = expected.mutable_swap();
     swap->set_total(524284);
     swap->set_used(25892);
     swap->set_free(498392);
     swap->set_cached(1316952);
 
-    CpuInfo::CpuUsage* usage = expected.mutable_cpu_usage();
+    CpuInfoProto::CpuUsage* usage = expected.mutable_cpu_usage();
     usage->set_cpu(400);
     usage->set_user(17);
     usage->set_nice(0);
@@ -85,59 +85,59 @@
     usage->set_host(0);
 
     // This is a special line which is able to be parsed by the CpuInfoParser
-    CpuInfo::Task* task1 = expected.add_tasks();
+    CpuInfoProto::Task* task1 = expected.add_tasks();
     task1->set_pid(29438);
     task1->set_tid(29438);
     task1->set_user("rootabcdefghij");
     task1->set_pr("20");
     task1->set_ni(0);
     task1->set_cpu(57.9);
-    task1->set_s(CpuInfo::Task::STATUS_R);
+    task1->set_s(CpuInfoProto::Task::STATUS_R);
     task1->set_virt("14M");
     task1->set_res("3.8M");
-    task1->set_pcy(CpuInfo::Task::POLICY_UNKNOWN);
+    task1->set_pcy(CpuInfoProto::Task::POLICY_UNKNOWN);
     task1->set_cmd("top test");
     task1->set_name("top");
 
-    CpuInfo::Task* task2 = expected.add_tasks();
+    CpuInfoProto::Task* task2 = expected.add_tasks();
     task2->set_pid(916);
     task2->set_tid(916);
     task2->set_user("system");
     task2->set_pr("18");
     task2->set_ni(-2);
     task2->set_cpu(1.4);
-    task2->set_s(CpuInfo::Task::STATUS_S);
+    task2->set_s(CpuInfoProto::Task::STATUS_S);
     task2->set_virt("4.6G");
     task2->set_res("404M");
-    task2->set_pcy(CpuInfo::Task::POLICY_fg);
+    task2->set_pcy(CpuInfoProto::Task::POLICY_fg);
     task2->set_cmd("system_server");
     task2->set_name("system_server");
 
-    CpuInfo::Task* task3 = expected.add_tasks();
+    CpuInfoProto::Task* task3 = expected.add_tasks();
     task3->set_pid(28);
     task3->set_tid(28);
     task3->set_user("root");
     task3->set_pr("-2");
     task3->set_ni(0);
     task3->set_cpu(1.4);
-    task3->set_s(CpuInfo::Task::STATUS_S);
+    task3->set_s(CpuInfoProto::Task::STATUS_S);
     task3->set_virt("0");
     task3->set_res("0");
-    task3->set_pcy(CpuInfo::Task::POLICY_bg);
+    task3->set_pcy(CpuInfoProto::Task::POLICY_bg);
     task3->set_cmd("rcuc/3");
     task3->set_name("[rcuc/3]");
 
-    CpuInfo::Task* task4 = expected.add_tasks();
+    CpuInfoProto::Task* task4 = expected.add_tasks();
     task4->set_pid(27);
     task4->set_tid(27);
     task4->set_user("root");
     task4->set_pr("RT");
     task4->set_ni(0);
     task4->set_cpu(1.4);
-    task4->set_s(CpuInfo::Task::STATUS_S);
+    task4->set_s(CpuInfoProto::Task::STATUS_S);
     task4->set_virt("0");
     task4->set_res("0");
-    task4->set_pcy(CpuInfo::Task::POLICY_ta);
+    task4->set_pcy(CpuInfoProto::Task::POLICY_ta);
     task4->set_cmd("migration/3");
     task4->set_name("[migration/3]");
 
diff --git a/cmds/incident_helper/tests/KernelWakesParser_test.cpp b/cmds/incident_helper/tests/KernelWakesParser_test.cpp
index a98c62b..f92d813 100644
--- a/cmds/incident_helper/tests/KernelWakesParser_test.cpp
+++ b/cmds/incident_helper/tests/KernelWakesParser_test.cpp
@@ -52,14 +52,14 @@
 TEST_F(KernelWakesParserTest, Short) {
     const string testFile = kTestDataPath + "kernel_wakeups_short.txt";
     KernelWakesParser parser;
-    KernelWakeSources expected;
+    KernelWakeSourcesProto expected;
 
-    WakeupSourceProto* record1 = expected.add_wakeup_sources();
+    KernelWakeSourcesProto::WakeupSource* record1 = expected.add_wakeup_sources();
     record1->set_name("ab");
     record1->set_active_count(8);
     record1->set_last_change(123456123456LL);
 
-    WakeupSourceProto* record2 = expected.add_wakeup_sources();
+    KernelWakeSourcesProto::WakeupSource* record2 = expected.add_wakeup_sources();
     record2->set_name("df");
     record2->set_active_count(143);
     record2->set_last_change(0LL);
@@ -76,9 +76,9 @@
 TEST_F(KernelWakesParserTest, Normal) {
     const string testFile = kTestDataPath + "kernel_wakeups.txt";
     KernelWakesParser parser;
-    KernelWakeSources expected;
+    KernelWakeSourcesProto expected;
 
-    WakeupSourceProto* record1 = expected.add_wakeup_sources();
+    KernelWakeSourcesProto::WakeupSource* record1 = expected.add_wakeup_sources();
     record1->set_name("ipc000000ab_ATFWD-daemon");
     record1->set_active_count(8);
     record1->set_event_count(8);
@@ -90,7 +90,7 @@
     record1->set_last_change(131348LL);
     record1->set_prevent_suspend_time(0LL);
 
-    WakeupSourceProto* record2 = expected.add_wakeup_sources();
+    KernelWakeSourcesProto::WakeupSource* record2 = expected.add_wakeup_sources();
     record2->set_name("ipc000000aa_ATFWD-daemon");
     record2->set_active_count(143);
     record2->set_event_count(143);
diff --git a/cmds/incident_helper/tests/PageTypeInfoParser_test.cpp b/cmds/incident_helper/tests/PageTypeInfoParser_test.cpp
index a9e6e816..9bad7be 100644
--- a/cmds/incident_helper/tests/PageTypeInfoParser_test.cpp
+++ b/cmds/incident_helper/tests/PageTypeInfoParser_test.cpp
@@ -52,12 +52,12 @@
 TEST_F(PageTypeInfoParserTest, Success) {
     const string testFile = kTestDataPath + "pagetypeinfo.txt";
     PageTypeInfoParser parser;
-    PageTypeInfo expected;
+    PageTypeInfoProto expected;
 
     expected.set_page_block_order(10);
     expected.set_pages_per_block(1024);
 
-    MigrateTypeProto* mt1 = expected.add_migrate_types();
+    PageTypeInfoProto::MigrateType* mt1 = expected.add_migrate_types();
     mt1->set_node(0);
     mt1->set_zone("DMA");
     mt1->set_type("Unmovable");
@@ -66,7 +66,7 @@
         mt1->add_free_pages_count(arr1[i]);
     }
 
-    MigrateTypeProto* mt2 = expected.add_migrate_types();
+    PageTypeInfoProto::MigrateType* mt2 = expected.add_migrate_types();
     mt2->set_node(0);
     mt2->set_zone("Normal");
     mt2->set_type("Reclaimable");
@@ -75,7 +75,7 @@
         mt2->add_free_pages_count(arr2[i]);
     }
 
-    BlockProto* block1 = expected.add_blocks();
+    PageTypeInfoProto::Block* block1 = expected.add_blocks();
     block1->set_node(0);
     block1->set_zone("DMA");
     block1->set_unmovable(74);
@@ -86,7 +86,7 @@
     block1->set_isolate(0);
 
 
-    BlockProto* block2 = expected.add_blocks();
+    PageTypeInfoProto::Block* block2 = expected.add_blocks();
     block2->set_node(0);
     block2->set_zone("Normal");
     block2->set_unmovable(70);
diff --git a/cmds/incident_helper/tests/ProcrankParser_test.cpp b/cmds/incident_helper/tests/ProcrankParser_test.cpp
index 76b25d7..0b567ae 100644
--- a/cmds/incident_helper/tests/ProcrankParser_test.cpp
+++ b/cmds/incident_helper/tests/ProcrankParser_test.cpp
@@ -52,9 +52,9 @@
 TEST_F(ProcrankParserTest, HasSwapInfo) {
     const string testFile = kTestDataPath + "procrank.txt";
     ProcrankParser parser;
-    Procrank expected;
+    ProcrankProto expected;
 
-    ProcessProto* process1 = expected.add_processes();
+    ProcrankProto::Process* process1 = expected.add_processes();
     process1->set_pid(1119);
     process1->set_vss(2607640);
     process1->set_rss(339564);
@@ -66,7 +66,7 @@
     process1->set_zswap(10);
     process1->set_cmdline("system_server");
 
-    ProcessProto* process2 = expected.add_processes();
+    ProcrankProto::Process* process2 = expected.add_processes();
     process2->set_pid(649);
     process2->set_vss(11016);
     process2->set_rss(1448);
@@ -78,7 +78,7 @@
     process2->set_zswap(75);
     process2->set_cmdline("/vendor/bin/qseecomd");
 
-    ProcessProto* total = expected.mutable_summary()->mutable_total();
+    ProcrankProto::Process* total = expected.mutable_summary()->mutable_total();
     total->set_pss(1201993);
     total->set_uss(935300);
     total->set_swap(88164);
@@ -104,9 +104,9 @@
 TEST_F(ProcrankParserTest, NoSwapInfo) {
     const string testFile = kTestDataPath + "procrank_short.txt";
     ProcrankParser parser;
-    Procrank expected;
+    ProcrankProto expected;
 
-    ProcessProto* process1 = expected.add_processes();
+    ProcrankProto::Process* process1 = expected.add_processes();
     process1->set_pid(1119);
     process1->set_vss(2607640);
     process1->set_rss(339564);
@@ -114,7 +114,7 @@
     process1->set_uss(114216);
     process1->set_cmdline("system_server");
 
-    ProcessProto* process2 = expected.add_processes();
+    ProcrankProto::Process* process2 = expected.add_processes();
     process2->set_pid(649);
     process2->set_vss(11016);
     process2->set_rss(1448);
@@ -122,7 +122,7 @@
     process2->set_uss(48);
     process2->set_cmdline("/vendor/bin/qseecomd");
 
-    ProcessProto* total = expected.mutable_summary()->mutable_total();
+    ProcrankProto::Process* total = expected.mutable_summary()->mutable_total();
     total->set_pss(1201993);
     total->set_uss(935300);
     total->set_cmdline("TOTAL");
diff --git a/cmds/incident_helper/tests/PsParser_test.cpp b/cmds/incident_helper/tests/PsParser_test.cpp
index 1f03a7f..114d634 100644
--- a/cmds/incident_helper/tests/PsParser_test.cpp
+++ b/cmds/incident_helper/tests/PsParser_test.cpp
@@ -52,10 +52,10 @@
 TEST_F(PsParserTest, Normal) {
     const string testFile = kTestDataPath + "ps.txt";
     PsParser parser;
-    PsDumpProto expected;
-    PsDumpProto got;
+    PsProto expected;
+    PsProto got;
 
-    PsDumpProto::Process* record1 = expected.add_processes();
+    PsProto::Process* record1 = expected.add_processes();
     record1->set_label("u:r:init:s0");
     record1->set_user("root");
     record1->set_pid(1);
@@ -65,16 +65,16 @@
     record1->set_rss(2636);
     record1->set_wchan("SyS_epoll_wait");
     record1->set_addr("0");
-    record1->set_s(PsDumpProto_Process_ProcessStateCode_STATE_S);
+    record1->set_s(PsProto_Process_ProcessStateCode_STATE_S);
     record1->set_pri(19);
     record1->set_ni(0);
     record1->set_rtprio("-");
-    record1->set_sch(PsDumpProto_Process_SchedulingPolicy_SCH_NORMAL);
-    record1->set_pcy(PsDumpProto::Process::POLICY_FG);
+    record1->set_sch(PsProto_Process_SchedulingPolicy_SCH_NORMAL);
+    record1->set_pcy(PsProto::Process::POLICY_FG);
     record1->set_time("00:00:01");
     record1->set_cmd("init");
 
-    PsDumpProto::Process* record2 = expected.add_processes();
+    PsProto::Process* record2 = expected.add_processes();
     record2->set_label("u:r:kernel:s0");
     record2->set_user("root");
     record2->set_pid(2);
@@ -84,16 +84,16 @@
     record2->set_rss(0);
     record2->set_wchan("kthreadd");
     record2->set_addr("0");
-    record2->set_s(PsDumpProto_Process_ProcessStateCode_STATE_S);
+    record2->set_s(PsProto_Process_ProcessStateCode_STATE_S);
     record2->set_pri(19);
     record2->set_ni(0);
     record2->set_rtprio("-");
-    record2->set_sch(PsDumpProto_Process_SchedulingPolicy_SCH_NORMAL);
-    record2->set_pcy(PsDumpProto::Process::POLICY_FG);
+    record2->set_sch(PsProto_Process_SchedulingPolicy_SCH_NORMAL);
+    record2->set_pcy(PsProto::Process::POLICY_FG);
     record2->set_time("00:00:00");
     record2->set_cmd("kthreadd");
 
-    PsDumpProto::Process* record3 = expected.add_processes();
+    PsProto::Process* record3 = expected.add_processes();
     record3->set_label("u:r:surfaceflinger:s0");
     record3->set_user("system");
     record3->set_pid(499);
@@ -103,16 +103,16 @@
     record3->set_rss(22024);
     record3->set_wchan("futex_wait_queue_me");
     record3->set_addr("0");
-    record3->set_s(PsDumpProto_Process_ProcessStateCode_STATE_S);
+    record3->set_s(PsProto_Process_ProcessStateCode_STATE_S);
     record3->set_pri(42);
     record3->set_ni(-9);
     record3->set_rtprio("2");
-    record3->set_sch(PsDumpProto_Process_SchedulingPolicy_SCH_FIFO);
-    record3->set_pcy(PsDumpProto::Process::POLICY_FG);
+    record3->set_sch(PsProto_Process_SchedulingPolicy_SCH_FIFO);
+    record3->set_pcy(PsProto::Process::POLICY_FG);
     record3->set_time("00:00:00");
     record3->set_cmd("EventThread");
 
-    PsDumpProto::Process* record4 = expected.add_processes();
+    PsProto::Process* record4 = expected.add_processes();
     record4->set_label("u:r:hal_gnss_default:s0");
     record4->set_user("gps");
     record4->set_pid(670);
@@ -122,16 +122,16 @@
     record4->set_rss(7272);
     record4->set_wchan("poll_schedule_timeout");
     record4->set_addr("0");
-    record4->set_s(PsDumpProto_Process_ProcessStateCode_STATE_S);
+    record4->set_s(PsProto_Process_ProcessStateCode_STATE_S);
     record4->set_pri(19);
     record4->set_ni(0);
     record4->set_rtprio("-");
-    record4->set_sch(PsDumpProto_Process_SchedulingPolicy_SCH_NORMAL);
-    record4->set_pcy(PsDumpProto::Process::POLICY_FG);
+    record4->set_sch(PsProto_Process_SchedulingPolicy_SCH_NORMAL);
+    record4->set_pcy(PsProto::Process::POLICY_FG);
     record4->set_time("00:00:00");
     record4->set_cmd("Loc_hal_worker");
 
-    PsDumpProto::Process* record5 = expected.add_processes();
+    PsProto::Process* record5 = expected.add_processes();
     record5->set_label("u:r:platform_app:s0:c512,c768");
     record5->set_user("u0_a48");
     record5->set_pid(1660);
@@ -141,16 +141,16 @@
     record5->set_rss(138328);
     record5->set_wchan("binder_thread_read");
     record5->set_addr("0");
-    record5->set_s(PsDumpProto_Process_ProcessStateCode_STATE_S);
+    record5->set_s(PsProto_Process_ProcessStateCode_STATE_S);
     record5->set_pri(35);
     record5->set_ni(-16);
     record5->set_rtprio("-");
-    record5->set_sch(PsDumpProto_Process_SchedulingPolicy_SCH_NORMAL);
-    record5->set_pcy(PsDumpProto::Process::POLICY_TA);
+    record5->set_sch(PsProto_Process_SchedulingPolicy_SCH_NORMAL);
+    record5->set_pcy(PsProto::Process::POLICY_TA);
     record5->set_time("00:00:00");
     record5->set_cmd("HwBinder:1660_1");
 
-    PsDumpProto::Process* record6 = expected.add_processes();
+    PsProto::Process* record6 = expected.add_processes();
     record6->set_label("u:r:perfd:s0");
     record6->set_user("root");
     record6->set_pid(1939);
@@ -160,16 +160,16 @@
     record6->set_rss(2088);
     record6->set_wchan("__skb_recv_datagram");
     record6->set_addr("7b9782fd14");
-    record6->set_s(PsDumpProto_Process_ProcessStateCode_STATE_S);
+    record6->set_s(PsProto_Process_ProcessStateCode_STATE_S);
     record6->set_pri(19);
     record6->set_ni(0);
     record6->set_rtprio("-");
-    record6->set_sch(PsDumpProto_Process_SchedulingPolicy_SCH_NORMAL);
-    record6->set_pcy(PsDumpProto::Process::POLICY_UNKNOWN);
+    record6->set_sch(PsProto_Process_SchedulingPolicy_SCH_NORMAL);
+    record6->set_pcy(PsProto::Process::POLICY_UNKNOWN);
     record6->set_time("00:00:00");
     record6->set_cmd("perfd");
 
-    PsDumpProto::Process* record7 = expected.add_processes();
+    PsProto::Process* record7 = expected.add_processes();
     record7->set_label("u:r:perfd:s0");
     record7->set_user("root");
     record7->set_pid(1939);
@@ -179,16 +179,16 @@
     record7->set_rss(2088);
     record7->set_wchan("do_sigtimedwait");
     record7->set_addr("7b9782ff6c");
-    record7->set_s(PsDumpProto_Process_ProcessStateCode_STATE_S);
+    record7->set_s(PsProto_Process_ProcessStateCode_STATE_S);
     record7->set_pri(19);
     record7->set_ni(0);
     record7->set_rtprio("-");
-    record7->set_sch(PsDumpProto_Process_SchedulingPolicy_SCH_NORMAL);
-    record7->set_pcy(PsDumpProto::Process::POLICY_UNKNOWN);
+    record7->set_sch(PsProto_Process_SchedulingPolicy_SCH_NORMAL);
+    record7->set_pcy(PsProto::Process::POLICY_UNKNOWN);
     record7->set_time("00:00:00");
     record7->set_cmd("POSIX timer 0");
 
-    PsDumpProto::Process* record8 = expected.add_processes();
+    PsProto::Process* record8 = expected.add_processes();
     record8->set_label("u:r:shell:s0");
     record8->set_user("shell");
     record8->set_pid(2645);
@@ -198,12 +198,12 @@
     record8->set_rss(2972);
     record8->set_wchan("0");
     record8->set_addr("7f67a2f8b4");
-    record8->set_s(PsDumpProto_Process_ProcessStateCode_STATE_R);
+    record8->set_s(PsProto_Process_ProcessStateCode_STATE_R);
     record8->set_pri(19);
     record8->set_ni(0);
     record8->set_rtprio("-");
-    record8->set_sch(PsDumpProto_Process_SchedulingPolicy_SCH_NORMAL);
-    record8->set_pcy(PsDumpProto::Process::POLICY_FG);
+    record8->set_sch(PsProto_Process_SchedulingPolicy_SCH_NORMAL);
+    record8->set_pcy(PsProto::Process::POLICY_FG);
     record8->set_time("00:00:00");
     record8->set_cmd("ps");
 
@@ -221,8 +221,8 @@
     } else {
         int n = got.processes_size();
         for (int i = 0; i < n; i++) {
-            PsDumpProto::Process g = got.processes(i);
-            PsDumpProto::Process e = expected.processes(i);
+            PsProto::Process g = got.processes(i);
+            PsProto::Process e = expected.processes(i);
 
             if (g.label() != e.label()) {
                 fprintf(stderr, "prcs[%d]: Invalid label. Got %s, want %s\n", i, g.label().c_str(), e.label().c_str());
diff --git a/cmds/incidentd/.clang-format b/cmds/incidentd/.clang-format
new file mode 100644
index 0000000..6fa5b47
--- /dev/null
+++ b/cmds/incidentd/.clang-format
@@ -0,0 +1,17 @@
+BasedOnStyle: Google
+AllowShortIfStatementsOnASingleLine: true
+AllowShortFunctionsOnASingleLine: true
+AllowShortLoopsOnASingleLine: true
+BinPackArguments: true
+BinPackParameters: true
+ColumnLimit: 100
+CommentPragmas: NOLINT:.*
+ContinuationIndentWidth: 8
+DerivePointerAlignment: false
+IndentWidth: 4
+PointerAlignment: Left
+TabWidth: 4
+AccessModifierOffset: -4
+IncludeCategories:
+  - Regex:    '^"Log\.h"'
+    Priority:    -1
diff --git a/cmds/incidentd/Android.mk b/cmds/incidentd/Android.mk
index 2b00d9e..d2d24c8 100644
--- a/cmds/incidentd/Android.mk
+++ b/cmds/incidentd/Android.mk
@@ -32,7 +32,7 @@
         src/Privacy.cpp \
         src/Reporter.cpp \
         src/Section.cpp \
-        src/io_util.cpp \
+        src/incidentd_util.cpp \
         src/main.cpp \
         src/report_directory.cpp
 
@@ -56,6 +56,7 @@
         libcutils \
         libincident \
         liblog \
+        libprotobuf-cpp-lite \
         libprotoutil \
         libselinux \
         libservices \
@@ -115,7 +116,7 @@
     src/Privacy.cpp \
     src/Reporter.cpp \
     src/Section.cpp \
-    src/io_util.cpp \
+    src/incidentd_util.cpp \
     src/report_directory.cpp \
     tests/section_list.cpp \
     tests/PrivacyBuffer_test.cpp \
diff --git a/cmds/incidentd/OWNERS b/cmds/incidentd/OWNERS
new file mode 100644
index 0000000..1a68a32
--- /dev/null
+++ b/cmds/incidentd/OWNERS
@@ -0,0 +1,2 @@
+jinyithu@google.com
+kwekua@google.com
diff --git a/cmds/incidentd/README.md b/cmds/incidentd/README.md
index 71c6deb..1730a640 100644
--- a/cmds/incidentd/README.md
+++ b/cmds/incidentd/README.md
@@ -20,4 +20,8 @@
 
 ```
 root$ atest incidentd_test
-```
\ No newline at end of file
+```
+
+Use clang-format to style the file
+
+clang-format -style=file -i <file list>
\ No newline at end of file
diff --git a/cmds/incidentd/src/FdBuffer.cpp b/cmds/incidentd/src/FdBuffer.cpp
index 0fff4e6..883924c8 100644
--- a/cmds/incidentd/src/FdBuffer.cpp
+++ b/cmds/incidentd/src/FdBuffer.cpp
@@ -13,8 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
-#define LOG_TAG "incidentd"
+#include "Log.h"
 
 #include "FdBuffer.h"
 
@@ -26,30 +25,16 @@
 #include <unistd.h>
 #include <wait.h>
 
-const bool DEBUG = false;
-const ssize_t BUFFER_SIZE = 16 * 1024; // 16 KB
-const ssize_t MAX_BUFFER_COUNT = 256; // 4 MB max
+const ssize_t BUFFER_SIZE = 16 * 1024;  // 16 KB
+const ssize_t MAX_BUFFER_COUNT = 256;   // 4 MB max
 
 FdBuffer::FdBuffer()
-    :mBuffer(BUFFER_SIZE),
-     mStartTime(-1),
-     mFinishTime(-1),
-     mTimedOut(false),
-     mTruncated(false)
-{
-}
+    : mBuffer(BUFFER_SIZE), mStartTime(-1), mFinishTime(-1), mTimedOut(false), mTruncated(false) {}
 
-FdBuffer::~FdBuffer()
-{
-}
+FdBuffer::~FdBuffer() {}
 
-status_t
-FdBuffer::read(int fd, int64_t timeout)
-{
-    struct pollfd pfds = {
-        .fd = fd,
-        .events = POLLIN
-    };
+status_t FdBuffer::read(int fd, int64_t timeout) {
+    struct pollfd pfds = {.fd = fd, .events = POLLIN};
     mStartTime = uptimeMillis();
 
     fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK);
@@ -63,22 +48,22 @@
 
         int64_t remainingTime = (mStartTime + timeout) - uptimeMillis();
         if (remainingTime <= 0) {
-            if (DEBUG) ALOGD("timed out due to long read");
+            VLOG("timed out due to long read");
             mTimedOut = true;
             break;
         }
 
         int count = poll(&pfds, 1, remainingTime);
         if (count == 0) {
-            if (DEBUG) ALOGD("timed out due to block calling poll");
+            VLOG("timed out due to block calling poll");
             mTimedOut = true;
             break;
         } else if (count < 0) {
-            if (DEBUG) ALOGD("poll failed: %s", strerror(errno));
+            VLOG("poll failed: %s", strerror(errno));
             return -errno;
         } else {
             if ((pfds.revents & POLLERR) != 0) {
-                if (DEBUG) ALOGD("return event has error %s", strerror(errno));
+                VLOG("return event has error %s", strerror(errno));
                 return errno != 0 ? -errno : UNKNOWN_ERROR;
             } else {
                 ssize_t amt = ::read(fd, mBuffer.writeBuffer(), mBuffer.currentToWrite());
@@ -86,7 +71,7 @@
                     if (errno == EAGAIN || errno == EWOULDBLOCK) {
                         continue;
                     } else {
-                        if (DEBUG) ALOGD("Fail to read %d: %s", fd, strerror(errno));
+                        VLOG("Fail to read %d: %s", fd, strerror(errno));
                         return -errno;
                     }
                 } else if (amt == 0) {
@@ -100,13 +85,12 @@
     return NO_ERROR;
 }
 
-status_t
-FdBuffer::readProcessedDataInStream(int fd, int toFd, int fromFd, int64_t timeoutMs, const bool isSysfs)
-{
+status_t FdBuffer::readProcessedDataInStream(int fd, int toFd, int fromFd, int64_t timeoutMs,
+                                             const bool isSysfs) {
     struct pollfd pfds[] = {
-        { .fd = fd,     .events = POLLIN  },
-        { .fd = toFd,   .events = POLLOUT },
-        { .fd = fromFd, .events = POLLIN  },
+            {.fd = fd, .events = POLLIN},
+            {.fd = toFd, .events = POLLOUT},
+            {.fd = fromFd, .events = POLLIN},
     };
 
     mStartTime = uptimeMillis();
@@ -131,7 +115,7 @@
 
         int64_t remainingTime = (mStartTime + timeoutMs) - uptimeMillis();
         if (remainingTime <= 0) {
-            if (DEBUG) ALOGD("timed out due to long read");
+            VLOG("timed out due to long read");
             mTimedOut = true;
             break;
         }
@@ -139,11 +123,11 @@
         // wait for any pfds to be ready to perform IO
         int count = poll(pfds, 3, remainingTime);
         if (count == 0) {
-            if (DEBUG) ALOGD("timed out due to block calling poll");
+            VLOG("timed out due to block calling poll");
             mTimedOut = true;
             break;
         } else if (count < 0) {
-            if (DEBUG) ALOGD("Fail to poll: %s", strerror(errno));
+            VLOG("Fail to poll: %s", strerror(errno));
             return -errno;
         }
 
@@ -151,10 +135,10 @@
         for (int i = 0; i < 3; ++i) {
             if ((pfds[i].revents & POLLERR) != 0) {
                 if (i == 0 && isSysfs) {
-                    if (DEBUG) ALOGD("fd %d is sysfs, ignore its POLLERR return value", fd);
+                    VLOG("fd %d is sysfs, ignore its POLLERR return value", fd);
                     continue;
                 }
-                if (DEBUG) ALOGD("fd[%d]=%d returns error events: %s", i, fd, strerror(errno));
+                VLOG("fd[%d]=%d returns error events: %s", i, fd, strerror(errno));
                 return errno != 0 ? -errno : UNKNOWN_ERROR;
             }
         }
@@ -169,9 +153,9 @@
             }
             if (amt < 0) {
                 if (!(errno == EAGAIN || errno == EWOULDBLOCK)) {
-                    if (DEBUG) ALOGD("Fail to read fd %d: %s", fd, strerror(errno));
+                    VLOG("Fail to read fd %d: %s", fd, strerror(errno));
                     return -errno;
-                } // otherwise just continue
+                }                   // otherwise just continue
             } else if (amt == 0) {  // reach EOF so don't have to poll pfds[0].
                 ::close(pfds[0].fd);
                 pfds[0].fd = -1;
@@ -191,9 +175,9 @@
             }
             if (amt < 0) {
                 if (!(errno == EAGAIN || errno == EWOULDBLOCK)) {
-                    if (DEBUG) ALOGD("Fail to write toFd %d: %s", toFd, strerror(errno));
+                    VLOG("Fail to write toFd %d: %s", toFd, strerror(errno));
                     return -errno;
-                } // otherwise just continue
+                }  // otherwise just continue
             } else {
                 wpos += amt;
                 cirSize -= amt;
@@ -218,9 +202,9 @@
         ssize_t amt = ::read(fromFd, mBuffer.writeBuffer(), mBuffer.currentToWrite());
         if (amt < 0) {
             if (!(errno == EAGAIN || errno == EWOULDBLOCK)) {
-                if (DEBUG) ALOGD("Fail to read fromFd %d: %s", fromFd, strerror(errno));
+                VLOG("Fail to read fromFd %d: %s", fromFd, strerror(errno));
                 return -errno;
-            } // otherwise just continue
+            }  // otherwise just continue
         } else if (amt == 0) {
             break;
         } else {
@@ -232,14 +216,6 @@
     return NO_ERROR;
 }
 
-size_t
-FdBuffer::size() const
-{
-    return mBuffer.size();
-}
+size_t FdBuffer::size() const { return mBuffer.size(); }
 
-EncodedBuffer::iterator
-FdBuffer::data() const
-{
-    return mBuffer.begin();
-}
+EncodedBuffer::iterator FdBuffer::data() const { return mBuffer.begin(); }
diff --git a/cmds/incidentd/src/FdBuffer.h b/cmds/incidentd/src/FdBuffer.h
index 48dc855..5bfa093 100644
--- a/cmds/incidentd/src/FdBuffer.h
+++ b/cmds/incidentd/src/FdBuffer.h
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+#pragma once
 
 #ifndef FD_BUFFER_H
 #define FD_BUFFER_H
@@ -27,8 +28,7 @@
 /**
  * Reads a file into a buffer, and then writes that data to an FdSet.
  */
-class FdBuffer
-{
+class FdBuffer {
 public:
     FdBuffer();
     ~FdBuffer();
@@ -50,7 +50,8 @@
      *
      * Poll will return POLLERR if fd is from sysfs, handle this edge case.
      */
-    status_t readProcessedDataInStream(int fd, int toFd, int fromFd, int64_t timeoutMs, const bool isSysfs=false);
+    status_t readProcessedDataInStream(int fd, int toFd, int fromFd, int64_t timeoutMs,
+                                       const bool isSysfs = false);
 
     /**
      * Whether we timed out.
@@ -90,4 +91,4 @@
     bool mTruncated;
 };
 
-#endif // FD_BUFFER_H
+#endif  // FD_BUFFER_H
diff --git a/cmds/incidentd/src/IncidentService.cpp b/cmds/incidentd/src/IncidentService.cpp
index 1d5ab59..9ae6240 100644
--- a/cmds/incidentd/src/IncidentService.cpp
+++ b/cmds/incidentd/src/IncidentService.cpp
@@ -13,15 +13,20 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
-#define LOG_TAG "incidentd"
+#include "Log.h"
 
 #include "IncidentService.h"
 
+#include "FdBuffer.h"
+#include "PrivacyBuffer.h"
 #include "Reporter.h"
+#include "incidentd_util.h"
+#include "section_list.h"
 
 #include <binder/IPCThreadState.h>
+#include <binder/IResultReceiver.h>
 #include <binder/IServiceManager.h>
+#include <binder/IShellCallback.h>
 #include <cutils/log.h>
 #include <private/android_filesystem_config.h>
 #include <utils/Looper.h>
@@ -29,11 +34,9 @@
 #include <unistd.h>
 
 using namespace android;
+using namespace android::base;
 
-enum {
-    WHAT_RUN_REPORT = 1,
-    WHAT_SEND_BACKLOG_TO_DROPBOX = 2
-};
+enum { WHAT_RUN_REPORT = 1, WHAT_SEND_BACKLOG_TO_DROPBOX = 2 };
 
 //#define DEFAULT_BACKLOG_DELAY_NS (1000000000LL * 60 * 5)
 #define DEFAULT_BACKLOG_DELAY_NS (1000000000LL)
@@ -42,10 +45,9 @@
 String16 const DUMP_PERMISSION("android.permission.DUMP");
 String16 const USAGE_STATS_PERMISSION("android.permission.PACKAGE_USAGE_STATS");
 
-static Status
-checkIncidentPermissions(const IncidentReportArgs& args)
-{
+static Status checkIncidentPermissions(const IncidentReportArgs& args) {
     uid_t callingUid = IPCThreadState::self()->getCallingUid();
+    pid_t callingPid = IPCThreadState::self()->getCallingPid();
     if (callingUid == AID_ROOT || callingUid == AID_SHELL) {
         // root doesn't have permission.DUMP if don't do this!
         return Status::ok();
@@ -54,52 +56,52 @@
     // checking calling permission.
     if (!checkCallingPermission(DUMP_PERMISSION)) {
         ALOGW("Calling pid %d and uid %d does not have permission: android.permission.DUMP",
-                IPCThreadState::self()->getCallingPid(), callingUid);
-        return Status::fromExceptionCode(Status::EX_SECURITY,
+              callingPid, callingUid);
+        return Status::fromExceptionCode(
+                Status::EX_SECURITY,
                 "Calling process does not have permission: android.permission.DUMP");
     }
     if (!checkCallingPermission(USAGE_STATS_PERMISSION)) {
         ALOGW("Calling pid %d and uid %d does not have permission: android.permission.USAGE_STATS",
-                IPCThreadState::self()->getCallingPid(), callingUid);
-        return Status::fromExceptionCode(Status::EX_SECURITY,
+              callingPid, callingUid);
+        return Status::fromExceptionCode(
+                Status::EX_SECURITY,
                 "Calling process does not have permission: android.permission.USAGE_STATS");
     }
 
     // checking calling request uid permission.
     switch (args.dest()) {
         case DEST_LOCAL:
-            if (callingUid != AID_SHELL || callingUid != AID_ROOT) {
-                return Status::fromExceptionCode(Status::EX_SECURITY,
-                    "Calling process does not have permission to get local data.");
+            if (callingUid != AID_SHELL && callingUid != AID_ROOT) {
+                ALOGW("Calling pid %d and uid %d does not have permission to get local data.",
+                      callingPid, callingUid);
+                return Status::fromExceptionCode(
+                        Status::EX_SECURITY,
+                        "Calling process does not have permission to get local data.");
             }
         case DEST_EXPLICIT:
-            if (callingUid != AID_SHELL || callingUid != AID_ROOT ||
-                callingUid != AID_STATSD || callingUid != AID_SYSTEM) {
-                return Status::fromExceptionCode(Status::EX_SECURITY,
-                    "Calling process does not have permission to get explicit data.");
+            if (callingUid != AID_SHELL && callingUid != AID_ROOT && callingUid != AID_STATSD &&
+                callingUid != AID_SYSTEM) {
+                ALOGW("Calling pid %d and uid %d does not have permission to get explicit data.",
+                      callingPid, callingUid);
+                return Status::fromExceptionCode(
+                        Status::EX_SECURITY,
+                        "Calling process does not have permission to get explicit data.");
             }
     }
     return Status::ok();
 }
 // ================================================================================
-ReportRequestQueue::ReportRequestQueue()
-{
-}
+ReportRequestQueue::ReportRequestQueue() {}
 
-ReportRequestQueue::~ReportRequestQueue()
-{
-}
+ReportRequestQueue::~ReportRequestQueue() {}
 
-void
-ReportRequestQueue::addRequest(const sp<ReportRequest>& request)
-{
+void ReportRequestQueue::addRequest(const sp<ReportRequest>& request) {
     unique_lock<mutex> lock(mLock);
     mQueue.push_back(request);
 }
 
-sp<ReportRequest>
-ReportRequestQueue::getNextRequest()
-{
+sp<ReportRequest> ReportRequestQueue::getNextRequest() {
     unique_lock<mutex> lock(mLock);
     if (mQueue.empty()) {
         return NULL;
@@ -110,22 +112,13 @@
     }
 }
 
-
 // ================================================================================
 ReportHandler::ReportHandler(const sp<Looper>& handlerLooper, const sp<ReportRequestQueue>& queue)
-    :mBacklogDelay(DEFAULT_BACKLOG_DELAY_NS),
-     mHandlerLooper(handlerLooper),
-     mQueue(queue)
-{
-}
+    : mBacklogDelay(DEFAULT_BACKLOG_DELAY_NS), mHandlerLooper(handlerLooper), mQueue(queue) {}
 
-ReportHandler::~ReportHandler()
-{
-}
+ReportHandler::~ReportHandler() {}
 
-void
-ReportHandler::handleMessage(const Message& message)
-{
+void ReportHandler::handleMessage(const Message& message) {
     switch (message.what) {
         case WHAT_RUN_REPORT:
             run_report();
@@ -136,33 +129,24 @@
     }
 }
 
-void
-ReportHandler::scheduleRunReport(const sp<ReportRequest>& request)
-{
+void ReportHandler::scheduleRunReport(const sp<ReportRequest>& request) {
     mQueue->addRequest(request);
     mHandlerLooper->removeMessages(this, WHAT_RUN_REPORT);
     mHandlerLooper->sendMessage(this, Message(WHAT_RUN_REPORT));
 }
 
-void
-ReportHandler::scheduleSendBacklogToDropbox()
-{
+void ReportHandler::scheduleSendBacklogToDropbox() {
     unique_lock<mutex> lock(mLock);
     mBacklogDelay = DEFAULT_BACKLOG_DELAY_NS;
     schedule_send_backlog_to_dropbox_locked();
 }
 
-void
-ReportHandler::schedule_send_backlog_to_dropbox_locked()
-{
+void ReportHandler::schedule_send_backlog_to_dropbox_locked() {
     mHandlerLooper->removeMessages(this, WHAT_SEND_BACKLOG_TO_DROPBOX);
-    mHandlerLooper->sendMessageDelayed(mBacklogDelay, this,
-            Message(WHAT_SEND_BACKLOG_TO_DROPBOX));
+    mHandlerLooper->sendMessageDelayed(mBacklogDelay, this, Message(WHAT_SEND_BACKLOG_TO_DROPBOX));
 }
 
-void
-ReportHandler::run_report()
-{
+void ReportHandler::run_report() {
     sp<Reporter> reporter = new Reporter();
 
     // Merge all of the requests into one that has all of the
@@ -185,15 +169,13 @@
     }
 }
 
-void
-ReportHandler::send_backlog_to_dropbox()
-{
+void ReportHandler::send_backlog_to_dropbox() {
     if (Reporter::upload_backlog() == Reporter::REPORT_NEEDS_DROPBOX) {
         // There was a failure. Exponential backoff.
         unique_lock<mutex> lock(mLock);
         mBacklogDelay *= 2;
         ALOGI("Error sending to dropbox. Trying again in %lld minutes",
-                (mBacklogDelay / (1000000000LL * 60)));
+              (mBacklogDelay / (1000000000LL * 60)));
         schedule_send_backlog_to_dropbox_locked();
     } else {
         mBacklogDelay = DEFAULT_BACKLOG_DELAY_NS;
@@ -202,18 +184,13 @@
 
 // ================================================================================
 IncidentService::IncidentService(const sp<Looper>& handlerLooper)
-    :mQueue(new ReportRequestQueue())
-{
+    : mQueue(new ReportRequestQueue()) {
     mHandler = new ReportHandler(handlerLooper, mQueue);
 }
 
-IncidentService::~IncidentService()
-{
-}
+IncidentService::~IncidentService() {}
 
-Status
-IncidentService::reportIncident(const IncidentReportArgs& args)
-{
+Status IncidentService::reportIncident(const IncidentReportArgs& args) {
     ALOGI("reportIncident");
 
     Status status = checkIncidentPermissions(args);
@@ -226,10 +203,9 @@
     return Status::ok();
 }
 
-Status
-IncidentService::reportIncidentToStream(const IncidentReportArgs& args,
-            const sp<IIncidentReportStatusListener>& listener, const unique_fd& stream)
-{
+Status IncidentService::reportIncidentToStream(const IncidentReportArgs& args,
+                                               const sp<IIncidentReportStatusListener>& listener,
+                                               const unique_fd& stream) {
     ALOGI("reportIncidentToStream");
 
     Status status = checkIncidentPermissions(args);
@@ -247,12 +223,10 @@
     return Status::ok();
 }
 
-Status
-IncidentService::systemRunning()
-{
+Status IncidentService::systemRunning() {
     if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) {
         return Status::fromExceptionCode(Status::EX_SECURITY,
-                "Only system uid can call systemRunning");
+                                         "Only system uid can call systemRunning");
     }
 
     // When system_server is up and running, schedule the dropbox task to run.
@@ -261,3 +235,120 @@
     return Status::ok();
 }
 
+/**
+ * Implement our own because the default binder implementation isn't
+ * properly handling SHELL_COMMAND_TRANSACTION.
+ */
+status_t IncidentService::onTransact(uint32_t code, const Parcel& data, Parcel* reply,
+                                     uint32_t flags) {
+    status_t err;
+
+    switch (code) {
+        case SHELL_COMMAND_TRANSACTION: {
+            int in = data.readFileDescriptor();
+            int out = data.readFileDescriptor();
+            int err = data.readFileDescriptor();
+            int argc = data.readInt32();
+            Vector<String8> args;
+            for (int i = 0; i < argc && data.dataAvail() > 0; i++) {
+                args.add(String8(data.readString16()));
+            }
+            sp<IShellCallback> shellCallback = IShellCallback::asInterface(data.readStrongBinder());
+            sp<IResultReceiver> resultReceiver =
+                    IResultReceiver::asInterface(data.readStrongBinder());
+
+            FILE* fin = fdopen(in, "r");
+            FILE* fout = fdopen(out, "w");
+            FILE* ferr = fdopen(err, "w");
+
+            if (fin == NULL || fout == NULL || ferr == NULL) {
+                resultReceiver->send(NO_MEMORY);
+            } else {
+                err = command(fin, fout, ferr, args);
+                resultReceiver->send(err);
+            }
+
+            if (fin != NULL) {
+                fflush(fin);
+                fclose(fin);
+            }
+            if (fout != NULL) {
+                fflush(fout);
+                fclose(fout);
+            }
+            if (fout != NULL) {
+                fflush(ferr);
+                fclose(ferr);
+            }
+
+            return NO_ERROR;
+        }
+        default: { return BnIncidentManager::onTransact(code, data, reply, flags); }
+    }
+}
+
+status_t IncidentService::command(FILE* in, FILE* out, FILE* err, Vector<String8>& args) {
+    const int argCount = args.size();
+
+    if (argCount >= 1) {
+        if (!args[0].compare(String8("privacy"))) {
+            return cmd_privacy(in, out, err, args);
+        }
+    }
+    return cmd_help(out);
+}
+
+status_t IncidentService::cmd_help(FILE* out) {
+    fprintf(out, "usage: adb shell cmd incident privacy print <section_id>\n");
+    fprintf(out, "usage: adb shell cmd incident privacy parse <section_id> < proto.txt\n");
+    fprintf(out, "    Prints/parses for the section id.\n");
+    return NO_ERROR;
+}
+
+static void printPrivacy(const Privacy* p, FILE* out, String8 indent) {
+    if (p == NULL) return;
+    fprintf(out, "%sid:%d, type:%d, dest:%d\n", indent.string(), p->field_id, p->type, p->dest);
+    if (p->children == NULL) return;
+    for (int i = 0; p->children[i] != NULL; i++) {  // NULL-terminated.
+        printPrivacy(p->children[i], out, indent + "  ");
+    }
+}
+
+status_t IncidentService::cmd_privacy(FILE* in, FILE* out, FILE* err, Vector<String8>& args) {
+    const int argCount = args.size();
+    if (argCount >= 3) {
+        String8 opt = args[1];
+        int sectionId = atoi(args[2].string());
+
+        const Privacy* p = get_privacy_of_section(sectionId);
+        if (p == NULL) {
+            fprintf(err, "Can't find section id %d\n", sectionId);
+            return NO_ERROR;
+        }
+        fprintf(err, "Get privacy for %d\n", sectionId);
+        if (opt == "print") {
+            printPrivacy(p, out, String8(""));
+        } else if (opt == "parse") {
+            FdBuffer buf;
+            status_t error = buf.read(fileno(in), 60000);
+            if (error != NO_ERROR) {
+                fprintf(err, "Error reading from stdin\n");
+                return error;
+            }
+            fprintf(err, "Read %zu bytes\n", buf.size());
+            auto data = buf.data();
+            PrivacyBuffer pBuf(p, data);
+
+            PrivacySpec spec = PrivacySpec::new_spec(argCount > 3 ? atoi(args[3]) : -1);
+            error = pBuf.strip(spec);
+            if (error != NO_ERROR) {
+                fprintf(err, "Error strip pii fields with spec %d\n", spec.dest);
+                return error;
+            }
+            return pBuf.flush(fileno(out));
+        }
+    } else {
+        return cmd_help(out);
+    }
+    return NO_ERROR;
+}
diff --git a/cmds/incidentd/src/IncidentService.h b/cmds/incidentd/src/IncidentService.h
index d6f33df..3c66507 100644
--- a/cmds/incidentd/src/IncidentService.h
+++ b/cmds/incidentd/src/IncidentService.h
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+#pragma once
 
 #ifndef INCIDENT_SERVICE_H
 #define INCIDENT_SERVICE_H
@@ -32,8 +33,7 @@
 using namespace std;
 
 // ================================================================================
-class ReportRequestQueue : public virtual RefBase
-{
+class ReportRequestQueue : public virtual RefBase {
 public:
     ReportRequestQueue();
     virtual ~ReportRequestQueue();
@@ -46,10 +46,8 @@
     deque<sp<ReportRequest> > mQueue;
 };
 
-
 // ================================================================================
-class ReportHandler : public MessageHandler
-{
+class ReportHandler : public MessageHandler {
 public:
     ReportHandler(const sp<Looper>& handlerLooper, const sp<ReportRequestQueue>& queue);
     virtual ~ReportHandler();
@@ -89,7 +87,6 @@
     void send_backlog_to_dropbox();
 };
 
-
 // ================================================================================
 class IncidentService : public BnIncidentManager {
 public:
@@ -99,14 +96,29 @@
     virtual Status reportIncident(const IncidentReportArgs& args);
 
     virtual Status reportIncidentToStream(const IncidentReportArgs& args,
-            const sp<IIncidentReportStatusListener>& listener, const unique_fd& stream);
+                                          const sp<IIncidentReportStatusListener>& listener,
+                                          const unique_fd& stream);
 
     virtual Status systemRunning();
 
+    // Implement commands for debugging purpose.
+    virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply,
+                                uint32_t flags) override;
+    virtual status_t command(FILE* in, FILE* out, FILE* err, Vector<String8>& args);
+
 private:
     sp<ReportRequestQueue> mQueue;
     sp<ReportHandler> mHandler;
+
+    /**
+     * Commands print out help.
+     */
+    status_t cmd_help(FILE* out);
+
+    /**
+     * Commands related to privacy filtering.
+     */
+    status_t cmd_privacy(FILE* in, FILE* out, FILE* err, Vector<String8>& args);
 };
 
-
-#endif // INCIDENT_SERVICE_H
+#endif  // INCIDENT_SERVICE_H
diff --git a/cmds/incidentd/src/Log.h b/cmds/incidentd/src/Log.h
new file mode 100644
index 0000000..46efbd1
--- /dev/null
+++ b/cmds/incidentd/src/Log.h
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+
+/*
+ * This file must be included at the top of the file. Other header files
+ * occasionally include log.h, and if LOG_TAG isn't set when that happens
+ * we'll get a preprocesser error when we try to define it here.
+ */
+
+#pragma once
+
+#define LOG_TAG "incidentd"
+#define DEBUG false
+
+#include <log/log.h>
+
+// Use the local value to turn on/off debug logs instead of using log.tag.properties.
+// The advantage is that in production compiler can remove the logging code if the local
+// DEBUG/VERBOSE is false.
+#define VLOG(...) \
+    if (DEBUG) ALOGD(__VA_ARGS__);
\ No newline at end of file
diff --git a/cmds/incidentd/src/Privacy.cpp b/cmds/incidentd/src/Privacy.cpp
index 3f0e331..c42a87b 100644
--- a/cmds/incidentd/src/Privacy.cpp
+++ b/cmds/incidentd/src/Privacy.cpp
@@ -21,10 +21,9 @@
 
 uint64_t encode_field_id(const Privacy* p) { return (uint64_t)p->type << 32 | p->field_id; }
 
-const Privacy* lookup(const Privacy* p, uint32_t fieldId)
-{
+const Privacy* lookup(const Privacy* p, uint32_t fieldId) {
     if (p->children == NULL) return NULL;
-    for (int i=0; p->children[i] != NULL; i++) { // NULL-terminated.
+    for (int i = 0; p->children[i] != NULL; i++) {  // NULL-terminated.
         if (p->children[i]->field_id == fieldId) return p->children[i];
         // Incident section gen tool guarantees field ids in ascending order.
         if (p->children[i]->field_id > fieldId) return NULL;
@@ -32,52 +31,37 @@
     return NULL;
 }
 
-static bool allowDest(const uint8_t dest, const uint8_t policy)
-{
+static bool allowDest(const uint8_t dest, const uint8_t policy) {
     switch (policy) {
-    case android::os::DEST_LOCAL:
-        return dest == android::os::DEST_LOCAL;
-    case android::os::DEST_EXPLICIT:
-    case DEST_UNSET:
-        return dest == android::os::DEST_LOCAL ||
-            dest == android::os::DEST_EXPLICIT ||
-            dest == DEST_UNSET;
-    case android::os::DEST_AUTOMATIC:
-        return true;
-    default:
-        return false;
+        case android::os::DEST_LOCAL:
+            return dest == android::os::DEST_LOCAL;
+        case android::os::DEST_EXPLICIT:
+        case DEST_UNSET:
+            return dest == android::os::DEST_LOCAL || dest == android::os::DEST_EXPLICIT ||
+                   dest == DEST_UNSET;
+        case android::os::DEST_AUTOMATIC:
+            return true;
+        default:
+            return false;
     }
 }
 
-bool
-PrivacySpec::operator<(const PrivacySpec& other) const
-{
-  return dest < other.dest;
-}
+bool PrivacySpec::operator<(const PrivacySpec& other) const { return dest < other.dest; }
 
-bool
-PrivacySpec::CheckPremission(const Privacy* privacy, const uint8_t defaultDest) const
-{
+bool PrivacySpec::CheckPremission(const Privacy* privacy, const uint8_t defaultDest) const {
     uint8_t policy = privacy != NULL ? privacy->dest : defaultDest;
     return allowDest(dest, policy);
 }
 
-bool
-PrivacySpec::RequireAll() const { return dest == android::os::DEST_LOCAL; }
+bool PrivacySpec::RequireAll() const { return dest == android::os::DEST_LOCAL; }
 
-PrivacySpec PrivacySpec::new_spec(int dest)
-{
+PrivacySpec PrivacySpec::new_spec(int dest) {
     switch (dest) {
         case android::os::DEST_AUTOMATIC:
         case android::os::DEST_EXPLICIT:
         case android::os::DEST_LOCAL:
             return PrivacySpec(dest);
         default:
-            return PrivacySpec();
+            return PrivacySpec(android::os::DEST_AUTOMATIC);
     }
 }
-
-PrivacySpec PrivacySpec::get_default_dropbox_spec()
-{
-    return PrivacySpec(android::os::DEST_AUTOMATIC);
-}
diff --git a/cmds/incidentd/src/Privacy.h b/cmds/incidentd/src/Privacy.h
index 4f3db67..6b6de9c 100644
--- a/cmds/incidentd/src/Privacy.h
+++ b/cmds/incidentd/src/Privacy.h
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+#pragma once
 
 #ifndef PRIVACY_H
 #define PRIVACY_H
@@ -20,7 +21,7 @@
 #include <stdint.h>
 
 // This is the default value of DEST enum, sync with privacy.proto
-const uint8_t DEST_UNSET = 255; // DEST_UNSET is not exposed to libincident
+const uint8_t DEST_UNSET = 255;  // DEST_UNSET is not exposed to libincident
 const uint8_t DEST_DEFAULT_VALUE = DEST_UNSET;
 
 /*
@@ -68,16 +69,17 @@
     bool operator<(const PrivacySpec& other) const;
 
     // check permission of a policy, if returns true, don't strip the data.
-    bool CheckPremission(const Privacy* privacy, const uint8_t defaultDest = DEST_DEFAULT_VALUE) const;
+    bool CheckPremission(const Privacy* privacy,
+                         const uint8_t defaultDest = DEST_DEFAULT_VALUE) const;
 
     // if returns true, no data need to be stripped.
     bool RequireAll() const;
 
     // Constructs spec using static methods below.
     static PrivacySpec new_spec(int dest);
-    static PrivacySpec get_default_dropbox_spec();
+
 private:
     PrivacySpec(uint8_t dest) : dest(dest) {}
 };
 
-#endif // PRIVACY_H
+#endif  // PRIVACY_H
diff --git a/cmds/incidentd/src/PrivacyBuffer.cpp b/cmds/incidentd/src/PrivacyBuffer.cpp
index 03faa92..e4128f4 100644
--- a/cmds/incidentd/src/PrivacyBuffer.cpp
+++ b/cmds/incidentd/src/PrivacyBuffer.cpp
@@ -13,29 +13,22 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
-#define LOG_TAG "incidentd"
+#include "Log.h"
 
 #include "PrivacyBuffer.h"
-#include "io_util.h"
+#include "incidentd_util.h"
 
+#include <android-base/file.h>
 #include <android/util/protobuf.h>
 #include <cutils/log.h>
 
 using namespace android::util;
 
-const bool DEBUG = false;
-
 /**
  * Write the field to buf based on the wire type, iterator will point to next field.
  * If skip is set to true, no data will be written to buf. Return number of bytes written.
  */
-void
-PrivacyBuffer::writeFieldOrSkip(uint32_t fieldTag, bool skip)
-{
-    if (DEBUG) ALOGD("%s field %d (wiretype = %d)", skip ? "skip" : "write",
-        read_field_id(fieldTag), read_wire_type(fieldTag));
-
+void PrivacyBuffer::writeFieldOrSkip(uint32_t fieldTag, bool skip) {
     uint8_t wireType = read_wire_type(fieldTag);
     size_t bytesToWrite = 0;
     uint32_t varint = 0;
@@ -54,18 +47,17 @@
             break;
         case WIRE_TYPE_LENGTH_DELIMITED:
             bytesToWrite = mData.readRawVarint();
-            if(!skip) mProto.writeLengthDelimitedHeader(read_field_id(fieldTag), bytesToWrite);
+            if (!skip) mProto.writeLengthDelimitedHeader(read_field_id(fieldTag), bytesToWrite);
             break;
         case WIRE_TYPE_FIXED32:
             if (!skip) mProto.writeRawVarint(fieldTag);
             bytesToWrite = 4;
             break;
     }
-    if (DEBUG) ALOGD("%s %d bytes of data", skip ? "skip" : "write", (int)bytesToWrite);
     if (skip) {
         mData.rp()->move(bytesToWrite);
     } else {
-        for (size_t i=0; i<bytesToWrite; i++) {
+        for (size_t i = 0; i < bytesToWrite; i++) {
             mProto.writeRawByte(mData.next());
         }
     }
@@ -78,28 +70,29 @@
  * The iterator must point to the head of a protobuf formatted field for successful operation.
  * After exit with NO_ERROR, iterator points to the next protobuf field's head.
  */
-status_t
-PrivacyBuffer::stripField(const Privacy* parentPolicy, const PrivacySpec& spec)
-{
+status_t PrivacyBuffer::stripField(const Privacy* parentPolicy, const PrivacySpec& spec,
+                                   int depth /* use as a counter for this recusive method. */) {
     if (!mData.hasNext() || parentPolicy == NULL) return BAD_VALUE;
     uint32_t fieldTag = mData.readRawVarint();
-    const Privacy* policy = lookup(parentPolicy, read_field_id(fieldTag));
+    uint32_t fieldId = read_field_id(fieldTag);
+    const Privacy* policy = lookup(parentPolicy, fieldId);
 
+    VLOG("[Depth %2d]Try to strip id %d, wiretype %d", depth, fieldId, read_wire_type(fieldTag));
     if (policy == NULL || policy->children == NULL) {
-        if (DEBUG) ALOGD("Not a message field %d: dest(%d)", read_field_id(fieldTag),
-            policy != NULL ? policy->dest : parentPolicy->dest);
-
         bool skip = !spec.CheckPremission(policy, parentPolicy->dest);
         // iterator will point to head of next field
+        size_t currentAt = mData.rp()->pos();
         writeFieldOrSkip(fieldTag, skip);
+        VLOG("[Depth %2d]Field %d %ss %d bytes", depth, fieldId, skip ? "skip" : "write",
+             (int)(get_varint_size(fieldTag) + mData.rp()->pos() - currentAt));
         return NO_ERROR;
     }
     // current field is message type and its sub-fields have extra privacy policies
     uint32_t msgSize = mData.readRawVarint();
-    EncodedBuffer::Pointer start = mData.rp()->copy();
+    size_t start = mData.rp()->pos();
     long long token = mProto.start(encode_field_id(policy));
-    while (mData.rp()->pos() - start.pos() != msgSize) {
-        status_t err = stripField(policy, spec);
+    while (mData.rp()->pos() - start != msgSize) {
+        status_t err = stripField(policy, spec, depth + 1);
         if (err != NO_ERROR) return err;
     }
     mProto.end(token);
@@ -108,53 +101,39 @@
 
 // ================================================================================
 PrivacyBuffer::PrivacyBuffer(const Privacy* policy, EncodedBuffer::iterator& data)
-        :mPolicy(policy),
-         mData(data),
-         mProto(),
-         mSize(0)
-{
-}
+    : mPolicy(policy), mData(data), mProto(), mSize(0) {}
 
-PrivacyBuffer::~PrivacyBuffer()
-{
-}
+PrivacyBuffer::~PrivacyBuffer() {}
 
-status_t
-PrivacyBuffer::strip(const PrivacySpec& spec)
-{
-    if (DEBUG) ALOGD("Strip with spec %d", spec.dest);
+status_t PrivacyBuffer::strip(const PrivacySpec& spec) {
+    VLOG("Strip with spec %d", spec.dest);
     // optimization when no strip happens
     if (mPolicy == NULL || mPolicy->children == NULL || spec.RequireAll()) {
         if (spec.CheckPremission(mPolicy)) mSize = mData.size();
         return NO_ERROR;
     }
     while (mData.hasNext()) {
-        status_t err = stripField(mPolicy, spec);
+        status_t err = stripField(mPolicy, spec, 0);
         if (err != NO_ERROR) return err;
     }
     if (mData.bytesRead() != mData.size()) return BAD_VALUE;
     mSize = mProto.size();
-    mData.rp()->rewind(); // rewind the read pointer back to beginning after the strip.
+    mData.rp()->rewind();  // rewind the read pointer back to beginning after the strip.
     return NO_ERROR;
 }
 
-void
-PrivacyBuffer::clear()
-{
+void PrivacyBuffer::clear() {
     mSize = 0;
-    mProto = ProtoOutputStream();
+    mProto.clear();
 }
 
-size_t
-PrivacyBuffer::size() const { return mSize; }
+size_t PrivacyBuffer::size() const { return mSize; }
 
-status_t
-PrivacyBuffer::flush(int fd)
-{
+status_t PrivacyBuffer::flush(int fd) {
     status_t err = NO_ERROR;
     EncodedBuffer::iterator iter = size() == mData.size() ? mData : mProto.data();
     while (iter.readBuffer() != NULL) {
-        err = write_all(fd, iter.readBuffer(), iter.currentToRead());
+        err = WriteFully(fd, iter.readBuffer(), iter.currentToRead()) ? NO_ERROR : -errno;
         iter.rp()->move(iter.currentToRead());
         if (err != NO_ERROR) return err;
     }
diff --git a/cmds/incidentd/src/PrivacyBuffer.h b/cmds/incidentd/src/PrivacyBuffer.h
index c9ca9a7..92e1a25 100644
--- a/cmds/incidentd/src/PrivacyBuffer.h
+++ b/cmds/incidentd/src/PrivacyBuffer.h
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+#pragma once
 
 #ifndef PRIVACY_BUFFER_H
 #define PRIVACY_BUFFER_H
@@ -31,14 +32,14 @@
  * PrivacyBuffer holds the original protobuf data and strips PII-sensitive fields
  * based on the request and holds stripped data in its own buffer for output.
  */
-class PrivacyBuffer
-{
+class PrivacyBuffer {
 public:
     PrivacyBuffer(const Privacy* policy, EncodedBuffer::iterator& data);
     ~PrivacyBuffer();
 
     /**
-     * Strip based on the request and hold data in its own buffer. Return NO_ERROR if strip succeeds.
+     * Strip based on the request and hold data in its own buffer. Return NO_ERROR if strip
+     * succeeds.
      */
     status_t strip(const PrivacySpec& spec);
 
@@ -64,8 +65,8 @@
     ProtoOutputStream mProto;
     size_t mSize;
 
-    status_t stripField(const Privacy* parentPolicy, const PrivacySpec& spec);
+    status_t stripField(const Privacy* parentPolicy, const PrivacySpec& spec, int depth);
     void writeFieldOrSkip(uint32_t fieldTag, bool skip);
 };
 
-#endif // PRIVACY_BUFFER_H
\ No newline at end of file
+#endif  // PRIVACY_BUFFER_H
\ No newline at end of file
diff --git a/cmds/incidentd/src/Reporter.cpp b/cmds/incidentd/src/Reporter.cpp
index b9f479b..c0b5358 100644
--- a/cmds/incidentd/src/Reporter.cpp
+++ b/cmds/incidentd/src/Reporter.cpp
@@ -13,11 +13,11 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
-#define LOG_TAG "incidentd"
+#include "Log.h"
 
 #include "Reporter.h"
 
+#include "Privacy.h"
 #include "report_directory.h"
 #include "section_list.h"
 
@@ -25,11 +25,11 @@
 #include <private/android_filesystem_config.h>
 #include <utils/SystemClock.h>
 
-#include <sys/types.h>
-#include <sys/stat.h>
 #include <dirent.h>
-#include <fcntl.h>
 #include <errno.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
 
 /**
  * The directory where the incident reports are stored.
@@ -38,72 +38,67 @@
 
 // ================================================================================
 ReportRequest::ReportRequest(const IncidentReportArgs& a,
-            const sp<IIncidentReportStatusListener> &l, int f)
-    :args(a),
-     listener(l),
-     fd(f),
-     err(NO_ERROR)
-{
-}
+                             const sp<IIncidentReportStatusListener>& l, int f)
+    : args(a), listener(l), fd(f), err(NO_ERROR) {}
 
-ReportRequest::~ReportRequest()
-{
+ReportRequest::~ReportRequest() {
     if (fd >= 0) {
         // clean up the opened file descriptor
         close(fd);
     }
 }
 
-bool
-ReportRequest::ok()
-{
-    return fd >= 0 && err == NO_ERROR;
-}
+bool ReportRequest::ok() { return fd >= 0 && err == NO_ERROR; }
 
 // ================================================================================
 ReportRequestSet::ReportRequestSet()
-    :mRequests(),
-     mSections(),
-     mMainFd(-1),
-     mMainDest(-1)
-{
-}
+    : mRequests(), mSections(), mMainFd(-1), mMainDest(-1), mMetadata(), mSectionStats() {}
 
-ReportRequestSet::~ReportRequestSet()
-{
-}
+ReportRequestSet::~ReportRequestSet() {}
 
 // TODO: dedup on exact same args and fd, report the status back to listener!
-void
-ReportRequestSet::add(const sp<ReportRequest>& request)
-{
+void ReportRequestSet::add(const sp<ReportRequest>& request) {
     mRequests.push_back(request);
     mSections.merge(request->args);
+    mMetadata.set_request_size(mMetadata.request_size() + 1);
 }
 
-void
-ReportRequestSet::setMainFd(int fd)
-{
+void ReportRequestSet::setMainFd(int fd) {
     mMainFd = fd;
+    mMetadata.set_use_dropbox(fd > 0);
 }
 
-void
-ReportRequestSet::setMainDest(int dest)
-{
+void ReportRequestSet::setMainDest(int dest) {
     mMainDest = dest;
+    PrivacySpec spec = PrivacySpec::new_spec(dest);
+    switch (spec.dest) {
+        case android::os::DEST_AUTOMATIC:
+            mMetadata.set_dest(IncidentMetadata_Destination_AUTOMATIC);
+            break;
+        case android::os::DEST_EXPLICIT:
+            mMetadata.set_dest(IncidentMetadata_Destination_EXPLICIT);
+            break;
+        case android::os::DEST_LOCAL:
+            mMetadata.set_dest(IncidentMetadata_Destination_LOCAL);
+            break;
+    }
 }
 
-bool
-ReportRequestSet::containsSection(int id) {
-    return mSections.containsSection(id);
+bool ReportRequestSet::containsSection(int id) { return mSections.containsSection(id); }
+
+IncidentMetadata::SectionStats* ReportRequestSet::sectionStats(int id) {
+    if (mSectionStats.find(id) == mSectionStats.end()) {
+        auto stats = mMetadata.add_sections();
+        stats->set_id(id);
+        mSectionStats[id] = stats;
+    }
+    return mSectionStats[id];
 }
 
 // ================================================================================
 Reporter::Reporter() : Reporter(INCIDENT_DIRECTORY) { isTest = false; };
 
-Reporter::Reporter(const char* directory)
-    :batch()
-{
+Reporter::Reporter(const char* directory) : batch() {
     char buf[100];
 
     // TODO: Make the max size smaller for user builds.
@@ -121,22 +116,18 @@
     mFilename = mIncidentDirectory + buf;
 }
 
-Reporter::~Reporter()
-{
-}
+Reporter::~Reporter() {}
 
-Reporter::run_report_status_t
-Reporter::runReport()
-{
-
+Reporter::run_report_status_t Reporter::runReport() {
     status_t err = NO_ERROR;
     bool needMainFd = false;
     int mainFd = -1;
     int mainDest = -1;
     HeaderSection headers;
+    MetadataSection metadataSection;
 
     // See if we need the main file
-    for (ReportRequestSet::iterator it=batch.begin(); it!=batch.end(); it++) {
+    for (ReportRequestSet::iterator it = batch.begin(); it != batch.end(); it++) {
         if ((*it)->fd < 0 && mainFd < 0) {
             needMainFd = true;
             mainDest = (*it)->args.dest();
@@ -167,7 +158,7 @@
     }
 
     // Tell everyone that we're starting.
-    for (ReportRequestSet::iterator it=batch.begin(); it!=batch.end(); it++) {
+    for (ReportRequestSet::iterator it = batch.begin(); it != batch.end(); it++) {
         if ((*it)->listener != NULL) {
             (*it)->listener->onReportStarted();
         }
@@ -178,31 +169,36 @@
 
     // For each of the report fields, see if we need it, and if so, execute the command
     // and report to those that care that we're doing it.
-    for (const Section** section=SECTION_LIST; *section; section++) {
+    for (const Section** section = SECTION_LIST; *section; section++) {
         const int id = (*section)->id;
         if (this->batch.containsSection(id)) {
             ALOGD("Taking incident report section %d '%s'", id, (*section)->name.string());
-            // Notify listener of starting
-            for (ReportRequestSet::iterator it=batch.begin(); it!=batch.end(); it++) {
+            for (ReportRequestSet::iterator it = batch.begin(); it != batch.end(); it++) {
                 if ((*it)->listener != NULL && (*it)->args.containsSection(id)) {
-                    (*it)->listener->onReportSectionStatus(id,
-                            IIncidentReportStatusListener::STATUS_STARTING);
+                    (*it)->listener->onReportSectionStatus(
+                            id, IIncidentReportStatusListener::STATUS_STARTING);
                 }
             }
 
             // Execute - go get the data and write it into the file descriptors.
+            auto stats = batch.sectionStats(id);
+            int64_t startTime = uptimeMillis();
             err = (*section)->Execute(&batch);
+            int64_t endTime = uptimeMillis();
+
+            stats->set_success(err == NO_ERROR);
+            stats->set_exec_duration_ms(endTime - startTime);
             if (err != NO_ERROR) {
                 ALOGW("Incident section %s (%d) failed: %s. Stopping report.",
-                        (*section)->name.string(), id, strerror(-err));
+                      (*section)->name.string(), id, strerror(-err));
                 goto DONE;
             }
 
             // Notify listener of starting
-            for (ReportRequestSet::iterator it=batch.begin(); it!=batch.end(); it++) {
+            for (ReportRequestSet::iterator it = batch.begin(); it != batch.end(); it++) {
                 if ((*it)->listener != NULL && (*it)->args.containsSection(id)) {
-                    (*it)->listener->onReportSectionStatus(id,
-                            IIncidentReportStatusListener::STATUS_FINISHED);
+                    (*it)->listener->onReportSectionStatus(
+                            id, IIncidentReportStatusListener::STATUS_FINISHED);
                 }
             }
             ALOGD("Finish incident report section %d '%s'", id, (*section)->name.string());
@@ -210,13 +206,16 @@
     }
 
 DONE:
+    // Reports the metdadata when taking the incident report.
+    if (!isTest) metadataSection.Execute(&batch);
+
     // Close the file.
     if (mainFd >= 0) {
         close(mainFd);
     }
 
     // Tell everyone that we're done.
-    for (ReportRequestSet::iterator it=batch.begin(); it!=batch.end(); it++) {
+    for (ReportRequestSet::iterator it = batch.begin(); it != batch.end(); it++) {
         if ((*it)->listener != NULL) {
             if (err == NO_ERROR) {
                 (*it)->listener->onReportFinished();
@@ -238,7 +237,7 @@
         // If the status was ok, delete the file. If not, leave it around until the next
         // boot or the next checkin. If the directory gets too big older files will
         // be rotated out.
-        if(!isTest) unlink(mFilename.c_str());
+        if (!isTest) unlink(mFilename.c_str());
     }
 
     return REPORT_FINISHED;
@@ -247,9 +246,7 @@
 /**
  * Create our output file and set the access permissions to -rw-rw----
  */
-status_t
-Reporter::create_file(int* fd)
-{
+status_t Reporter::create_file(int* fd) {
     const char* filename = mFilename.c_str();
 
     *fd = open(filename, O_CREAT | O_TRUNC | O_RDWR | O_CLOEXEC, 0660);
@@ -271,9 +268,7 @@
     return NO_ERROR;
 }
 
-Reporter::run_report_status_t
-Reporter::upload_backlog()
-{
+Reporter::run_report_status_t Reporter::upload_backlog() {
     DIR* dir;
     struct dirent* entry;
     struct stat st;
@@ -324,4 +319,3 @@
 
     return REPORT_FINISHED;
 }
-
diff --git a/cmds/incidentd/src/Reporter.h b/cmds/incidentd/src/Reporter.h
index f30ecf0..0f3f221 100644
--- a/cmds/incidentd/src/Reporter.h
+++ b/cmds/incidentd/src/Reporter.h
@@ -13,13 +13,17 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+#pragma once
 
 #ifndef REPORTER_H
 #define REPORTER_H
 
+#include "frameworks/base/libs/incident/proto/android/os/metadata.pb.h"
+
 #include <android/os/IIncidentReportStatusListener.h>
 #include <android/os/IncidentReportArgs.h>
 
+#include <map>
 #include <string>
 #include <vector>
 
@@ -30,23 +34,21 @@
 using namespace std;
 
 // ================================================================================
-struct ReportRequest : public virtual RefBase
-{
+struct ReportRequest : public virtual RefBase {
     IncidentReportArgs args;
     sp<IIncidentReportStatusListener> listener;
     int fd;
     status_t err;
 
-    ReportRequest(const IncidentReportArgs& args,
-            const sp<IIncidentReportStatusListener> &listener, int fd);
+    ReportRequest(const IncidentReportArgs& args, const sp<IIncidentReportStatusListener>& listener,
+                  int fd);
     virtual ~ReportRequest();
 
-    bool ok(); // returns true if the request is ok for write.
+    bool ok();  // returns true if the request is ok for write.
 };
 
 // ================================================================================
-class ReportRequestSet
-{
+class ReportRequestSet {
 public:
     ReportRequestSet();
     ~ReportRequestSet();
@@ -61,28 +63,31 @@
     iterator end() { return mRequests.end(); }
 
     int mainFd() { return mMainFd; }
-    bool containsSection(int id);
     int mainDest() { return mMainDest; }
+    IncidentMetadata& metadata() { return mMetadata; }
+
+    bool containsSection(int id);
+    IncidentMetadata::SectionStats* sectionStats(int id);
+
 private:
     vector<sp<ReportRequest>> mRequests;
     IncidentReportArgs mSections;
     int mMainFd;
     int mMainDest;
+
+    IncidentMetadata mMetadata;
+    map<int, IncidentMetadata::SectionStats*> mSectionStats;
 };
 
 // ================================================================================
-class Reporter : public virtual RefBase
-{
+class Reporter : public virtual RefBase {
 public:
-    enum run_report_status_t {
-        REPORT_FINISHED = 0,
-        REPORT_NEEDS_DROPBOX = 1
-    };
+    enum run_report_status_t { REPORT_FINISHED = 0, REPORT_NEEDS_DROPBOX = 1 };
 
     ReportRequestSet batch;
 
-    Reporter();
-    Reporter(const char* directory);
+    Reporter();                       // PROD must use this constructor.
+    Reporter(const char* directory);  // For testing purpose only.
     virtual ~Reporter();
 
     // Run the report as described in the batch and args parameters.
@@ -100,8 +105,7 @@
 
     status_t create_file(int* fd);
 
-    bool isTest = true; // default to true for testing
+    bool isTest = true;  // default to true for testing
 };
 
-
-#endif // REPORTER_H
+#endif  // REPORTER_H
diff --git a/cmds/incidentd/src/Section.cpp b/cmds/incidentd/src/Section.cpp
index faeab87..2e4e980 100644
--- a/cmds/incidentd/src/Section.cpp
+++ b/cmds/incidentd/src/Section.cpp
@@ -13,8 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
-#define LOG_TAG "incidentd"
+#include "Log.h"
 
 #include "Section.h"
 
@@ -26,42 +25,41 @@
 #include <memory>
 #include <mutex>
 
+#include <android-base/file.h>
 #include <android/util/protobuf.h>
 #include <binder/IServiceManager.h>
 #include <log/log_event_list.h>
-#include <log/logprint.h>
 #include <log/log_read.h>
+#include <log/logprint.h>
 #include <private/android_logger.h>
 
 #include "FdBuffer.h"
-#include "frameworks/base/core/proto/android/util/log.proto.h"
-#include "io_util.h"
 #include "Privacy.h"
 #include "PrivacyBuffer.h"
-#include "section_list.h"
+#include "frameworks/base/core/proto/android/util/log.proto.h"
+#include "incidentd_util.h"
 
+using namespace android::base;
 using namespace android::util;
 using namespace std;
 
 // special section ids
 const int FIELD_ID_INCIDENT_HEADER = 1;
+const int FIELD_ID_INCIDENT_METADATA = 2;
 
 // incident section parameters
-const int   WAIT_MAX = 5;
+const int WAIT_MAX = 5;
 const struct timespec WAIT_INTERVAL_NS = {0, 200 * 1000 * 1000};
 const char INCIDENT_HELPER[] = "/system/bin/incident_helper";
 
-static pid_t
-fork_execute_incident_helper(const int id, const char* name, Fpipe& p2cPipe, Fpipe& c2pPipe)
-{
-    const char* ihArgs[] { INCIDENT_HELPER, "-s", String8::format("%d", id).string(), NULL };
+static pid_t fork_execute_incident_helper(const int id, const char* name, Fpipe& p2cPipe,
+                                          Fpipe& c2pPipe) {
+    const char* ihArgs[]{INCIDENT_HELPER, "-s", String8::format("%d", id).string(), NULL};
     // fork used in multithreaded environment, avoid adding unnecessary code in child process
     pid_t pid = fork();
     if (pid == 0) {
-        if (TEMP_FAILURE_RETRY(dup2(p2cPipe.readFd(),  STDIN_FILENO))  != 0
-            || !p2cPipe.close()
-            || TEMP_FAILURE_RETRY(dup2(c2pPipe.writeFd(), STDOUT_FILENO)) != 1
-            || !c2pPipe.close()) {
+        if (TEMP_FAILURE_RETRY(dup2(p2cPipe.readFd(), STDIN_FILENO)) != 0 || !p2cPipe.close() ||
+            TEMP_FAILURE_RETRY(dup2(c2pPipe.writeFd(), STDOUT_FILENO)) != 1 || !c2pPipe.close()) {
             ALOGW("%s can't setup stdin and stdout for incident helper", name);
             _exit(EXIT_FAILURE);
         }
@@ -72,7 +70,7 @@
         execv(INCIDENT_HELPER, const_cast<char**>(ihArgs));
 
         ALOGW("%s failed in incident helper process: %s", name, strerror(errno));
-        _exit(EXIT_FAILURE); // always exits with failure if any
+        _exit(EXIT_FAILURE);  // always exits with failure if any
     }
     // close the fds used in incident helper
     close(p2cPipe.readFd());
@@ -83,18 +81,18 @@
 // ================================================================================
 static status_t statusCode(int status) {
     if (WIFSIGNALED(status)) {
-      ALOGD("return by signal: %s", strerror(WTERMSIG(status)));
-      return -WTERMSIG(status);
+        VLOG("return by signal: %s", strerror(WTERMSIG(status)));
+        return -WTERMSIG(status);
     } else if (WIFEXITED(status) && WEXITSTATUS(status) > 0) {
-      ALOGD("return by exit: %s", strerror(WEXITSTATUS(status)));
-      return -WEXITSTATUS(status);
+        VLOG("return by exit: %s", strerror(WEXITSTATUS(status)));
+        return -WEXITSTATUS(status);
     }
     return NO_ERROR;
 }
 
 static status_t kill_child(pid_t pid) {
     int status;
-    ALOGD("try to kill child process %d", pid);
+    VLOG("try to kill child process %d", pid);
     kill(pid, SIGKILL);
     if (waitpid(pid, &status, 0) == -1) return -1;
     return statusCode(status);
@@ -104,7 +102,7 @@
     int status;
     bool died = false;
     // wait for child to report status up to 1 seconds
-    for(int loop = 0; !died && loop < WAIT_MAX; loop++) {
+    for (int loop = 0; !died && loop < WAIT_MAX; loop++) {
         if (waitpid(pid, &status, WNOHANG) == pid) died = true;
         // sleep for 0.2 second
         nanosleep(&WAIT_INTERVAL_NS, NULL);
@@ -113,42 +111,24 @@
     return statusCode(status);
 }
 // ================================================================================
-static const Privacy*
-get_privacy_of_section(int id)
-{
-    int l = 0;
-    int r = PRIVACY_POLICY_COUNT - 1;
-    while (l <= r) {
-        int mid = (l + r) >> 1;
-        const Privacy* p = PRIVACY_POLICY_LIST[mid];
-
-        if (p->field_id < (uint32_t)id) {
-            l = mid + 1;
-        } else if (p->field_id > (uint32_t)id) {
-            r = mid - 1;
-        } else {
-            return p;
-        }
-    }
-    return NULL;
-}
-
-// ================================================================================
-static status_t
-write_section_header(int fd, int sectionId, size_t size)
-{
+static status_t write_section_header(int fd, int sectionId, size_t size) {
     uint8_t buf[20];
-    uint8_t *p = write_length_delimited_tag_header(buf, sectionId, size);
-    return write_all(fd, buf, p-buf);
+    uint8_t* p = write_length_delimited_tag_header(buf, sectionId, size);
+    return WriteFully(fd, buf, p - buf) ? NO_ERROR : -errno;
 }
 
-static status_t
-write_report_requests(const int id, const FdBuffer& buffer, ReportRequestSet* requests)
-{
+static status_t write_report_requests(const int id, const FdBuffer& buffer,
+                                      ReportRequestSet* requests) {
     status_t err = -EBADF;
     EncodedBuffer::iterator data = buffer.data();
     PrivacyBuffer privacyBuffer(get_privacy_of_section(id), data);
     int writeable = 0;
+    auto stats = requests->sectionStats(id);
+
+    stats->set_dump_size_bytes(data.size());
+    stats->set_dump_duration_ms(buffer.durationMs());
+    stats->set_timed_out(buffer.timedOut());
+    stats->set_is_truncated(buffer.truncated());
 
     // The streaming ones, group requests by spec in order to save unnecessary strip operations
     map<PrivacySpec, vector<sp<ReportRequest>>> requestsBySpec;
@@ -164,38 +144,49 @@
     for (auto mit = requestsBySpec.begin(); mit != requestsBySpec.end(); mit++) {
         PrivacySpec spec = mit->first;
         err = privacyBuffer.strip(spec);
-        if (err != NO_ERROR) return err; // it means the privacyBuffer data is corrupted.
+        if (err != NO_ERROR) return err;  // it means the privacyBuffer data is corrupted.
         if (privacyBuffer.size() == 0) continue;
 
         for (auto it = mit->second.begin(); it != mit->second.end(); it++) {
             sp<ReportRequest> request = *it;
             err = write_section_header(request->fd, id, privacyBuffer.size());
-            if (err != NO_ERROR) { request->err = err; continue; }
+            if (err != NO_ERROR) {
+                request->err = err;
+                continue;
+            }
             err = privacyBuffer.flush(request->fd);
-            if (err != NO_ERROR) { request->err = err; continue; }
+            if (err != NO_ERROR) {
+                request->err = err;
+                continue;
+            }
             writeable++;
-            ALOGD("Section %d flushed %zu bytes to fd %d with spec %d", id,
-                  privacyBuffer.size(), request->fd, spec.dest);
+            VLOG("Section %d flushed %zu bytes to fd %d with spec %d", id, privacyBuffer.size(),
+                 request->fd, spec.dest);
         }
         privacyBuffer.clear();
     }
 
     // The dropbox file
     if (requests->mainFd() >= 0) {
-        PrivacySpec spec = requests->mainDest() < 0 ?
-                PrivacySpec::get_default_dropbox_spec() :
-                PrivacySpec::new_spec(requests->mainDest());
+        PrivacySpec spec = PrivacySpec::new_spec(requests->mainDest());
         err = privacyBuffer.strip(spec);
-        if (err != NO_ERROR) return err; // the buffer data is corrupted.
+        if (err != NO_ERROR) return err;  // the buffer data is corrupted.
         if (privacyBuffer.size() == 0) goto DONE;
 
         err = write_section_header(requests->mainFd(), id, privacyBuffer.size());
-        if (err != NO_ERROR) { requests->setMainFd(-1); goto DONE; }
+        if (err != NO_ERROR) {
+            requests->setMainFd(-1);
+            goto DONE;
+        }
         err = privacyBuffer.flush(requests->mainFd());
-        if (err != NO_ERROR) { requests->setMainFd(-1); goto DONE; }
+        if (err != NO_ERROR) {
+            requests->setMainFd(-1);
+            goto DONE;
+        }
         writeable++;
-        ALOGD("Section %d flushed %zu bytes to dropbox %d with spec %d", id,
-              privacyBuffer.size(), requests->mainFd(), spec.dest);
+        VLOG("Section %d flushed %zu bytes to dropbox %d with spec %d", id, privacyBuffer.size(),
+             requests->mainFd(), spec.dest);
+        stats->set_report_size_bytes(privacyBuffer.size());
     }
 
 DONE:
@@ -204,67 +195,78 @@
 }
 
 // ================================================================================
-Section::Section(int i, const int64_t timeoutMs)
-    :id(i),
-     timeoutMs(timeoutMs)
-{
-}
+Section::Section(int i, const int64_t timeoutMs) : id(i), timeoutMs(timeoutMs) {}
 
-Section::~Section()
-{
-}
+Section::~Section() {}
 
 // ================================================================================
-HeaderSection::HeaderSection()
-    :Section(FIELD_ID_INCIDENT_HEADER, 0)
-{
-}
+HeaderSection::HeaderSection() : Section(FIELD_ID_INCIDENT_HEADER, 0) {}
 
-HeaderSection::~HeaderSection()
-{
-}
+HeaderSection::~HeaderSection() {}
 
-status_t
-HeaderSection::Execute(ReportRequestSet* requests) const
-{
-    for (ReportRequestSet::iterator it=requests->begin(); it!=requests->end(); it++) {
+status_t HeaderSection::Execute(ReportRequestSet* requests) const {
+    for (ReportRequestSet::iterator it = requests->begin(); it != requests->end(); it++) {
         const sp<ReportRequest> request = *it;
         const vector<vector<uint8_t>>& headers = request->args.headers();
 
-        for (vector<vector<uint8_t>>::const_iterator buf=headers.begin(); buf!=headers.end(); buf++) {
+        for (vector<vector<uint8_t>>::const_iterator buf = headers.begin(); buf != headers.end();
+             buf++) {
             if (buf->empty()) continue;
 
             // So the idea is only requests with negative fd are written to dropbox file.
             int fd = request->fd >= 0 ? request->fd : requests->mainFd();
-            write_section_header(fd, FIELD_ID_INCIDENT_HEADER, buf->size());
-            write_all(fd, (uint8_t const*)buf->data(), buf->size());
+            write_section_header(fd, id, buf->size());
+            WriteFully(fd, (uint8_t const*)buf->data(), buf->size());
             // If there was an error now, there will be an error later and we will remove
             // it from the list then.
         }
     }
     return NO_ERROR;
 }
+// ================================================================================
+MetadataSection::MetadataSection() : Section(FIELD_ID_INCIDENT_METADATA, 0) {}
 
+MetadataSection::~MetadataSection() {}
+
+status_t MetadataSection::Execute(ReportRequestSet* requests) const {
+    std::string metadataBuf;
+    requests->metadata().SerializeToString(&metadataBuf);
+    for (ReportRequestSet::iterator it = requests->begin(); it != requests->end(); it++) {
+        const sp<ReportRequest> request = *it;
+        if (metadataBuf.empty() || request->fd < 0 || request->err != NO_ERROR) {
+            continue;
+        }
+        write_section_header(request->fd, id, metadataBuf.size());
+        if (!WriteFully(request->fd, (uint8_t const*)metadataBuf.data(), metadataBuf.size())) {
+            ALOGW("Failed to write metadata to fd %d", request->fd);
+            // we don't fail if we can't write to a single request's fd.
+        }
+    }
+    if (requests->mainFd() >= 0 && !metadataBuf.empty()) {
+        write_section_header(requests->mainFd(), id, metadataBuf.size());
+        if (!WriteFully(requests->mainFd(), (uint8_t const*)metadataBuf.data(), metadataBuf.size())) {
+            ALOGW("Failed to write metadata to dropbox fd %d", requests->mainFd());
+            return -1;
+        }
+    }
+    return NO_ERROR;
+}
 // ================================================================================
 FileSection::FileSection(int id, const char* filename, const int64_t timeoutMs)
-    :Section(id, timeoutMs),
-     mFilename(filename)
-{
+    : Section(id, timeoutMs), mFilename(filename) {
     name = filename;
     mIsSysfs = strncmp(filename, "/sys/", 5) == 0;
 }
 
 FileSection::~FileSection() {}
 
-status_t
-FileSection::Execute(ReportRequestSet* requests) const
-{
+status_t FileSection::Execute(ReportRequestSet* requests) const {
     // read from mFilename first, make sure the file is available
     // add O_CLOEXEC to make sure it is closed when exec incident helper
     int fd = open(mFilename, O_RDONLY | O_CLOEXEC);
     if (fd == -1) {
-       ALOGW("FileSection '%s' failed to open file", this->name.string());
-       return -errno;
+        ALOGW("FileSection '%s' failed to open file", this->name.string());
+        return -errno;
     }
 
     FdBuffer buffer;
@@ -284,22 +286,23 @@
 
     // parent process
     status_t readStatus = buffer.readProcessedDataInStream(fd, p2cPipe.writeFd(), c2pPipe.readFd(),
-            this->timeoutMs, mIsSysfs);
+                                                           this->timeoutMs, mIsSysfs);
     if (readStatus != NO_ERROR || buffer.timedOut()) {
         ALOGW("FileSection '%s' failed to read data from incident helper: %s, timedout: %s",
-            this->name.string(), strerror(-readStatus), buffer.timedOut() ? "true" : "false");
+              this->name.string(), strerror(-readStatus), buffer.timedOut() ? "true" : "false");
         kill_child(pid);
         return readStatus;
     }
 
     status_t ihStatus = wait_child(pid);
     if (ihStatus != NO_ERROR) {
-        ALOGW("FileSection '%s' abnormal child process: %s", this->name.string(), strerror(-ihStatus));
+        ALOGW("FileSection '%s' abnormal child process: %s", this->name.string(),
+              strerror(-ihStatus));
         return ihStatus;
     }
 
-    ALOGD("FileSection '%s' wrote %zd bytes in %d ms", this->name.string(), buffer.size(),
-            (int)buffer.durationMs());
+    VLOG("FileSection '%s' wrote %zd bytes in %d ms", this->name.string(), buffer.size(),
+         (int)buffer.durationMs());
     status_t err = write_report_requests(this->id, buffer, requests);
     if (err != NO_ERROR) {
         ALOGW("FileSection '%s' failed writing: %s", this->name.string(), strerror(-err));
@@ -310,8 +313,7 @@
 }
 
 // ================================================================================
-struct WorkerThreadData : public virtual RefBase
-{
+struct WorkerThreadData : public virtual RefBase {
     const WorkerThreadSection* section;
     int fds[2];
 
@@ -328,31 +330,19 @@
 };
 
 WorkerThreadData::WorkerThreadData(const WorkerThreadSection* sec)
-    :section(sec),
-     workerDone(false),
-     workerError(NO_ERROR)
-{
+    : section(sec), workerDone(false), workerError(NO_ERROR) {
     fds[0] = -1;
     fds[1] = -1;
 }
 
-WorkerThreadData::~WorkerThreadData()
-{
-}
+WorkerThreadData::~WorkerThreadData() {}
 
 // ================================================================================
-WorkerThreadSection::WorkerThreadSection(int id)
-    :Section(id)
-{
-}
+WorkerThreadSection::WorkerThreadSection(int id) : Section(id) {}
 
-WorkerThreadSection::~WorkerThreadSection()
-{
-}
+WorkerThreadSection::~WorkerThreadSection() {}
 
-static void*
-worker_thread_func(void* cookie)
-{
+static void* worker_thread_func(void* cookie) {
     WorkerThreadData* data = (WorkerThreadData*)cookie;
     status_t err = data->section->BlockingCall(data->writeFd());
 
@@ -368,9 +358,7 @@
     return NULL;
 }
 
-status_t
-WorkerThreadSection::Execute(ReportRequestSet* requests) const
-{
+status_t WorkerThreadSection::Execute(ReportRequestSet* requests) const {
     status_t err = NO_ERROR;
     pthread_t thread;
     pthread_attr_t attr;
@@ -413,7 +401,7 @@
     if (err != NO_ERROR) {
         // TODO: Log this error into the incident report.
         ALOGW("WorkerThreadSection '%s' reader failed with error '%s'", this->name.string(),
-                strerror(-err));
+              strerror(-err));
     }
 
     // Done with the read fd. The worker thread closes the write one so
@@ -432,7 +420,7 @@
                 err = data->workerError;
                 // TODO: Log this error into the incident report.
                 ALOGW("WorkerThreadSection '%s' worker failed with error '%s'", this->name.string(),
-                        strerror(-err));
+                      strerror(-err));
             }
         }
     }
@@ -450,13 +438,13 @@
     // just exit with a log messasge.
     if (err != NO_ERROR) {
         ALOGW("WorkerThreadSection '%s' failed with error '%s'", this->name.string(),
-                strerror(-err));
+              strerror(-err));
         return NO_ERROR;
     }
 
     // Write the data that was collected
-    ALOGD("WorkerThreadSection '%s' wrote %zd bytes in %d ms", name.string(), buffer.size(),
-            (int)buffer.durationMs());
+    VLOG("WorkerThreadSection '%s' wrote %zd bytes in %d ms", name.string(), buffer.size(),
+         (int)buffer.durationMs());
     err = write_report_requests(this->id, buffer, requests);
     if (err != NO_ERROR) {
         ALOGW("WorkerThreadSection '%s' failed writing: '%s'", this->name.string(), strerror(-err));
@@ -467,14 +455,12 @@
 }
 
 // ================================================================================
-void
-CommandSection::init(const char* command, va_list args)
-{
+void CommandSection::init(const char* command, va_list args) {
     va_list copied_args;
     int numOfArgs = 0;
 
     va_copy(copied_args, args);
-    while(va_arg(copied_args, const char*) != NULL) {
+    while (va_arg(copied_args, const char*) != NULL) {
         numOfArgs++;
     }
     va_end(copied_args);
@@ -484,41 +470,33 @@
 
     mCommand[0] = command;
     name = command;
-    for (int i=0; i<numOfArgs; i++) {
+    for (int i = 0; i < numOfArgs; i++) {
         const char* arg = va_arg(args, const char*);
-        mCommand[i+1] = arg;
+        mCommand[i + 1] = arg;
         name += " ";
         name += arg;
     }
-    mCommand[numOfArgs+1] = NULL;
+    mCommand[numOfArgs + 1] = NULL;
 }
 
 CommandSection::CommandSection(int id, const int64_t timeoutMs, const char* command, ...)
-    :Section(id, timeoutMs)
-{
+    : Section(id, timeoutMs) {
     va_list args;
     va_start(args, command);
     init(command, args);
     va_end(args);
 }
 
-CommandSection::CommandSection(int id, const char* command, ...)
-    :Section(id)
-{
+CommandSection::CommandSection(int id, const char* command, ...) : Section(id) {
     va_list args;
     va_start(args, command);
     init(command, args);
     va_end(args);
 }
 
-CommandSection::~CommandSection()
-{
-    free(mCommand);
-}
+CommandSection::~CommandSection() { free(mCommand); }
 
-status_t
-CommandSection::Execute(ReportRequestSet* requests) const
-{
+status_t CommandSection::Execute(ReportRequestSet* requests) const {
     FdBuffer buffer;
     Fpipe cmdPipe;
     Fpipe ihPipe;
@@ -537,13 +515,15 @@
     if (cmdPid == 0) {
         // replace command's stdout with ihPipe's write Fd
         if (dup2(cmdPipe.writeFd(), STDOUT_FILENO) != 1 || !ihPipe.close() || !cmdPipe.close()) {
-            ALOGW("CommandSection '%s' failed to set up stdout: %s", this->name.string(), strerror(errno));
+            ALOGW("CommandSection '%s' failed to set up stdout: %s", this->name.string(),
+                  strerror(errno));
             _exit(EXIT_FAILURE);
         }
-        execvp(this->mCommand[0], (char *const *) this->mCommand);
-        int err = errno; // record command error code
-        ALOGW("CommandSection '%s' failed in executing command: %s", this->name.string(), strerror(errno));
-        _exit(err); // exit with command error code
+        execvp(this->mCommand[0], (char* const*)this->mCommand);
+        int err = errno;  // record command error code
+        ALOGW("CommandSection '%s' failed in executing command: %s", this->name.string(),
+              strerror(errno));
+        _exit(err);  // exit with command error code
     }
     pid_t ihPid = fork_execute_incident_helper(this->id, this->name.string(), cmdPipe, ihPipe);
     if (ihPid == -1) {
@@ -555,24 +535,26 @@
     status_t readStatus = buffer.read(ihPipe.readFd(), this->timeoutMs);
     if (readStatus != NO_ERROR || buffer.timedOut()) {
         ALOGW("CommandSection '%s' failed to read data from incident helper: %s, timedout: %s",
-            this->name.string(), strerror(-readStatus), buffer.timedOut() ? "true" : "false");
+              this->name.string(), strerror(-readStatus), buffer.timedOut() ? "true" : "false");
         kill_child(cmdPid);
         kill_child(ihPid);
         return readStatus;
     }
 
-    // TODO: wait for command here has one trade-off: the failed status of command won't be detected until
+    // TODO: wait for command here has one trade-off: the failed status of command won't be detected
+    // until
     //       buffer timeout, but it has advatage on starting the data stream earlier.
     status_t cmdStatus = wait_child(cmdPid);
-    status_t ihStatus  = wait_child(ihPid);
+    status_t ihStatus = wait_child(ihPid);
     if (cmdStatus != NO_ERROR || ihStatus != NO_ERROR) {
-        ALOGW("CommandSection '%s' abnormal child processes, return status: command: %s, incident helper: %s",
-            this->name.string(), strerror(-cmdStatus), strerror(-ihStatus));
+        ALOGW("CommandSection '%s' abnormal child processes, return status: command: %s, incident "
+              "helper: %s",
+              this->name.string(), strerror(-cmdStatus), strerror(-ihStatus));
         return cmdStatus != NO_ERROR ? cmdStatus : ihStatus;
     }
 
-    ALOGD("CommandSection '%s' wrote %zd bytes in %d ms", this->name.string(), buffer.size(),
-            (int)buffer.durationMs());
+    VLOG("CommandSection '%s' wrote %zd bytes in %d ms", this->name.string(), buffer.size(),
+         (int)buffer.durationMs());
     status_t err = write_report_requests(this->id, buffer, requests);
     if (err != NO_ERROR) {
         ALOGW("CommandSection '%s' failed writing: %s", this->name.string(), strerror(-err));
@@ -583,9 +565,7 @@
 
 // ================================================================================
 DumpsysSection::DumpsysSection(int id, const char* service, ...)
-    :WorkerThreadSection(id),
-     mService(service)
-{
+    : WorkerThreadSection(id), mService(service) {
     name = "dumpsys ";
     name += service;
 
@@ -603,13 +583,9 @@
     va_end(args);
 }
 
-DumpsysSection::~DumpsysSection()
-{
-}
+DumpsysSection::~DumpsysSection() {}
 
-status_t
-DumpsysSection::BlockingCall(int pipeWriteFd) const
-{
+status_t DumpsysSection::BlockingCall(int pipeWriteFd) const {
     // checkService won't wait for the service to show up like getService will.
     sp<IBinder> service = defaultServiceManager()->checkService(mService);
 
@@ -633,30 +609,23 @@
 // initialization only once in Section.cpp.
 map<log_id_t, log_time> LogSection::gLastLogsRetrieved;
 
-LogSection::LogSection(int id, log_id_t logID)
-    :WorkerThreadSection(id),
-     mLogID(logID)
-{
+LogSection::LogSection(int id, log_id_t logID) : WorkerThreadSection(id), mLogID(logID) {
     name += "logcat ";
     name += android_log_id_to_name(logID);
     switch (logID) {
-    case LOG_ID_EVENTS:
-    case LOG_ID_STATS:
-    case LOG_ID_SECURITY:
-        mBinary = true;
-        break;
-    default:
-        mBinary = false;
+        case LOG_ID_EVENTS:
+        case LOG_ID_STATS:
+        case LOG_ID_SECURITY:
+            mBinary = true;
+            break;
+        default:
+            mBinary = false;
     }
 }
 
-LogSection::~LogSection()
-{
-}
+LogSection::~LogSection() {}
 
-static size_t
-trimTail(char const* buf, size_t len)
-{
+static size_t trimTail(char const* buf, size_t len) {
     while (len > 0) {
         char c = buf[len - 1];
         if (c == '\0' || c == ' ' || c == '\n' || c == '\r' || c == ':') {
@@ -672,17 +641,15 @@
     return src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24);
 }
 
-status_t
-LogSection::BlockingCall(int pipeWriteFd) const
-{
+status_t LogSection::BlockingCall(int pipeWriteFd) const {
     status_t err = NO_ERROR;
     // Open log buffer and getting logs since last retrieved time if any.
     unique_ptr<logger_list, void (*)(logger_list*)> loggers(
-        gLastLogsRetrieved.find(mLogID) == gLastLogsRetrieved.end() ?
-        android_logger_list_alloc(ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 0, 0) :
-        android_logger_list_alloc_time(ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK,
-            gLastLogsRetrieved[mLogID], 0),
-        android_logger_list_free);
+            gLastLogsRetrieved.find(mLogID) == gLastLogsRetrieved.end()
+                    ? android_logger_list_alloc(ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 0, 0)
+                    : android_logger_list_alloc_time(ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK,
+                                                     gLastLogsRetrieved[mLogID], 0),
+            android_logger_list_free);
 
     if (android_logger_open(loggers.get(), mLogID) == NULL) {
         ALOGW("LogSection %s: Can't get logger.", this->name.string());
@@ -693,7 +660,7 @@
     log_time lastTimestamp(0);
 
     ProtoOutputStream proto;
-    while (true) { // keeps reading until logd buffer is fully read.
+    while (true) {  // keeps reading until logd buffer is fully read.
         status_t err = android_logger_list_read(loggers.get(), &msg);
         // err = 0 - no content, unexpected connection drop or EOF.
         // err = +ive number - size of retrieved data from logger
@@ -708,7 +675,8 @@
         if (mBinary) {
             // remove the first uint32 which is tag's index in event log tags
             android_log_context context = create_android_log_parser(msg.msg() + sizeof(uint32_t),
-                    msg.len() - sizeof(uint32_t));;
+                                                                    msg.len() - sizeof(uint32_t));
+            ;
             android_log_list_element elem;
 
             lastTimestamp.tv_sec = msg.entry_v1.sec;
@@ -718,38 +686,46 @@
             long long token = proto.start(LogProto::BINARY_LOGS);
             proto.write(BinaryLogEntry::SEC, msg.entry_v1.sec);
             proto.write(BinaryLogEntry::NANOSEC, msg.entry_v1.nsec);
-            proto.write(BinaryLogEntry::UID, (int) msg.entry_v4.uid);
+            proto.write(BinaryLogEntry::UID, (int)msg.entry_v4.uid);
             proto.write(BinaryLogEntry::PID, msg.entry_v1.pid);
             proto.write(BinaryLogEntry::TID, msg.entry_v1.tid);
-            proto.write(BinaryLogEntry::TAG_INDEX, get4LE(reinterpret_cast<uint8_t const*>(msg.msg())));
+            proto.write(BinaryLogEntry::TAG_INDEX,
+                        get4LE(reinterpret_cast<uint8_t const*>(msg.msg())));
             do {
                 elem = android_log_read_next(context);
                 long long elemToken = proto.start(BinaryLogEntry::ELEMS);
                 switch (elem.type) {
                     case EVENT_TYPE_INT:
-                        proto.write(BinaryLogEntry::Elem::TYPE, BinaryLogEntry::Elem::EVENT_TYPE_INT);
-                        proto.write(BinaryLogEntry::Elem::VAL_INT32, (int) elem.data.int32);
+                        proto.write(BinaryLogEntry::Elem::TYPE,
+                                    BinaryLogEntry::Elem::EVENT_TYPE_INT);
+                        proto.write(BinaryLogEntry::Elem::VAL_INT32, (int)elem.data.int32);
                         break;
                     case EVENT_TYPE_LONG:
-                        proto.write(BinaryLogEntry::Elem::TYPE, BinaryLogEntry::Elem::EVENT_TYPE_LONG);
-                        proto.write(BinaryLogEntry::Elem::VAL_INT64, (long long) elem.data.int64);
+                        proto.write(BinaryLogEntry::Elem::TYPE,
+                                    BinaryLogEntry::Elem::EVENT_TYPE_LONG);
+                        proto.write(BinaryLogEntry::Elem::VAL_INT64, (long long)elem.data.int64);
                         break;
                     case EVENT_TYPE_STRING:
-                        proto.write(BinaryLogEntry::Elem::TYPE, BinaryLogEntry::Elem::EVENT_TYPE_STRING);
+                        proto.write(BinaryLogEntry::Elem::TYPE,
+                                    BinaryLogEntry::Elem::EVENT_TYPE_STRING);
                         proto.write(BinaryLogEntry::Elem::VAL_STRING, elem.data.string, elem.len);
                         break;
                     case EVENT_TYPE_FLOAT:
-                        proto.write(BinaryLogEntry::Elem::TYPE, BinaryLogEntry::Elem::EVENT_TYPE_FLOAT);
+                        proto.write(BinaryLogEntry::Elem::TYPE,
+                                    BinaryLogEntry::Elem::EVENT_TYPE_FLOAT);
                         proto.write(BinaryLogEntry::Elem::VAL_FLOAT, elem.data.float32);
                         break;
                     case EVENT_TYPE_LIST:
-                        proto.write(BinaryLogEntry::Elem::TYPE, BinaryLogEntry::Elem::EVENT_TYPE_LIST);
+                        proto.write(BinaryLogEntry::Elem::TYPE,
+                                    BinaryLogEntry::Elem::EVENT_TYPE_LIST);
                         break;
                     case EVENT_TYPE_LIST_STOP:
-                        proto.write(BinaryLogEntry::Elem::TYPE, BinaryLogEntry::Elem::EVENT_TYPE_LIST_STOP);
+                        proto.write(BinaryLogEntry::Elem::TYPE,
+                                    BinaryLogEntry::Elem::EVENT_TYPE_LIST_STOP);
                         break;
                     case EVENT_TYPE_UNKNOWN:
-                        proto.write(BinaryLogEntry::Elem::TYPE, BinaryLogEntry::Elem::EVENT_TYPE_UNKNOWN);
+                        proto.write(BinaryLogEntry::Elem::TYPE,
+                                    BinaryLogEntry::Elem::EVENT_TYPE_UNKNOWN);
                         break;
                 }
                 proto.end(elemToken);
@@ -777,7 +753,8 @@
             proto.write(TextLogEntry::PID, entry.pid);
             proto.write(TextLogEntry::TID, entry.tid);
             proto.write(TextLogEntry::TAG, entry.tag, trimTail(entry.tag, entry.tagLen));
-            proto.write(TextLogEntry::LOG, entry.message, trimTail(entry.message, entry.messageLen));
+            proto.write(TextLogEntry::LOG, entry.message,
+                        trimTail(entry.message, entry.messageLen));
             proto.end(token);
         }
     }
diff --git a/cmds/incidentd/src/Section.h b/cmds/incidentd/src/Section.h
index d440ee9..d644681 100644
--- a/cmds/incidentd/src/Section.h
+++ b/cmds/incidentd/src/Section.h
@@ -13,31 +13,31 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+#pragma once
 
 #ifndef SECTIONS_H
 #define SECTIONS_H
 
 #include "Reporter.h"
 
-#include <map>
 #include <stdarg.h>
+#include <map>
 
-#include <utils/String8.h>
 #include <utils/String16.h>
+#include <utils/String8.h>
 #include <utils/Vector.h>
 
 using namespace android;
 
-const int64_t REMOTE_CALL_TIMEOUT_MS = 10 * 1000; // 10 seconds
+const int64_t REMOTE_CALL_TIMEOUT_MS = 10 * 1000;  // 10 seconds
 
 /**
  * Base class for sections
  */
-class Section
-{
+class Section {
 public:
     const int id;
-    const int64_t timeoutMs; // each section must have a timeout
+    const int64_t timeoutMs;  // each section must have a timeout
     String8 name;
 
     Section(int id, const int64_t timeoutMs = REMOTE_CALL_TIMEOUT_MS);
@@ -49,8 +49,7 @@
 /**
  * Section that generates incident headers.
  */
-class HeaderSection : public Section
-{
+class HeaderSection : public Section {
 public:
     HeaderSection();
     virtual ~HeaderSection();
@@ -59,10 +58,20 @@
 };
 
 /**
+ * Section that generates incident metadata.
+ */
+class MetadataSection : public Section {
+public:
+    MetadataSection();
+    virtual ~MetadataSection();
+
+    virtual status_t Execute(ReportRequestSet* requests) const;
+};
+
+/**
  * Section that reads in a file.
  */
-class FileSection : public Section
-{
+class FileSection : public Section {
 public:
     FileSection(int id, const char* filename, const int64_t timeoutMs = 5000 /* 5 seconds */);
     virtual ~FileSection();
@@ -71,14 +80,13 @@
 
 private:
     const char* mFilename;
-    bool mIsSysfs; // sysfs files are pollable but return POLLERR by default, handle it separately
+    bool mIsSysfs;  // sysfs files are pollable but return POLLERR by default, handle it separately
 };
 
 /**
  * Base class for sections that call a command that might need a timeout.
  */
-class WorkerThreadSection : public Section
-{
+class WorkerThreadSection : public Section {
 public:
     WorkerThreadSection(int id);
     virtual ~WorkerThreadSection();
@@ -91,8 +99,7 @@
 /**
  * Section that forks and execs a command, and puts stdout as the section.
  */
-class CommandSection : public Section
-{
+class CommandSection : public Section {
 public:
     CommandSection(int id, const int64_t timeoutMs, const char* command, ...);
 
@@ -111,8 +118,7 @@
 /**
  * Section that calls dumpsys on a system service.
  */
-class DumpsysSection : public WorkerThreadSection
-{
+class DumpsysSection : public WorkerThreadSection {
 public:
     DumpsysSection(int id, const char* service, ...);
     virtual ~DumpsysSection();
@@ -127,8 +133,7 @@
 /**
  * Section that reads from logd.
  */
-class LogSection : public WorkerThreadSection
-{
+class LogSection : public WorkerThreadSection {
     // global last log retrieved timestamp for each log_id_t.
     static map<log_id_t, log_time> gLastLogsRetrieved;
 
@@ -143,5 +148,4 @@
     bool mBinary;
 };
 
-#endif // SECTIONS_H
-
+#endif  // SECTIONS_H
diff --git a/cmds/incidentd/src/incidentd_util.cpp b/cmds/incidentd/src/incidentd_util.cpp
new file mode 100644
index 0000000..2415860
--- /dev/null
+++ b/cmds/incidentd/src/incidentd_util.cpp
@@ -0,0 +1,53 @@
+/*
+ * 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 "incidentd_util.h"
+
+#include "section_list.h"
+
+const Privacy* get_privacy_of_section(int id) {
+    int l = 0;
+    int r = PRIVACY_POLICY_COUNT - 1;
+    while (l <= r) {
+        int mid = (l + r) >> 1;
+        const Privacy* p = PRIVACY_POLICY_LIST[mid];
+
+        if (p->field_id < (uint32_t)id) {
+            l = mid + 1;
+        } else if (p->field_id > (uint32_t)id) {
+            r = mid - 1;
+        } else {
+            return p;
+        }
+    }
+    return NULL;
+}
+
+// ================================================================================
+Fpipe::Fpipe() : mRead(), mWrite() {}
+
+Fpipe::~Fpipe() { close(); }
+
+bool Fpipe::close() {
+    mRead.reset();
+    mWrite.reset();
+    return true;
+}
+
+bool Fpipe::init() { return Pipe(&mRead, &mWrite); }
+
+int Fpipe::readFd() const { return mRead.get(); }
+
+int Fpipe::writeFd() const { return mWrite.get(); }
\ No newline at end of file
diff --git a/cmds/incidentd/src/io_util.h b/cmds/incidentd/src/incidentd_util.h
similarity index 74%
rename from cmds/incidentd/src/io_util.h
rename to cmds/incidentd/src/incidentd_util.h
index 320dd6c..09aa040 100644
--- a/cmds/incidentd/src/io_util.h
+++ b/cmds/incidentd/src/incidentd_util.h
@@ -13,16 +13,18 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+#pragma once
 
-#ifndef IO_UTIL_H
-#define IO_UTIL_H
+#ifndef INCIDENTD_UTIL_H
+#define INCIDENTD_UTIL_H
 
-#include <stdint.h>
-#include <utils/Errors.h>
+#include <android-base/unique_fd.h>
 
-using namespace android;
+#include "Privacy.h"
 
-status_t write_all(int fd, uint8_t const* buf, size_t size);
+using namespace android::base;
+
+const Privacy* get_privacy_of_section(int id);
 
 class Fpipe {
 public:
@@ -35,7 +37,8 @@
     int writeFd() const;
 
 private:
-    int mFds[2];
+    unique_fd mRead;
+    unique_fd mWrite;
 };
 
-#endif // IO_UTIL_H
\ No newline at end of file
+#endif  // INCIDENTD_UTIL_H
\ No newline at end of file
diff --git a/cmds/incidentd/src/io_util.cpp b/cmds/incidentd/src/io_util.cpp
deleted file mode 100644
index 90f543e..0000000
--- a/cmds/incidentd/src/io_util.cpp
+++ /dev/null
@@ -1,46 +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.
- */
-
-#define LOG_TAG "incidentd"
-
-#include "io_util.h"
-
-#include <unistd.h>
-
-status_t write_all(int fd, uint8_t const* buf, size_t size)
-{
-    while (size > 0) {
-        ssize_t amt = TEMP_FAILURE_RETRY(::write(fd, buf, size));
-        if (amt < 0) {
-            return -errno;
-        }
-        size -= amt;
-        buf += amt;
-    }
-    return NO_ERROR;
-}
-
-Fpipe::Fpipe() {}
-
-Fpipe::~Fpipe() { close(); }
-
-bool Fpipe::close() { return !(::close(mFds[0]) || ::close(mFds[1])); }
-
-bool Fpipe::init() { return pipe(mFds) != -1; }
-
-int Fpipe::readFd() const { return mFds[0]; }
-
-int Fpipe::writeFd() const { return mFds[1]; }
diff --git a/cmds/incidentd/src/main.cpp b/cmds/incidentd/src/main.cpp
index 3a7511d..38b7449 100644
--- a/cmds/incidentd/src/main.cpp
+++ b/cmds/incidentd/src/main.cpp
@@ -13,8 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
-#define LOG_TAG "incidentd"
+#include "Log.h"
 
 #include "IncidentService.h"
 
@@ -23,25 +22,22 @@
 #include <binder/IServiceManager.h>
 #include <binder/ProcessState.h>
 #include <binder/Status.h>
-#include <cutils/log.h>
 #include <utils/Looper.h>
 #include <utils/StrongPointer.h>
 
-#include <sys/types.h>
 #include <sys/stat.h>
+#include <sys/types.h>
 
 using namespace android;
 
 // ================================================================================
-int
-main(int /*argc*/, char** /*argv*/)
-{
+int main(int /*argc*/, char** /*argv*/) {
     // Set up the looper
     sp<Looper> looper(Looper::prepare(0 /* opts */));
 
     // Set up the binder
     sp<ProcessState> ps(ProcessState::self());
-    ps->setThreadPoolMaxThreadCount(1); // everything is oneway, let it queue and save ram
+    ps->setThreadPoolMaxThreadCount(1);  // everything is oneway, let it queue and save ram
     ps->startThreadPool();
     ps->giveThreadPoolName();
     IPCThreadState::self()->disableBackgroundScheduling(true);
diff --git a/cmds/incidentd/src/report_directory.cpp b/cmds/incidentd/src/report_directory.cpp
index 20111d8..b71c066 100644
--- a/cmds/incidentd/src/report_directory.cpp
+++ b/cmds/incidentd/src/report_directory.cpp
@@ -13,19 +13,17 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
-#define LOG_TAG "incidentd"
+#include "Log.h"
 
 #include "report_directory.h"
 
-#include <cutils/log.h>
 #include <private/android_filesystem_config.h>
 #include <utils/String8.h>
 
-#include <sys/types.h>
-#include <sys/stat.h>
 #include <dirent.h>
 #include <libgen.h>
+#include <sys/stat.h>
+#include <sys/types.h>
 #include <unistd.h>
 
 #include <vector>
@@ -33,9 +31,7 @@
 using namespace android;
 using namespace std;
 
-status_t
-create_directory(const char* directory)
-{
+status_t create_directory(const char* directory) {
     struct stat st;
     status_t err = NO_ERROR;
     char* dir = strdup(directory);
@@ -75,14 +71,14 @@
         goto done;
     }
     if ((st.st_mode & 0777) != 0770) {
-        ALOGE("No incident reports today. Mode is %0o on report directory %s",
-                st.st_mode, directory);
+        ALOGE("No incident reports today. Mode is %0o on report directory %s", st.st_mode,
+              directory);
         err = BAD_VALUE;
         goto done;
     }
     if (st.st_uid != AID_INCIDENTD || st.st_gid != AID_INCIDENTD) {
         ALOGE("No incident reports today. Owner is %d and group is %d on report directory %s",
-                st.st_uid, st.st_gid, directory);
+              st.st_uid, st.st_gid, directory);
         err = BAD_VALUE;
         goto done;
     }
@@ -92,20 +88,17 @@
     return err;
 }
 
-static bool
-stat_mtime_cmp(const pair<String8,struct stat>& a, const pair<String8,struct stat>& b)
-{
+static bool stat_mtime_cmp(const pair<String8, struct stat>& a,
+                           const pair<String8, struct stat>& b) {
     return a.second.st_mtime < b.second.st_mtime;
 }
 
-void
-clean_directory(const char* directory, off_t maxSize, size_t maxCount)
-{
+void clean_directory(const char* directory, off_t maxSize, size_t maxCount) {
     DIR* dir;
     struct dirent* entry;
     struct stat st;
 
-    vector<pair<String8,struct stat>> files;
+    vector<pair<String8, struct stat>> files;
 
     if ((dir = opendir(directory)) == NULL) {
         ALOGE("Couldn't open incident directory: %s", directory);
@@ -131,7 +124,7 @@
         if (!S_ISREG(st.st_mode)) {
             continue;
         }
-        files.push_back(pair<String8,struct stat>(filename, st));
+        files.push_back(pair<String8, struct stat>(filename, st));
 
         totalSize += st.st_size;
         totalCount++;
@@ -148,8 +141,8 @@
     sort(files.begin(), files.end(), stat_mtime_cmp);
 
     // Remove files until we're under our limits.
-    for (vector<pair<String8,struct stat>>::iterator it = files.begin();
-            it != files.end() && totalSize >= maxSize && totalCount >= maxCount; it++) {
+    for (vector<pair<String8, struct stat>>::iterator it = files.begin();
+         it != files.end() && totalSize >= maxSize && totalCount >= maxCount; it++) {
         remove(it->first.string());
         totalSize -= it->second.st_size;
         totalCount--;
diff --git a/cmds/incidentd/src/report_directory.h b/cmds/incidentd/src/report_directory.h
index bed4f86..2a3cf4c 100644
--- a/cmds/incidentd/src/report_directory.h
+++ b/cmds/incidentd/src/report_directory.h
@@ -13,17 +13,15 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+#pragma once
 
 #ifndef DIRECTORY_CLEANER_H
 #define DIRECTORY_CLEANER_H
 
+#include <sys/types.h>
 #include <utils/Errors.h>
 
-#include <sys/types.h>
-
-using namespace android;
-
-status_t create_directory(const char* directory);
+android::status_t create_directory(const char* directory);
 void clean_directory(const char* directory, off_t maxSize, size_t maxCount);
 
-#endif // DIRECTORY_CLEANER_H
+#endif  // DIRECTORY_CLEANER_H
diff --git a/cmds/incidentd/src/section_list.h b/cmds/incidentd/src/section_list.h
index ddc0505..697e66f 100644
--- a/cmds/incidentd/src/section_list.h
+++ b/cmds/incidentd/src/section_list.h
@@ -13,11 +13,12 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+#pragma once
 
 #ifndef SECTION_LIST_H
 #define SECTION_LIST_H
 
-#include <log/log_event_list.h> // include log_id_t enums.
+#include <log/log_event_list.h>  // include log_id_t enums.
 
 #include "Privacy.h"
 #include "Section.h"
@@ -36,5 +37,4 @@
 
 extern const int PRIVACY_POLICY_COUNT;
 
-#endif // SECTION_LIST_H
-
+#endif  // SECTION_LIST_H
diff --git a/cmds/incidentd/tests/FdBuffer_test.cpp b/cmds/incidentd/tests/FdBuffer_test.cpp
index 3fd2ed8..956c8d3 100644
--- a/cmds/incidentd/tests/FdBuffer_test.cpp
+++ b/cmds/incidentd/tests/FdBuffer_test.cpp
@@ -11,11 +11,10 @@
 // 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 "incidentd"
+#include "Log.h"
 
 #include "FdBuffer.h"
-#include "io_util.h"
+#include "incidentd_util.h"
 
 #include <android-base/file.h>
 #include <android-base/test_utils.h>
@@ -48,7 +47,7 @@
     }
 
     void AssertBufferContent(const char* expected) {
-        int i=0;
+        int i = 0;
         EncodedBuffer::iterator it = buffer.data();
         while (it.hasNext()) {
             ASSERT_EQ(it.next(), expected[i++]);
@@ -100,7 +99,7 @@
     ASSERT_TRUE(WriteStringToFile(testdata, tf.path));
     ASSERT_EQ(NO_ERROR, buffer.read(tf.fd, READ_TIMEOUT));
 
-    int i=0;
+    int i = 0;
     EncodedBuffer::iterator it = buffer.data();
     while (it.hasNext()) {
         EXPECT_EQ(it.next(), (uint8_t)testdata[i++]);
@@ -118,7 +117,7 @@
 
     if (pid == 0) {
         close(c2pPipe.readFd());
-        while(true) {
+        while (true) {
             write(c2pPipe.writeFd(), "poo", 3);
             sleep(1);
         }
@@ -130,7 +129,7 @@
         ASSERT_EQ(NO_ERROR, status);
         EXPECT_TRUE(buffer.timedOut());
 
-        kill(pid, SIGKILL); // reap the child process
+        kill(pid, SIGKILL);  // reap the child process
     }
 }
 
@@ -155,8 +154,8 @@
         close(p2cPipe.readFd());
         close(c2pPipe.writeFd());
 
-        ASSERT_EQ(NO_ERROR, buffer.readProcessedDataInStream(tf.fd,
-            p2cPipe.writeFd(), c2pPipe.readFd(), READ_TIMEOUT));
+        ASSERT_EQ(NO_ERROR, buffer.readProcessedDataInStream(tf.fd, p2cPipe.writeFd(),
+                                                             c2pPipe.readFd(), READ_TIMEOUT));
         AssertBufferReadSuccessful(HEAD.size() + testdata.size());
         AssertBufferContent(expected.c_str());
         wait(&pid);
@@ -187,8 +186,8 @@
         close(p2cPipe.readFd());
         close(c2pPipe.writeFd());
 
-        ASSERT_EQ(NO_ERROR, buffer.readProcessedDataInStream(tf.fd,
-            p2cPipe.writeFd(), c2pPipe.readFd(), READ_TIMEOUT));
+        ASSERT_EQ(NO_ERROR, buffer.readProcessedDataInStream(tf.fd, p2cPipe.writeFd(),
+                                                             c2pPipe.readFd(), READ_TIMEOUT));
         AssertBufferReadSuccessful(HEAD.size() + testdata.size());
         AssertBufferContent(expected.c_str());
         wait(&pid);
@@ -212,8 +211,8 @@
         close(p2cPipe.readFd());
         close(c2pPipe.writeFd());
 
-        ASSERT_EQ(NO_ERROR, buffer.readProcessedDataInStream(tf.fd,
-            p2cPipe.writeFd(), c2pPipe.readFd(), READ_TIMEOUT));
+        ASSERT_EQ(NO_ERROR, buffer.readProcessedDataInStream(tf.fd, p2cPipe.writeFd(),
+                                                             c2pPipe.readFd(), READ_TIMEOUT));
         AssertBufferReadSuccessful(0);
         AssertBufferContent("");
         wait(&pid);
@@ -222,7 +221,7 @@
 
 TEST_F(FdBufferTest, ReadInStreamMoreThan4MB) {
     const std::string testFile = kTestDataPath + "morethan4MB.txt";
-    size_t fourMB = (size_t) 4 * 1024 * 1024;
+    size_t fourMB = (size_t)4 * 1024 * 1024;
     int fd = open(testFile.c_str(), O_RDONLY | O_CLOEXEC);
     ASSERT_NE(fd, -1);
     int pid = fork();
@@ -239,8 +238,8 @@
         close(p2cPipe.readFd());
         close(c2pPipe.writeFd());
 
-        ASSERT_EQ(NO_ERROR, buffer.readProcessedDataInStream(fd,
-            p2cPipe.writeFd(), c2pPipe.readFd(), READ_TIMEOUT));
+        ASSERT_EQ(NO_ERROR, buffer.readProcessedDataInStream(fd, p2cPipe.writeFd(),
+                                                             c2pPipe.readFd(), READ_TIMEOUT));
         EXPECT_EQ(buffer.size(), fourMB);
         EXPECT_FALSE(buffer.timedOut());
         EXPECT_TRUE(buffer.truncated());
@@ -276,9 +275,9 @@
         close(p2cPipe.readFd());
         close(c2pPipe.writeFd());
 
-        ASSERT_EQ(NO_ERROR, buffer.readProcessedDataInStream(tf.fd,
-            p2cPipe.writeFd(), c2pPipe.readFd(), QUICK_TIMEOUT_MS));
+        ASSERT_EQ(NO_ERROR, buffer.readProcessedDataInStream(tf.fd, p2cPipe.writeFd(),
+                                                             c2pPipe.readFd(), QUICK_TIMEOUT_MS));
         EXPECT_TRUE(buffer.timedOut());
-        kill(pid, SIGKILL); // reap the child process
+        kill(pid, SIGKILL);  // reap the child process
     }
 }
diff --git a/cmds/incidentd/tests/PrivacyBuffer_test.cpp b/cmds/incidentd/tests/PrivacyBuffer_test.cpp
index c7bfe55..7ea9bbf 100644
--- a/cmds/incidentd/tests/PrivacyBuffer_test.cpp
+++ b/cmds/incidentd/tests/PrivacyBuffer_test.cpp
@@ -11,8 +11,7 @@
 // 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 "incidentd"
+#include "Log.h"
 
 #include "FdBuffer.h"
 #include "PrivacyBuffer.h"
@@ -37,13 +36,12 @@
 const uint8_t STRING_TYPE = 9;
 const uint8_t MESSAGE_TYPE = 11;
 const string STRING_FIELD_0 = "\x02\viamtestdata";
-const string VARINT_FIELD_1 = "\x08\x96\x01"; // 150
+const string VARINT_FIELD_1 = "\x08\x96\x01";  // 150
 const string STRING_FIELD_2 = "\x12\vwhatthefuck";
-const string FIX64_FIELD_3 = "\x19\xff\xff\xff\xff\xff\xff\xff\xff"; // -1
-const string FIX32_FIELD_4 = "\x25\xff\xff\xff\xff"; // -1
+const string FIX64_FIELD_3 = "\x19\xff\xff\xff\xff\xff\xff\xff\xff";  // -1
+const string FIX32_FIELD_4 = "\x25\xff\xff\xff\xff";                  // -1
 const string MESSAGE_FIELD_5 = "\x2a\x10" + VARINT_FIELD_1 + STRING_FIELD_2;
 
-
 class PrivacyBufferTest : public Test {
 public:
     virtual ~PrivacyBufferTest() {
@@ -55,9 +53,7 @@
         }
     }
 
-    virtual void SetUp() override {
-        ASSERT_NE(tf.fd, -1);
-    }
+    virtual void SetUp() override { ASSERT_NE(tf.fd, -1); }
 
     void writeToFdBuffer(string str) {
         ASSERT_TRUE(WriteStringToFile(str, tf.path));
@@ -81,11 +77,11 @@
     }
 
     void assertStripByFields(uint8_t dest, string expected, int size, Privacy* privacy, ...) {
-        Privacy* list[size+1];
+        Privacy* list[size + 1];
         list[0] = privacy;
         va_list args;
         va_start(args, privacy);
-        for (int i=1; i<size; i++) {
+        for (int i = 1; i < size; i++) {
             Privacy* p = va_arg(args, Privacy*);
             list[i] = p;
         }
@@ -115,13 +111,14 @@
     }
 
     FdBuffer buffer;
+
 private:
     TemporaryFile tf;
     // Littering this code with unique_ptr (or similar) is ugly, so we just
     // mass-free everything after the test completes.
-    std::vector<Privacy *> privacies;
+    std::vector<Privacy*> privacies;
 
-    Privacy *new_uninit_privacy() {
+    Privacy* new_uninit_privacy() {
         Privacy* p = new Privacy;
         privacies.push_back(p);
         return p;
@@ -165,63 +162,69 @@
 
 TEST_F(PrivacyBufferTest, NoStripVarintField) {
     writeToFdBuffer(VARINT_FIELD_1);
-    assertStripByFields(DEST_EXPLICIT, VARINT_FIELD_1, 1, create_privacy(1, OTHER_TYPE, DEST_AUTOMATIC));
+    assertStripByFields(DEST_EXPLICIT, VARINT_FIELD_1, 1,
+                        create_privacy(1, OTHER_TYPE, DEST_AUTOMATIC));
 }
 
 TEST_F(PrivacyBufferTest, NoStripLengthDelimitedField_String) {
     writeToFdBuffer(STRING_FIELD_2);
-    assertStripByFields(DEST_EXPLICIT, STRING_FIELD_2, 1, create_privacy(2, STRING_TYPE, DEST_AUTOMATIC));
+    assertStripByFields(DEST_EXPLICIT, STRING_FIELD_2, 1,
+                        create_privacy(2, STRING_TYPE, DEST_AUTOMATIC));
 }
 
 TEST_F(PrivacyBufferTest, NoStripFixed64Field) {
     writeToFdBuffer(FIX64_FIELD_3);
-    assertStripByFields(DEST_EXPLICIT, FIX64_FIELD_3, 1, create_privacy(3, OTHER_TYPE, DEST_AUTOMATIC));
+    assertStripByFields(DEST_EXPLICIT, FIX64_FIELD_3, 1,
+                        create_privacy(3, OTHER_TYPE, DEST_AUTOMATIC));
 }
 
 TEST_F(PrivacyBufferTest, NoStripFixed32Field) {
     writeToFdBuffer(FIX32_FIELD_4);
-    assertStripByFields(DEST_EXPLICIT, FIX32_FIELD_4, 1, create_privacy(4, OTHER_TYPE, DEST_AUTOMATIC));
+    assertStripByFields(DEST_EXPLICIT, FIX32_FIELD_4, 1,
+                        create_privacy(4, OTHER_TYPE, DEST_AUTOMATIC));
 }
 
 TEST_F(PrivacyBufferTest, NoStripLengthDelimitedField_Message) {
     writeToFdBuffer(MESSAGE_FIELD_5);
-    assertStripByFields(DEST_EXPLICIT, MESSAGE_FIELD_5, 1, create_privacy(5, MESSAGE_TYPE, DEST_AUTOMATIC));
+    assertStripByFields(DEST_EXPLICIT, MESSAGE_FIELD_5, 1,
+                        create_privacy(5, MESSAGE_TYPE, DEST_AUTOMATIC));
 }
 
 TEST_F(PrivacyBufferTest, StripVarintAndString) {
-    writeToFdBuffer(STRING_FIELD_0 + VARINT_FIELD_1 + STRING_FIELD_2
-            + FIX64_FIELD_3 + FIX32_FIELD_4);
+    writeToFdBuffer(STRING_FIELD_0 + VARINT_FIELD_1 + STRING_FIELD_2 + FIX64_FIELD_3 +
+                    FIX32_FIELD_4);
     string expected = STRING_FIELD_0 + FIX64_FIELD_3 + FIX32_FIELD_4;
-    assertStripByFields(DEST_EXPLICIT, expected, 2,
-            create_privacy(1, OTHER_TYPE, DEST_LOCAL), create_privacy(2, STRING_TYPE, DEST_LOCAL));
+    assertStripByFields(DEST_EXPLICIT, expected, 2, create_privacy(1, OTHER_TYPE, DEST_LOCAL),
+                        create_privacy(2, STRING_TYPE, DEST_LOCAL));
 }
 
 TEST_F(PrivacyBufferTest, StripVarintAndFixed64) {
-    writeToFdBuffer(STRING_FIELD_0 + VARINT_FIELD_1 + STRING_FIELD_2
-            + FIX64_FIELD_3 + FIX32_FIELD_4);
+    writeToFdBuffer(STRING_FIELD_0 + VARINT_FIELD_1 + STRING_FIELD_2 + FIX64_FIELD_3 +
+                    FIX32_FIELD_4);
     string expected = STRING_FIELD_0 + STRING_FIELD_2 + FIX32_FIELD_4;
-    assertStripByFields(DEST_EXPLICIT, expected, 2,
-            create_privacy(1, OTHER_TYPE, DEST_LOCAL), create_privacy(3, OTHER_TYPE, DEST_LOCAL));
+    assertStripByFields(DEST_EXPLICIT, expected, 2, create_privacy(1, OTHER_TYPE, DEST_LOCAL),
+                        create_privacy(3, OTHER_TYPE, DEST_LOCAL));
 }
 
 TEST_F(PrivacyBufferTest, StripVarintInNestedMessage) {
     writeToFdBuffer(STRING_FIELD_0 + MESSAGE_FIELD_5);
-    Privacy* list[] = { create_privacy(1, OTHER_TYPE, DEST_LOCAL), NULL };
+    Privacy* list[] = {create_privacy(1, OTHER_TYPE, DEST_LOCAL), NULL};
     string expected = STRING_FIELD_0 + "\x2a\xd" + STRING_FIELD_2;
     assertStripByFields(DEST_EXPLICIT, expected, 1, create_message_privacy(5, list));
 }
 
 TEST_F(PrivacyBufferTest, StripFix64AndVarintInNestedMessage) {
     writeToFdBuffer(STRING_FIELD_0 + FIX64_FIELD_3 + MESSAGE_FIELD_5);
-    Privacy* list[] = { create_privacy(1, OTHER_TYPE, DEST_LOCAL), NULL };
+    Privacy* list[] = {create_privacy(1, OTHER_TYPE, DEST_LOCAL), NULL};
     string expected = STRING_FIELD_0 + "\x2a\xd" + STRING_FIELD_2;
-    assertStripByFields(DEST_EXPLICIT, expected, 2, create_privacy(3, OTHER_TYPE, DEST_LOCAL), create_message_privacy(5, list));
+    assertStripByFields(DEST_EXPLICIT, expected, 2, create_privacy(3, OTHER_TYPE, DEST_LOCAL),
+                        create_message_privacy(5, list));
 }
 
 TEST_F(PrivacyBufferTest, ClearAndStrip) {
     string data = STRING_FIELD_0 + VARINT_FIELD_1;
     writeToFdBuffer(data);
-    Privacy* list[] = { create_privacy(1, OTHER_TYPE, DEST_LOCAL), NULL };
+    Privacy* list[] = {create_privacy(1, OTHER_TYPE, DEST_LOCAL), NULL};
     EncodedBuffer::iterator bufData = buffer.data();
     PrivacyBuffer privacyBuf(create_message_privacy(300, list), bufData);
     PrivacySpec spec1 = PrivacySpec::new_spec(DEST_EXPLICIT);
@@ -235,7 +238,7 @@
 
 TEST_F(PrivacyBufferTest, BadDataInFdBuffer) {
     writeToFdBuffer("iambaddata");
-    Privacy* list[] = { create_privacy(4, OTHER_TYPE, DEST_AUTOMATIC), NULL };
+    Privacy* list[] = {create_privacy(4, OTHER_TYPE, DEST_AUTOMATIC), NULL};
     EncodedBuffer::iterator bufData = buffer.data();
     PrivacyBuffer privacyBuf(create_message_privacy(300, list), bufData);
     PrivacySpec spec;
@@ -244,8 +247,8 @@
 
 TEST_F(PrivacyBufferTest, BadDataInNestedMessage) {
     writeToFdBuffer(STRING_FIELD_0 + MESSAGE_FIELD_5 + "aoeoe");
-    Privacy* list[] = { create_privacy(1, OTHER_TYPE, DEST_LOCAL), NULL };
-    Privacy* field5[] = { create_message_privacy(5, list), NULL };
+    Privacy* list[] = {create_privacy(1, OTHER_TYPE, DEST_LOCAL), NULL};
+    Privacy* field5[] = {create_message_privacy(5, list), NULL};
     EncodedBuffer::iterator bufData = buffer.data();
     PrivacyBuffer privacyBuf(create_message_privacy(300, field5), bufData);
     PrivacySpec spec;
@@ -256,7 +259,7 @@
     string input = "\x2a\"" + VARINT_FIELD_1 + STRING_FIELD_2 + MESSAGE_FIELD_5;
     writeToFdBuffer(input);
     Privacy* field5 = create_message_privacy(5, NULL);
-    Privacy* list[] = { create_privacy(1, OTHER_TYPE, DEST_LOCAL), field5, NULL };
+    Privacy* list[] = {create_privacy(1, OTHER_TYPE, DEST_LOCAL), field5, NULL};
     field5->children = list;
     string expected = "\x2a\x1c" + STRING_FIELD_2 + "\x2a\xd" + STRING_FIELD_2;
     assertStrip(DEST_EXPLICIT, expected, field5);
@@ -264,7 +267,7 @@
 
 TEST_F(PrivacyBufferTest, AutoMessage) {
     writeToFdBuffer(STRING_FIELD_2 + MESSAGE_FIELD_5);
-    Privacy* list[] = { create_privacy(1, OTHER_TYPE, DEST_LOCAL), NULL };
+    Privacy* list[] = {create_privacy(1, OTHER_TYPE, DEST_LOCAL), NULL};
     Privacy* autoMsg = create_privacy(5, MESSAGE_TYPE, DEST_AUTOMATIC);
     autoMsg->children = list;
     string expected = "\x2a\xd" + STRING_FIELD_2;
diff --git a/cmds/incidentd/tests/Reporter_test.cpp b/cmds/incidentd/tests/Reporter_test.cpp
index c494bd6..bd359ac 100644
--- a/cmds/incidentd/tests/Reporter_test.cpp
+++ b/cmds/incidentd/tests/Reporter_test.cpp
@@ -11,8 +11,7 @@
 // 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 "incidentd"
+#include "Log.h"
 
 #include "Reporter.h"
 
@@ -26,7 +25,6 @@
 #include <gtest/gtest.h>
 #include <string.h>
 
-
 using namespace android;
 using namespace android::base;
 using namespace android::binder;
@@ -35,8 +33,7 @@
 using ::testing::StrEq;
 using ::testing::Test;
 
-class TestListener : public IIncidentReportStatusListener
-{
+class TestListener : public IIncidentReportStatusListener {
 public:
     int startInvoked;
     int finishInvoked;
@@ -44,8 +41,8 @@
     map<int, int> startSections;
     map<int, int> finishSections;
 
-    TestListener() : startInvoked(0), finishInvoked(0), failedInvoked(0) {};
-    virtual ~TestListener() {};
+    TestListener() : startInvoked(0), finishInvoked(0), failedInvoked(0){};
+    virtual ~TestListener(){};
 
     virtual Status onReportStarted() {
         startInvoked++;
@@ -53,16 +50,14 @@
     };
     virtual Status onReportSectionStatus(int section, int status) {
         switch (status) {
-        case IIncidentReportStatusListener::STATUS_STARTING:
-            if (startSections.count(section) == 0)
-                startSections[section] = 0;
-            startSections[section] = startSections[section] + 1;
-            break;
-        case IIncidentReportStatusListener::STATUS_FINISHED:
-            if (finishSections.count(section) == 0)
-                finishSections[section] = 0;
-            finishSections[section] = finishSections[section] + 1;
-            break;
+            case IIncidentReportStatusListener::STATUS_STARTING:
+                if (startSections.count(section) == 0) startSections[section] = 0;
+                startSections[section] = startSections[section] + 1;
+                break;
+            case IIncidentReportStatusListener::STATUS_FINISHED:
+                if (finishSections.count(section) == 0) finishSections[section] = 0;
+                finishSections[section] = finishSections[section] + 1;
+                break;
         }
         return Status::ok();
     };
@@ -156,7 +151,8 @@
 
     string result;
     ReadFileToString(tf.path, &result);
-    EXPECT_THAT(result, StrEq("\n\x2" "\b\f"));
+    EXPECT_THAT(result, StrEq("\n\x2"
+                              "\b\f"));
 
     EXPECT_EQ(l->startInvoked, 2);
     EXPECT_EQ(l->finishInvoked, 2);
@@ -178,5 +174,24 @@
     ASSERT_EQ(Reporter::REPORT_FINISHED, reporter->runReport());
     vector<string> results = InspectFiles();
     ASSERT_EQ((int)results.size(), 1);
-    EXPECT_EQ(results[0], "\n\x2" "\b\f\n\x6" "\x12\x4" "abcd");
+    EXPECT_EQ(results[0],
+              "\n\x2"
+              "\b\f\n\x6"
+              "\x12\x4"
+              "abcd");
 }
+
+TEST_F(ReporterTest, ReportMetadata) {
+    IncidentReportArgs args;
+    args.addSection(1);
+    args.setDest(android::os::DEST_EXPLICIT);
+    sp<ReportRequest> r = new ReportRequest(args, l, -1);
+    reporter->batch.add(r);
+
+    ASSERT_EQ(Reporter::REPORT_FINISHED, reporter->runReport());
+    auto metadata = reporter->batch.metadata();
+    EXPECT_EQ(IncidentMetadata_Destination_EXPLICIT, metadata.dest());
+    EXPECT_EQ(1, metadata.request_size());
+    EXPECT_TRUE(metadata.use_dropbox());
+    EXPECT_EQ(0, metadata.sections_size());
+}
\ No newline at end of file
diff --git a/cmds/incidentd/tests/Section_test.cpp b/cmds/incidentd/tests/Section_test.cpp
index 2cfd7df..a1f4fdc 100644
--- a/cmds/incidentd/tests/Section_test.cpp
+++ b/cmds/incidentd/tests/Section_test.cpp
@@ -11,13 +11,13 @@
 // 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 "incidentd"
+#include "Log.h"
 
 #include "Section.h"
 
 #include <android-base/file.h>
 #include <android-base/test_utils.h>
+#include <android/os/IncidentReportArgs.h>
 #include <frameworks/base/libs/incident/proto/android/os/header.pb.h>
 #include <gmock/gmock.h>
 #include <gtest/gtest.h>
@@ -29,9 +29,9 @@
 
 const int QUICK_TIMEOUT_MS = 100;
 
-const string VARINT_FIELD_1 = "\x08\x96\x01"; // 150
+const string VARINT_FIELD_1 = "\x08\x96\x01";  // 150
 const string STRING_FIELD_2 = "\x12\vwhatthefuck";
-const string FIX64_FIELD_3 = "\x19\xff\xff\xff\xff\xff\xff\xff\xff"; // -1
+const string FIX64_FIELD_3 = "\x19\xff\xff\xff\xff\xff\xff\xff\xff";  // -1
 
 using namespace android::base;
 using namespace android::binder;
@@ -43,11 +43,10 @@
 
 // NOTICE: this test requires /system/bin/incident_helper is installed.
 
-class SimpleListener : public IIncidentReportStatusListener
-{
+class SimpleListener : public IIncidentReportStatusListener {
 public:
-    SimpleListener() {};
-    virtual ~SimpleListener() {};
+    SimpleListener(){};
+    virtual ~SimpleListener(){};
 
     virtual Status onReportStarted() { return Status::ok(); };
     virtual Status onReportSectionStatus(int /*section*/, int /*status*/) { return Status::ok(); };
@@ -83,12 +82,26 @@
     string content;
     CaptureStdout();
     ASSERT_EQ(NO_ERROR, hs.Execute(&requests));
-    EXPECT_THAT(GetCapturedStdout(), StrEq("\n\x5" "\x12\x3" "axe\n\x05\x12\x03pup"));
+    EXPECT_THAT(GetCapturedStdout(), StrEq("\n\x5"
+                                           "\x12\x3"
+                                           "axe\n\x05\x12\x03pup"));
 
     EXPECT_TRUE(ReadFileToString(output2.path, &content));
     EXPECT_THAT(content, StrEq("\n\x05\x12\x03pup"));
 }
 
+TEST(SectionTest, MetadataSection) {
+    MetadataSection ms;
+    ReportRequestSet requests;
+
+    requests.setMainFd(STDOUT_FILENO);
+    requests.sectionStats(1)->set_success(true);
+
+    CaptureStdout();
+    ASSERT_EQ(NO_ERROR, ms.Execute(&requests));
+    EXPECT_THAT(GetCapturedStdout(), StrEq("\x12\b\x18\x1\"\x4\b\x1\x10\x1"));
+}
+
 TEST(SectionTest, FileSection) {
     TemporaryFile tf;
     FileSection fs(REVERSE_PARSER, tf.path);
@@ -243,8 +256,9 @@
 
     IncidentReportArgs args1, args2, args3;
     args1.setAll(true);
-    args1.setDest(0); // LOCAL
-    args2.setAll(true); // default to explicit
+    args1.setDest(android::os::DEST_LOCAL);
+    args2.setAll(true);
+    args2.setDest(android::os::DEST_EXPLICIT);
     sp<SimpleListener> l = new SimpleListener();
     requests.add(new ReportRequest(args1, l, output1.fd));
     requests.add(new ReportRequest(args2, l, output2.fd));
@@ -257,12 +271,12 @@
 
     string content, expect;
     expect = VARINT_FIELD_1 + STRING_FIELD_2 + FIX64_FIELD_3;
-    char c = (char) expect.size();
+    char c = (char)expect.size();
     EXPECT_TRUE(ReadFileToString(output1.path, &content));
     EXPECT_THAT(content, StrEq(string("\x02") + c + expect));
 
     expect = STRING_FIELD_2 + FIX64_FIELD_3;
-    c = (char) expect.size();
+    c = (char)expect.size();
     EXPECT_TRUE(ReadFileToString(output2.path, &content));
     EXPECT_THAT(content, StrEq(string("\x02") + c + expect));
 
@@ -283,10 +297,12 @@
 
     ASSERT_TRUE(WriteStringToFile(VARINT_FIELD_1 + STRING_FIELD_2 + FIX64_FIELD_3, input.path));
 
-    IncidentReportArgs args1, args2, args3, args4;
+    IncidentReportArgs args1, args2, args3;
     args1.setAll(true);
+    args1.setDest(android::os::DEST_EXPLICIT);
     args2.setAll(true);
-    args4.setAll(true);
+    args2.setDest(android::os::DEST_EXPLICIT);
+    args3.setAll(true);
     sp<SimpleListener> l = new SimpleListener();
     requests.add(new ReportRequest(args1, l, output1.fd));
     requests.add(new ReportRequest(args2, l, output2.fd));
@@ -299,7 +315,7 @@
 
     string content, expect;
     expect = STRING_FIELD_2 + FIX64_FIELD_3;
-    char c = (char) expect.size();
+    char c = (char)expect.size();
 
     // output1 and output2 are the same
     EXPECT_TRUE(ReadFileToString(output1.path, &content));
@@ -307,7 +323,8 @@
     EXPECT_TRUE(ReadFileToString(output2.path, &content));
     EXPECT_THAT(content, StrEq(string("\x02") + c + expect));
 
-    // because args3 doesn't set section, so it should receive nothing
+    // output3 has only auto field
+    c = (char)STRING_FIELD_2.size();
     EXPECT_TRUE(ReadFileToString(output3.path, &content));
-    EXPECT_THAT(content, StrEq(""));
+    EXPECT_THAT(content, StrEq(string("\x02") + c + STRING_FIELD_2));
 }
\ No newline at end of file
diff --git a/cmds/incidentd/tests/section_list.cpp b/cmds/incidentd/tests/section_list.cpp
index 1d6213f..bd2d15c 100644
--- a/cmds/incidentd/tests/section_list.cpp
+++ b/cmds/incidentd/tests/section_list.cpp
@@ -1,25 +1,17 @@
 // This file is a dummy section_list.cpp used for test only.
 #include "section_list.h"
 
-const Section* SECTION_LIST[] = {
-    NULL
-};
+const Section* SECTION_LIST[] = {NULL};
 
-Privacy sub_field_1 { 1, 1, NULL, DEST_LOCAL, NULL };
-Privacy sub_field_2 { 2, 9, NULL, DEST_AUTOMATIC, NULL };
+Privacy sub_field_1{1, 1, NULL, DEST_LOCAL, NULL};
+Privacy sub_field_2{2, 9, NULL, DEST_AUTOMATIC, NULL};
 
-Privacy* list[] = {
-    &sub_field_1,
-    &sub_field_2,
-    NULL };
+Privacy* list[] = {&sub_field_1, &sub_field_2, NULL};
 
-Privacy field_0 { 0, 11, list, DEST_EXPLICIT, NULL };
-Privacy field_1 { 1, 9, NULL, DEST_AUTOMATIC, NULL };
+Privacy field_0{0, 11, list, DEST_EXPLICIT, NULL};
+Privacy field_1{1, 9, NULL, DEST_AUTOMATIC, NULL};
 
-Privacy* final_list[] = {
-    &field_0,
-    &field_1
-};
+Privacy* final_list[] = {&field_0, &field_1};
 
 const Privacy** PRIVACY_POLICY_LIST = const_cast<const Privacy**>(final_list);
 
diff --git a/cmds/statsd/Android.mk b/cmds/statsd/Android.mk
index b0019ac..740fdc0 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 \
@@ -44,6 +42,7 @@
     src/external/KernelUidCpuActiveTimeReader.cpp \
     src/external/KernelUidCpuClusterTimeReader.cpp \
     src/external/StatsPullerManagerImpl.cpp \
+    src/external/puller_util.cpp \
     src/logd/LogEvent.cpp \
     src/logd/LogListener.cpp \
     src/logd/LogReader.cpp \
@@ -65,6 +64,7 @@
     src/storage/StorageManager.cpp \
     src/StatsLogProcessor.cpp \
     src/StatsService.cpp \
+    src/subscriber/IncidentdReporter.cpp \
     src/subscriber/SubscriberReporter.cpp \
     src/HashableDimensionKey.cpp \
     src/guardrail/MemoryLeakTrackUtil.cpp \
@@ -116,10 +116,8 @@
 
 LOCAL_CFLAGS += \
     -Wall \
+    -Wextra \
     -Werror \
-    -Wno-missing-field-initializers \
-    -Wno-unused-variable \
-    -Wno-unused-function \
     -Wno-unused-parameter
 
 ifeq (debug,)
@@ -170,10 +168,10 @@
 
 LOCAL_SRC_FILES := \
     $(statsd_common_src) \
-    tests/dimension_test.cpp \
     tests/AnomalyMonitor_test.cpp \
     tests/anomaly/AnomalyTracker_test.cpp \
     tests/ConfigManager_test.cpp \
+    tests/external/puller_util_test.cpp \
     tests/indexed_priority_queue_test.cpp \
     tests/LogEntryMatcher_test.cpp \
     tests/LogReader_test.cpp \
@@ -181,6 +179,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 \
@@ -239,7 +238,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)
 
@@ -258,7 +258,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/OWNERS b/cmds/statsd/OWNERS
new file mode 100644
index 0000000..362d411
--- /dev/null
+++ b/cmds/statsd/OWNERS
@@ -0,0 +1,6 @@
+bookatz@google.com
+jinyithu@google.com
+kwekua@google.com
+stlafon@google.com
+yaochen@google.com
+yanglu@google.com
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..6894bcf
--- /dev/null
+++ b/cmds/statsd/src/FieldValue.cpp
@@ -0,0 +1,202 @@
+/*
+ * 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 {
+
+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;
+}
+
+int32_t encodeMatcherMask(int32_t mask[], int32_t depth) {
+    return getEncodedField(mask, depth, false) | 0xff000000;
+}
+
+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)));
+    } 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..d17dded
--- /dev/null
+++ b/cmds/statsd/src/FieldValue.h
@@ -0,0 +1,323 @@
+/*
+ * 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 };
+
+int32_t getEncodedField(int32_t pos[], int32_t depth, bool includeDepth);
+
+int32_t encodeMatcherMask(int32_t mask[], int32_t depth);
+
+// Get the encoded field for a leaf with a [field] number at depth 0;
+inline 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 f0eaeff..d901bd6 100644
--- a/cmds/statsd/src/HashableDimensionKey.cpp
+++ b/cmds/statsd/src/HashableDimensionKey.cpp
@@ -13,174 +13,250 @@
  * 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.
+            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) {
+            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;
+    }
 
+    return mDimensionKeyInCondition < that.getDimensionKeyInCondition();
+}
 
 }  // namespace statsd
 }  // namespace os
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 a4066aa..87dec5d 100644
--- a/cmds/statsd/src/StatsLogProcessor.cpp
+++ b/cmds/statsd/src/StatsLogProcessor.cpp
@@ -21,17 +21,17 @@
 #include <android-base/file.h>
 #include <dirent.h>
 #include "StatsLogProcessor.h"
+#include "stats_log_util.h"
 #include "android-base/stringprintf.h"
 #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"
 
 #include <log/log_event_list.h>
 #include <utils/Errors.h>
+#include <utils/SystemClock.h>
 
 using namespace android;
 using android::base::StringPrintf;
@@ -58,8 +58,10 @@
 const int FIELD_ID_UID = 1;
 const int FIELD_ID_ID = 2;
 // for ConfigMetricsReport
-const int FIELD_ID_METRICS = 1;
+// const int FIELD_ID_METRICS = 1; // written in MetricsManager.cpp
 const int FIELD_ID_UID_MAP = 2;
+const int FIELD_ID_LAST_REPORT_ELAPSED_NANOS = 3;
+const int FIELD_ID_CURRENT_REPORT_ELAPSED_NANOS = 4;
 
 #define STATS_DATA_DIR "/data/misc/stats-data"
 
@@ -71,9 +73,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);
 }
@@ -90,27 +89,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);
     }
 }
 
@@ -134,7 +137,7 @@
 void StatsLogProcessor::OnLogEvent(LogEvent* event) {
     std::lock_guard<std::mutex> lock(mMetricsMutex);
     StatsdStats::getInstance().noteAtomLogged(
-        event->GetTagId(), event->GetTimestampNs() / NS_PER_SEC);
+        event->GetTagId(), event->GetElapsedTimestampNs() / NS_PER_SEC);
 
     // Hard-coded logic to update the isolated uid's in the uid-map.
     // The field numbers need to be currently updated by hand with atoms.proto
@@ -146,6 +149,12 @@
         return;
     }
 
+    uint64_t curTimeSec = getElapsedRealtimeSec();
+    if (curTimeSec - mLastPullerCacheClearTimeSec > StatsdStats::kPullerCacheClearIntervalSec) {
+        mStatsPullerManager.ClearPullerCacheIfNecessary(curTimeSec);
+        mLastPullerCacheClearTimeSec = curTimeSec;
+    }
+
     if (event->GetTagId() != android::util::ISOLATED_UID_CHANGED) {
         // Map the isolated uid to host uid if necessary.
         mapIsolatedUidToHostUidIfNecessaryLocked(event);
@@ -154,13 +163,13 @@
     // pass the event to metrics managers.
     for (auto& pair : mMetricsManagers) {
         pair.second->onLogEvent(*event);
-        flushIfNecessaryLocked(event->GetTimestampNs(), pair.first, *(pair.second));
+        flushIfNecessaryLocked(event->GetElapsedTimestampNs(), pair.first, *(pair.second));
     }
 }
 
 void StatsLogProcessor::OnConfigUpdated(const ConfigKey& key, const StatsdConfig& config) {
     std::lock_guard<std::mutex> lock(mMetricsMutex);
-    ALOGD("Updated configuration for key %s", key.ToString().c_str());
+    VLOG("Updated configuration for key %s", key.ToString().c_str());
     sp<MetricsManager> newMetricsManager = new MetricsManager(key, config, mTimeBaseSec, mUidMap);
     auto it = mMetricsManagers.find(key);
     if (it == mMetricsManagers.end() && mMetricsManagers.size() > StatsdStats::kMaxConfigCount) {
@@ -203,27 +212,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());
@@ -247,9 +243,10 @@
     long long reportsToken =
             proto.start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_REPORTS);
 
+    int64_t lastReportTimeNs = it->second->getLastReportTimeNs();
     // 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);
@@ -258,6 +255,12 @@
     uidMap.SerializeToArray(&uidMapBuffer[0], uidMapSize);
     proto.write(FIELD_TYPE_MESSAGE | FIELD_ID_UID_MAP, uidMapBuffer, uidMapSize);
 
+    // Fill in the timestamps.
+    proto.write(FIELD_TYPE_INT64 | FIELD_ID_LAST_REPORT_ELAPSED_NANOS,
+                (long long)lastReportTimeNs);
+    proto.write(FIELD_TYPE_INT64 | FIELD_ID_CURRENT_REPORT_ELAPSED_NANOS,
+                (long long)dumpTimeStampNs);
+
     // End of ConfigMetricsReport (reports).
     proto.end(reportsToken);
 
@@ -277,6 +280,7 @@
             iter.rp()->move(toRead);
         }
     }
+
     StatsdStats::getInstance().noteMetricsReportSent(key);
 }
 
@@ -290,6 +294,10 @@
     StatsdStats::getInstance().noteConfigRemoved(key);
 
     mLastBroadcastTimes.erase(key);
+
+    if (mMetricsManagers.empty()) {
+        mStatsPullerManager.ForceClearPullerCache();
+    }
 }
 
 void StatsLogProcessor::flushIfNecessaryLocked(
@@ -308,7 +316,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) {
@@ -332,10 +340,10 @@
     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());
+        string file_name = StringPrintf("%s/%ld_%d_%lld", STATS_DATA_DIR,
+             (long)getWallClockSec(), key.GetUid(), (long long)key.GetId());
         StorageManager::writeFile(file_name.c_str(), &data[0], data.size());
     }
 }
diff --git a/cmds/statsd/src/StatsLogProcessor.h b/cmds/statsd/src/StatsLogProcessor.h
index 7642aafa..1444306 100644
--- a/cmds/statsd/src/StatsLogProcessor.h
+++ b/cmds/statsd/src/StatsLogProcessor.h
@@ -21,6 +21,7 @@
 #include "logd/LogReader.h"
 #include "metrics/MetricsManager.h"
 #include "packages/UidMap.h"
+#include "external/StatsPullerManager.h"
 
 #include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
 
@@ -45,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(
@@ -75,9 +74,12 @@
 
     sp<UidMap> mUidMap;  // Reference to the UidMap to lookup app name and version for each uid.
 
+    StatsPullerManager mStatsPullerManager;
+
     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. */
@@ -96,12 +98,20 @@
 
     const long mTimeBaseSec;
 
+    long mLastPullerCacheClearTimeSec = 0;
+
     FRIEND_TEST(StatsLogProcessorTest, TestRateLimitByteSize);
     FRIEND_TEST(StatsLogProcessorTest, TestRateLimitBroadcast);
     FRIEND_TEST(StatsLogProcessorTest, TestDropWhenByteSizeTooLarge);
     FRIEND_TEST(StatsLogProcessorTest, TestDropWhenByteSizeTooLarge);
-    FRIEND_TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensions);
-    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 32da94f..791fb14 100644
--- a/cmds/statsd/src/StatsService.cpp
+++ b/cmds/statsd/src/StatsService.cpp
@@ -14,10 +14,11 @@
  * limitations under the License.
  */
 
-#define DEBUG true  // STOPSHIP if true
+#define DEBUG false  // STOPSHIP if true
 #include "Log.h"
 
 #include "StatsService.h"
+#include "stats_log_util.h"
 #include "android-base/stringprintf.h"
 #include "config/ConfigKey.h"
 #include "config/ConfigManager.h"
@@ -77,20 +78,22 @@
     : mAnomalyMonitor(new AnomalyMonitor(MIN_DIFF_TO_UPDATE_REGISTERED_ALARM_SECS))
 {
     mUidMap = new UidMap();
+    StatsPuller::SetUidMap(mUidMap);
     mConfigManager = new ConfigManager();
-    mProcessor = new StatsLogProcessor(mUidMap, mAnomalyMonitor, time(nullptr), [this](const ConfigKey& key) {
-        sp<IStatsCompanionService> sc = getStatsCompanionService();
-        auto receiver = mConfigManager->GetConfigReceiver(key);
-        if (sc == nullptr) {
-            VLOG("Could not find StatsCompanionService");
-        } else if (receiver.first.size() == 0) {
-            VLOG("Statscompanion could not find a broadcast receiver for %s",
-                 key.ToString().c_str());
-        } else {
-            sc->sendBroadcast(String16(receiver.first.c_str()),
-                              String16(receiver.second.c_str()));
+    mProcessor = new StatsLogProcessor(mUidMap, mAnomalyMonitor, getElapsedRealtimeSec(),
+        [this](const ConfigKey& key) {
+            sp<IStatsCompanionService> sc = getStatsCompanionService();
+            auto receiver = mConfigManager->GetConfigReceiver(key);
+            if (sc == nullptr) {
+                VLOG("Could not find StatsCompanionService");
+            } else if (receiver == nullptr) {
+                VLOG("Statscompanion could not find a broadcast receiver for %s",
+                     key.ToString().c_str());
+            } else {
+                sc->sendDataBroadcast(receiver);
+            }
         }
-    });
+    );
 
     mConfigManager->AddListener(mProcessor);
 
@@ -121,8 +124,6 @@
  */
 status_t StatsService::onTransact(uint32_t code, const Parcel& data, Parcel* reply,
                                   uint32_t flags) {
-    status_t err;
-
     switch (code) {
         case SHELL_COMMAND_TRANSACTION: {
             int in = data.readFileDescriptor();
@@ -237,8 +238,12 @@
             return cmd_write_data_to_disk(out);
         }
 
-        if (!args[0].compare(String8("log-app-hook"))) {
-            return cmd_log_app_hook(out, args);
+        if (!args[0].compare(String8("log-app-breadcrumb"))) {
+            return cmd_log_app_breadcrumb(out, args);
+        }
+
+        if (!args[0].compare(String8("clear-puller-cache"))) {
+            return cmd_clear_puller_cache(out);
         }
     }
 
@@ -277,8 +282,8 @@
     fprintf(out, "  Flushes all data on memory to disk.\n");
     fprintf(out, "\n");
     fprintf(out, "\n");
-    fprintf(out, "usage: adb shell cmd stats log-app-hook [UID] LABEL STATE\n");
-    fprintf(out, "  Writes an AppHook event to the statslog buffer.\n");
+    fprintf(out, "usage: adb shell cmd stats log-app-breadcrumb [UID] LABEL STATE\n");
+    fprintf(out, "  Writes an AppBreadcrumbReported event to the statslog buffer.\n");
     fprintf(out, "  UID           The uid to use. It is only possible to pass a UID\n");
     fprintf(out, "                parameter on eng builds. If UID is omitted the calling\n");
     fprintf(out, "                uid is used.\n");
@@ -320,6 +325,10 @@
     fprintf(out, "\n");
     fprintf(out, "usage: adb shell cmd stats print-stats\n");
     fprintf(out, "  Prints some basic stats.\n");
+    fprintf(out, "\n");
+    fprintf(out, "\n");
+    fprintf(out, "usage: adb shell cmd stats clear-puller-cache\n");
+    fprintf(out, "  Clear cached puller data.\n");
 }
 
 status_t StatsService::cmd_trigger_broadcast(FILE* out, Vector<String8>& args) {
@@ -358,12 +367,14 @@
     }
     auto receiver = mConfigManager->GetConfigReceiver(ConfigKey(uid, StrToInt64(name)));
     sp<IStatsCompanionService> sc = getStatsCompanionService();
-    if (sc != nullptr) {
-        sc->sendBroadcast(String16(receiver.first.c_str()), String16(receiver.second.c_str()));
+    if (sc == nullptr) {
+        VLOG("Could not access statsCompanion");
+    } else if (receiver == nullptr) {
+        VLOG("Could not find receiver for %s, %s", args[1].c_str(), args[2].c_str())
+    } else {
+        sc->sendDataBroadcast(receiver);
         VLOG("StatsService::trigger broadcast succeeded to %s, %s", args[1].c_str(),
              args[2].c_str());
-    } else {
-        VLOG("Could not access statsCompanion");
     }
 
     return NO_ERROR;
@@ -482,7 +493,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 ++) {
@@ -537,7 +549,7 @@
     return NO_ERROR;
 }
 
-status_t StatsService::cmd_log_app_hook(FILE* out, const Vector<String8>& args) {
+status_t StatsService::cmd_log_app_breadcrumb(FILE* out, const Vector<String8>& args) {
     bool good = false;
     int32_t uid;
     int32_t label;
@@ -559,13 +571,13 @@
             good = true;
         } else {
             fprintf(out,
-                    "Selecting a UID for writing AppHook can only be dumped for other UIDs on eng"
-                            " or userdebug builds.\n");
+                    "Selecting a UID for writing AppBreadcrumb can only be done for other UIDs "
+                            "on eng or userdebug builds.\n");
         }
     }
     if (good) {
-        fprintf(out, "Logging AppHook(%d, %d, %d) to statslog.\n", uid, label, state);
-        android::util::stats_write(android::util::APP_HOOK, uid, label, state);
+        fprintf(out, "Logging AppBreadcrumbReported(%d, %d, %d) to statslog.\n", uid, label, state);
+        android::util::stats_write(android::util::APP_BREADCRUMB_REPORTED, uid, label, state);
     } else {
         print_cmd_help(out);
         return UNKNOWN_ERROR;
@@ -602,9 +614,15 @@
 }
 
 status_t StatsService::cmd_clear_puller_cache(FILE* out) {
-    mStatsPullerManager.ClearPullerCache();
-    fprintf(out, "Puller cached data removed!\n");
-    return NO_ERROR;
+    IPCThreadState* ipc = IPCThreadState::self();
+    VLOG("StatsService::cmd_clear_puller_cache with Pid %i, Uid %i", ipc->getCallingPid(), ipc->getCallingUid());
+    if (checkCallingPermission(String16(kPermissionDump))) {
+        int cleared = mStatsPullerManager.ForceClearPullerCache();
+        fprintf(out, "Puller removed %d cached data!\n", cleared);
+        return NO_ERROR;
+    } else {
+        return PERMISSION_DENIED;
+    }
 }
 
 Status StatsService::informAllUidData(const vector<int32_t>& uid, const vector<int64_t>& version,
@@ -651,12 +669,15 @@
         return Status::fromExceptionCode(Status::EX_SECURITY,
                                          "Only system uid can call informAnomalyAlarmFired");
     }
-
-    VLOG("StatsService::informAnomalyAlarmFired succeeded");
-    uint64_t currentTimeSec = time(nullptr);
+    uint64_t currentTimeSec = getElapsedRealtimeSec();
     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();
 }
 
@@ -764,7 +785,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);
@@ -785,7 +806,6 @@
 
 Status StatsService::addConfiguration(int64_t key,
                                       const vector <uint8_t>& config,
-                                      const String16& package, const String16& cls,
                                       bool* success) {
     IPCThreadState* ipc = IPCThreadState::self();
     if (checkCallingPermission(String16(kPermissionDump))) {
@@ -796,8 +816,33 @@
             return Status::ok();
         }
         mConfigManager->UpdateConfig(configKey, cfg);
-        mConfigManager->SetConfigReceiver(configKey, string(String8(package).string()),
-                                          string(String8(cls).string()));
+        *success = true;
+        return Status::ok();
+    } else {
+        *success = false;
+        return Status::fromExceptionCode(binder::Status::EX_SECURITY);
+    }
+}
+
+Status StatsService::removeDataFetchOperation(int64_t key, bool* success) {
+    IPCThreadState* ipc = IPCThreadState::self();
+    if (checkCallingPermission(String16(kPermissionDump))) {
+        ConfigKey configKey(ipc->getCallingUid(), key);
+        mConfigManager->RemoveConfigReceiver(configKey);
+        *success = true;
+        return Status::ok();
+    } else {
+        *success = false;
+        return Status::fromExceptionCode(binder::Status::EX_SECURITY);
+    }
+}
+
+Status StatsService::setDataFetchOperation(int64_t key, const sp<android::IBinder>& intentSender,
+                                           bool* success) {
+    IPCThreadState* ipc = IPCThreadState::self();
+    if (checkCallingPermission(String16(kPermissionDump))) {
+        ConfigKey configKey(ipc->getCallingUid(), key);
+        mConfigManager->SetConfigReceiver(configKey, intentSender);
         *success = true;
         return Status::ok();
     } else {
diff --git a/cmds/statsd/src/StatsService.h b/cmds/statsd/src/StatsService.h
index 109752b..9690de7 100644
--- a/cmds/statsd/src/StatsService.h
+++ b/cmds/statsd/src/StatsService.h
@@ -90,9 +90,19 @@
      * Binder call to let clients send a configuration and indicate they're interested when they
      * should requestData for this configuration.
      */
-    virtual Status addConfiguration(int64_t key, const vector <uint8_t>& config,
-                                    const String16& package, const String16& cls, bool* success)
-    override;
+    virtual Status addConfiguration(int64_t key, const vector<uint8_t>& config,
+                                    bool* success) override;
+
+    /**
+     * Binder call to let clients register the data fetch operation for a configuration.
+     */
+    virtual Status setDataFetchOperation(int64_t key, const sp<android::IBinder>& intentSender,
+                                         bool* success) override;
+
+    /**
+     * Binder call to remove the data fetch operation for the specified config key.
+     */
+    virtual Status removeDataFetchOperation(int64_t key, bool* success) override;
 
     /**
      * Binder call to allow clients to remove the specified configuration.
@@ -183,9 +193,10 @@
     status_t cmd_write_data_to_disk(FILE* out);
 
     /**
-     * Write an AppHook event to the StatsLog buffer, as though StatsLog.write(APP_HOOK).
+     * Write an AppBreadcrumbReported event to the StatsLog buffer, as if calling
+     * StatsLog.write(APP_BREADCRUMB_REPORTED).
      */
-    status_t cmd_log_app_hook(FILE* out, const Vector<String8>& args);
+    status_t cmd_log_app_breadcrumb(FILE* out, const Vector<String8>& args);
 
     /**
      * Print contents of a pulled metrics source.
diff --git a/cmds/statsd/src/anomaly/AnomalyMonitor.cpp b/cmds/statsd/src/anomaly/AnomalyMonitor.cpp
index 4912648..ca34dc6 100644
--- a/cmds/statsd/src/anomaly/AnomalyMonitor.cpp
+++ b/cmds/statsd/src/anomaly/AnomalyMonitor.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#define DEBUG true
+#define DEBUG false
 #include "Log.h"
 
 #include "anomaly/AnomalyMonitor.h"
@@ -36,10 +36,10 @@
     sp<IStatsCompanionService> tmpForLock = mStatsCompanionService;
     mStatsCompanionService = statsCompanionService;
     if (statsCompanionService == nullptr) {
-        if (DEBUG) ALOGD("Erasing link to statsCompanionService");
+        VLOG("Erasing link to statsCompanionService");
         return;
     }
-    if (DEBUG) ALOGD("Creating link to statsCompanionService");
+    VLOG("Creating link to statsCompanionService");
     const sp<const AnomalyAlarm> top = mPq.top();
     if (top != nullptr) {
         updateRegisteredAlarmTime_l(top->timestampSec);
@@ -58,7 +58,7 @@
         return;
     }
     // TODO: Ensure that refractory period is respected.
-    if (DEBUG) ALOGD("Adding alarm with time %u", alarm->timestampSec);
+    VLOG("Adding alarm with time %u", alarm->timestampSec);
     mPq.push(alarm);
     if (mRegisteredAlarmTimeSec < 1 ||
         alarm->timestampSec + mMinUpdateTimeSec < mRegisteredAlarmTimeSec) {
@@ -72,16 +72,16 @@
         ALOGW("Asked to remove a null alarm.");
         return;
     }
-    if (DEBUG) ALOGD("Removing alarm with time %u", alarm->timestampSec);
+    VLOG("Removing alarm with time %u", alarm->timestampSec);
     bool wasPresent = mPq.remove(alarm);
     if (!wasPresent) return;
     if (mPq.empty()) {
-        if (DEBUG) ALOGD("Queue is empty. Cancel any alarm.");
+        VLOG("Queue is empty. Cancel any alarm.");
         cancelRegisteredAlarmTime_l();
         return;
     }
     uint32_t soonestAlarmTimeSec = mPq.top()->timestampSec;
-    if (DEBUG) ALOGD("Soonest alarm is %u", soonestAlarmTimeSec);
+    VLOG("Soonest alarm is %u", soonestAlarmTimeSec);
     if (soonestAlarmTimeSec > mRegisteredAlarmTimeSec + mMinUpdateTimeSec) {
         updateRegisteredAlarmTime_l(soonestAlarmTimeSec);
     }
@@ -91,19 +91,19 @@
 // updates to the registered alarm.
 unordered_set<sp<const AnomalyAlarm>, SpHash<AnomalyAlarm>> AnomalyMonitor::popSoonerThan(
         uint32_t timestampSec) {
-    if (DEBUG) ALOGD("Removing alarms with time <= %u", timestampSec);
+    VLOG("Removing alarms with time <= %u", timestampSec);
     unordered_set<sp<const AnomalyAlarm>, SpHash<AnomalyAlarm>> oldAlarms;
     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
     }
     // Always update registered alarm time (if anything has changed).
     if (!oldAlarms.empty()) {
         if (mPq.empty()) {
-            if (DEBUG) ALOGD("Queue is empty. Cancel any alarm.");
+            VLOG("Queue is empty. Cancel any alarm.");
             cancelRegisteredAlarmTime_l();
         } else {
             // Always update the registered alarm in this case (unlike remove()).
@@ -114,7 +114,7 @@
 }
 
 void AnomalyMonitor::updateRegisteredAlarmTime_l(uint32_t timestampSec) {
-    if (DEBUG) ALOGD("Updating reg alarm time to %u", timestampSec);
+    VLOG("Updating reg alarm time to %u", timestampSec);
     mRegisteredAlarmTimeSec = timestampSec;
     if (mStatsCompanionService != nullptr) {
         mStatsCompanionService->setAnomalyAlarm(secToMs(mRegisteredAlarmTimeSec));
@@ -123,7 +123,7 @@
 }
 
 void AnomalyMonitor::cancelRegisteredAlarmTime_l() {
-    if (DEBUG) ALOGD("Cancelling reg alarm.");
+    VLOG("Cancelling reg alarm.");
     mRegisteredAlarmTimeSec = 0;
     if (mStatsCompanionService != nullptr) {
         mStatsCompanionService->cancelAnomalyAlarm();
diff --git a/cmds/statsd/src/anomaly/AnomalyTracker.cpp b/cmds/statsd/src/anomaly/AnomalyTracker.cpp
index c84a5b4..443d33d 100644
--- a/cmds/statsd/src/anomaly/AnomalyTracker.cpp
+++ b/cmds/statsd/src/anomaly/AnomalyTracker.cpp
@@ -14,18 +14,15 @@
  * limitations under the License.
  */
 
-#define DEBUG true  // STOPSHIP if true
+#define DEBUG false  // STOPSHIP if true
 #include "Log.h"
 
 #include "AnomalyTracker.h"
 #include "external/Perfetto.h"
 #include "guardrail/StatsdStats.h"
-#include "frameworks/base/libs/incident/proto/android/os/header.pb.h"
+#include "subscriber/IncidentdReporter.h"
 #include "subscriber/SubscriberReporter.h"
 
-#include <android/os/IIncidentManager.h>
-#include <android/os/IncidentReportArgs.h>
-#include <binder/IServiceManager.h>
 #include <statslog.h>
 #include <time.h>
 
@@ -35,20 +32,17 @@
 
 // TODO: Get rid of bucketNumbers, and return to the original circular array method.
 AnomalyTracker::AnomalyTracker(const Alert& alert, const ConfigKey& configKey)
-    : mAlert(alert),
-      mConfigKey(configKey),
-      mNumOfPastBuckets(mAlert.num_buckets() - 1) {
+    : mAlert(alert), mConfigKey(configKey), mNumOfPastBuckets(mAlert.num_buckets() - 1) {
     VLOG("AnomalyTracker() called");
     if (mAlert.num_buckets() <= 0) {
-        ALOGE("Cannot create AnomalyTracker with %lld buckets",
-              (long long)mAlert.num_buckets());
+        ALOGE("Cannot create AnomalyTracker with %lld buckets", (long long)mAlert.num_buckets());
         return;
     }
     if (!mAlert.has_trigger_if_sum_gt()) {
         ALOGE("Cannot create AnomalyTracker without threshold");
         return;
     }
-    resetStorage(); // initialization
+    resetStorage();  // initialization
 }
 
 AnomalyTracker::~AnomalyTracker() {
@@ -98,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)];
@@ -112,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;
@@ -171,8 +171,8 @@
         // TODO: This creates a needless 0 entry in mSumOverPastBuckets. Fix this.
         addPastBucket(key, 0, currentBucketNum - 1);
     }
-    return mAlert.has_trigger_if_sum_gt()
-            && getSumOverPastBuckets(key) + currentBucketValue > mAlert.trigger_if_sum_gt();
+    return mAlert.has_trigger_if_sum_gt() &&
+           getSumOverPastBuckets(key) + currentBucketValue > mAlert.trigger_if_sum_gt();
 }
 
 void AnomalyTracker::declareAnomaly(const uint64_t& timestampNs, const MetricDimensionKey& key) {
@@ -188,7 +188,7 @@
 
     if (!mSubscriptions.empty()) {
         if (mAlert.has_id()) {
-            ALOGI("An anomaly (%llu) has occurred! Informing subscribers.",mAlert.id());
+            ALOGI("An anomaly (%llu) has occurred! Informing subscribers.", mAlert.id());
             informSubscribers(key);
         } else {
             ALOGI("An anomaly (with no id) has occurred! Not informing any subscribers.");
@@ -233,44 +233,26 @@
         return;
     }
 
-    std::set<int> incidentdSections;
-
     for (const Subscription& subscription : mSubscriptions) {
         switch (subscription.subscriber_information_case()) {
             case Subscription::SubscriberInformationCase::kIncidentdDetails:
-                for (int i = 0; i < subscription.incidentd_details().section_size(); i++) {
-                    incidentdSections.insert(subscription.incidentd_details().section(i));
+                if (!GenerateIncidentReport(subscription.incidentd_details(), mAlert, mConfigKey)) {
+                    ALOGW("Failed to generate incident report.");
                 }
                 break;
             case Subscription::SubscriberInformationCase::kPerfettoDetails:
-                CollectPerfettoTraceAndUploadToDropbox(subscription.perfetto_details());
+                if (!CollectPerfettoTraceAndUploadToDropbox(subscription.perfetto_details())) {
+                    ALOGW("Failed to generate prefetto traces.");
+                }
                 break;
             case Subscription::SubscriberInformationCase::kBroadcastSubscriberDetails:
-                SubscriberReporter::getInstance()
-                        .alertBroadcastSubscriber(mConfigKey, subscription, key);
+                SubscriberReporter::getInstance().alertBroadcastSubscriber(mConfigKey, subscription,
+                                                                           key);
                 break;
             default:
                 break;
         }
     }
-    if (!incidentdSections.empty()) {
-        sp<IIncidentManager> service = interface_cast<IIncidentManager>(
-                defaultServiceManager()->getService(android::String16("incident")));
-        if (service != NULL) {
-            IncidentReportArgs incidentReport;
-            for (const auto section : incidentdSections) {
-                incidentReport.addSection(section);
-            }
-            android::os::IncidentHeaderProto header;
-            header.set_alert_id(mAlert.id());
-            header.mutable_config_key()->set_uid(mConfigKey.GetUid());
-            header.mutable_config_key()->set_id(mConfigKey.GetId());
-            incidentReport.addHeader(header);
-            service->reportIncident(incidentReport);
-        } else {
-            ALOGW("Couldn't get the incident service.");
-        }
-    }
 }
 
 }  // namespace statsd
diff --git a/cmds/statsd/src/anomaly/AnomalyTracker.h b/cmds/statsd/src/anomaly/AnomalyTracker.h
index f01a97f..3be959d 100644
--- a/cmds/statsd/src/anomaly/AnomalyTracker.h
+++ b/cmds/statsd/src/anomaly/AnomalyTracker.h
@@ -16,22 +16,24 @@
 
 #pragma once
 
+#include <memory>  // unique_ptr
+
+#include <stdlib.h>
+
 #include <gtest/gtest_prod.h>
+#include <utils/RefBase.h>
+
 #include "AnomalyMonitor.h"
 #include "config/ConfigKey.h"
 #include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"  // Alert
 #include "stats_util.h"  // HashableDimensionKey and DimToValMap
 
-#include <memory> // unique_ptr
-#include <stdlib.h>
-#include <utils/RefBase.h>
-
 namespace android {
 namespace os {
 namespace statsd {
 
-using std::unordered_map;
 using std::shared_ptr;
+using std::unordered_map;
 
 // Does NOT allow negative values.
 class AnomalyTracker : public virtual RefBase {
@@ -60,12 +62,11 @@
 
     // Detects the alert and informs the incidentd when applicable.
     void detectAndDeclareAnomaly(const uint64_t& timestampNs, const int64_t& currBucketNum,
-                                 const MetricDimensionKey& key,
-                                 const int64_t& currentBucketValue);
+                                 const MetricDimensionKey& key, const int64_t& currentBucketValue);
 
     // Init the AnomalyMonitor which is shared across anomaly trackers.
     virtual void setAnomalyMonitor(const sp<AnomalyMonitor>& anomalyMonitor) {
-        return; // Base AnomalyTracker class has no need for the AnomalyMonitor.
+        return;  // Base AnomalyTracker class has no need for the AnomalyMonitor.
     }
 
     // Helper function to return the sum value of past buckets at given dimension.
@@ -92,9 +93,10 @@
 
     // Declares an anomaly for each alarm in firedAlarms that belongs to this AnomalyTracker,
     // and removes it from firedAlarms. Does NOT remove the alarm from the AnomalyMonitor.
-    virtual void informAlarmsFired(const uint64_t& timestampNs,
+    virtual void informAlarmsFired(
+            const uint64_t& timestampNs,
             unordered_set<sp<const AnomalyAlarm>, SpHash<AnomalyAlarm>>& firedAlarms) {
-        return; // The base AnomalyTracker class doesn't have alarms.
+        return;  // The base AnomalyTracker class doesn't have alarms.
     }
 
 protected:
diff --git a/cmds/statsd/src/anomaly/DurationAnomalyTracker.cpp b/cmds/statsd/src/anomaly/DurationAnomalyTracker.cpp
index bbee9fa..3ba943c 100644
--- a/cmds/statsd/src/anomaly/DurationAnomalyTracker.cpp
+++ b/cmds/statsd/src/anomaly/DurationAnomalyTracker.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#define DEBUG true  // STOPSHIP if true
+#define DEBUG false  // STOPSHIP if true
 #include "Log.h"
 
 #include "DurationAnomalyTracker.h"
@@ -52,12 +52,12 @@
 }
 
 void DurationAnomalyTracker::startAlarm(const MetricDimensionKey& dimensionKey,
-                                const uint64_t& timestampNs) {
-
-    uint32_t timestampSec = static_cast<uint32_t>(timestampNs / NS_PER_SEC);
+                                        const uint64_t& timestampNs) {
+    // 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});
@@ -86,15 +86,15 @@
     }
 }
 
-void DurationAnomalyTracker::informAlarmsFired(const uint64_t& timestampNs,
+void DurationAnomalyTracker::informAlarmsFired(
+        const uint64_t& timestampNs,
         unordered_set<sp<const AnomalyAlarm>, SpHash<AnomalyAlarm>>& firedAlarms) {
-
     if (firedAlarms.empty() || mAlarms.empty()) return;
     // Find the intersection of firedAlarms and mAlarms.
     // The for loop is inefficient, since it loops over all keys, but that's okay since it is very
     // seldomly called. The alternative would be having AnomalyAlarms store information about the
-    // DurationAnomalyTracker and key, but that's a lot of data overhead to speed up something that is
-    // rarely ever called.
+    // DurationAnomalyTracker and key, but that's a lot of data overhead to speed up something that
+    // is rarely ever called.
     unordered_map<MetricDimensionKey, sp<const AnomalyAlarm>> matchedAlarms;
     for (const auto& kv : mAlarms) {
         if (firedAlarms.count(kv.second) > 0) {
diff --git a/cmds/statsd/src/anomaly/DurationAnomalyTracker.h b/cmds/statsd/src/anomaly/DurationAnomalyTracker.h
index 052fdf57..ba687da 100644
--- a/cmds/statsd/src/anomaly/DurationAnomalyTracker.h
+++ b/cmds/statsd/src/anomaly/DurationAnomalyTracker.h
@@ -53,7 +53,8 @@
     // and removes it from firedAlarms.
     // Note that this will generally be called from a different thread from the other functions;
     // the caller is responsible for thread safety.
-    void informAlarmsFired(const uint64_t& timestampNs,
+    void informAlarmsFired(
+            const uint64_t& timestampNs,
             unordered_set<sp<const AnomalyAlarm>, SpHash<AnomalyAlarm>>& firedAlarms) override;
 
 protected:
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index e58c535..85e209b 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -24,6 +24,7 @@
 import "frameworks/base/core/proto/android/app/enums.proto";
 import "frameworks/base/core/proto/android/os/enums.proto";
 import "frameworks/base/core/proto/android/server/enums.proto";
+import "frameworks/base/core/proto/android/telecomm/enums.proto";
 import "frameworks/base/core/proto/android/telephony/enums.proto";
 import "frameworks/base/core/proto/android/view/enums.proto";
 
@@ -84,7 +85,7 @@
         PacketWakeupOccurred packet_wakeup_occurred = 44;
         DropboxErrorChanged dropbox_error_changed = 45;
         AnomalyDetected anomaly_detected = 46;
-        AppHook app_hook = 47;
+        AppBreadcrumbReported app_breadcrumb_reported = 47;
         AppStartChanged app_start_changed = 48;
         AppStartCancelChanged app_start_cancel_changed = 49;
         AppStartFullyDrawnChanged app_start_fully_drawn_changed = 50;
@@ -98,6 +99,7 @@
         DaveyOccurred davey_occurred = 58;
         OverlayStateChanged overlay_state_changed = 59;
         ForegroundServiceStateChanged foreground_service_state_changed = 60;
+        CallStateChanged call_state_changed = 61;
         // TODO: Reorder the numbering so that the most frequent occur events occur in the first 15.
     }
 
@@ -200,9 +202,10 @@
  *   frameworks/base/services/core/java/com/android/server/am/BatteryStatsService.java
  */
 message ProcessLifeCycleStateChanged {
-    optional int32 uid = 1; // TODO: should be a string tagged w/ uid annotation
+    // TODO: should be a string tagged w/ uid annotation
+    optional int32 uid = 1;
 
-    // TODO: What is this?
+    // The process name (usually same as the app name).
     optional string name = 2;
 
     // What lifecycle state the process changed to.
@@ -310,7 +313,7 @@
 message SyncStateChanged {
     repeated AttributionNode attribution_node = 1;
 
-    // Name of the sync (as named in the app)
+    // Name of the sync (as named in the app). Can be chosen at run-time.
     optional string name = 2;
 
     enum State {
@@ -613,7 +616,7 @@
     optional string wakeup_reason_name = 1;
 
     // Duration (in microseconds) for the wake-up interrupt to be serviced.
-    optional int64 duration_usec = 2;
+    optional int64 duration_micros = 2;
 }
 
 /**
@@ -690,10 +693,10 @@
 
     // Beginning of shutdown time in ms using wall clock time since unix epoch.
     // Default: 0 if no start time received.
-    optional int64 start_time_ms = 3;
+    optional int64 start_time_millis = 3;
 
     // Duration of shutdown in ms. Default: 0 if no duration received.
-    optional int64 duration_ms = 4;
+    optional int64 duration_millis = 4;
 }
 
 
@@ -713,18 +716,45 @@
     optional string system_reason = 2;
 
     // End of boot time in ms from unix epoch using system wall clock.
-    optional int64 end_time_ms = 3;
+    optional int64 end_time_millis = 3;
 
     // Total boot duration in ms.
-    optional int64 total_duration_ms = 4;
+    optional int64 total_duration_millis = 4;
 
     // Bootloader duration in ms.
-    optional int64 bootloader_duration_ms = 5;
+    optional int64 bootloader_duration_millis = 5;
 
     // Time since last boot in ms. Default: 0 if not available.
     optional int64 time_since_last_boot = 6;
 }
 
+
+/**
+ * Logs call state and disconnect cause (if applicable).
+ *
+ * Logged from:
+ *   packages/services/Telecomm/src/com/android/server/telecom/Call.java
+ */
+message CallStateChanged {
+    // The state of the call. Eg. DIALING, ACTIVE, ON_HOLD, DISCONNECTED.
+    // From frameworks/base/core/proto/android/telecomm/enums.proto.
+    optional android.telecom.CallStateEnum call_state = 1;
+
+    // The reason the call disconnected. Eg. ERROR, MISSED, REJECTED, BUSY.
+    // This value is only applicable when the call_state is DISCONNECTED, and
+    // should always be UNKNOWN if the call_state is not DISCONNECTED.
+    // From frameworks/base/core/proto/android/telecomm/enums.proto.
+    optional android.telecom.DisconnectCauseEnum disconnect_cause = 2;
+
+    // True if the call is self-managed, which are apps that use the
+    // telecom infrastructure to make their own calls.
+    optional bool self_managed = 3;
+
+    // True if call is external. External calls are calls on connected Wear
+    // devices but show up in Telecom so the user can pull them onto the device.
+    optional bool external_call = 4;
+}
+
 /**
  * Logs the duration of a davey (jank of >=700ms) when it occurs
  *
@@ -733,7 +763,7 @@
  */
 message DaveyOccurred {
     // Amount of time it took to render the frame. Should be >=700ms.
-    optional int64 jank_duration_ms = 1;
+    optional int64 jank_duration_millis = 1;
 }
 
 /**
@@ -834,7 +864,7 @@
  * Logged from:
  *      frameworks/base/core/java/android/util/StatsLog.java
  */
-message AppHook {
+message AppBreadcrumbReported {
     // The uid of the application that sent this custom atom.
     optional int32 uid = 1;
 
@@ -895,16 +925,16 @@
     optional bool is_instant_app = 6;
 
     // Device uptime when activity started.
-    optional int64 activity_start_msec = 7;
+    optional int64 activity_start_millis = 7;
 
     optional android.app.AppTransitionReasonEnum reason = 8;
 
-    optional int32 transition_delay_msec = 9;
+    optional int32 transition_delay_millis = 9;
     // -1 if not set.
-    optional int32 starting_window_delay_msec = 10;
+    optional int32 starting_window_delay_millis = 10;
     // -1 if not set.
-    optional int32 bind_application_delay_msec = 11;
-    optional int32 windows_drawn_delay_msec = 12;
+    optional int32 bind_application_delay_millis = 11;
+    optional int32 windows_drawn_delay_millis = 12;
 
     // Empty if not set.
     optional string launch_token = 13;
@@ -952,7 +982,7 @@
     optional bool transition_process_running = 5;
 
     // App startup time (until call to Activity#reportFullyDrawn()).
-    optional int64 app_startup_time_ms = 6;
+    optional int64 app_startup_time_millis = 6;
 }
 
 /**
@@ -1019,6 +1049,138 @@
 }
 
 /**
+ * Logs creation or removal of an isolated uid. Isolated uid's are temporary uid's to sandbox risky
+ * behavior in its own uid. However, the metrics of these isolated uid's almost always should be
+ * attributed back to the parent (host) uid. One example is Chrome.
+ *
+ * Logged from:
+ *   frameworks/base/core/java/com/android/internal/os/BatteryStatsImpl.java
+ */
+message IsolatedUidChanged {
+    // The host UID. Generally, we should attribute metrics from the isolated uid to the host uid.
+    optional int32 parent_uid = 1;
+
+    optional int32 isolated_uid = 2;
+
+    // We expect an isolated uid to be removed before if it's used for another parent uid.
+    enum Event {
+        REMOVED = 0;
+        CREATED = 1;
+    }
+    optional Event event = 3;
+}
+
+/*
+ * Logs the reception of an incoming network packet causing the main system to wake up for
+ * processing that packet. These events are notified by the kernel via Netlink NFLOG to Netd
+ * and processed by WakeupController.cpp.
+ */
+message PacketWakeupOccurred {
+    // The uid owning the socket into which the packet was delivered, or -1 if the packet was
+    // delivered nowhere.
+    optional int32 uid = 1;
+    // The interface name on which the packet was received.
+    optional string iface = 2;
+    // The ethertype value of the packet.
+    optional int32 ethertype = 3;
+    // String representation of the destination MAC address of the packet.
+    optional string destination_hardware_address = 4;
+    // String representation of the source address of the packet if this was an IP packet.
+    optional string source_ip = 5;
+    // String representation of the destination address of the packet if this was an IP packet.
+    optional string destination_ip = 6;
+    // The value of the protocol field if this was an IPv4 packet or the value of the Next Header
+    // field if this was an IPv6 packet. The range of possible values is the same for both IP
+    // families.
+    optional int32 ip_next_header = 7;
+    // The source port if this was a TCP or UDP packet.
+    optional int32 source_port = 8;
+    // The destination port if this was a TCP or UDP packet.
+    optional int32 destination_port = 9;
+}
+
+/*
+ * Logs the memory stats for an app on startup.
+ * Logged from:
+ *     frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
+ */
+message AppStartMemoryStateCaptured {
+    // The uid if available. -1 means not available.
+    optional int32 uid = 1;
+
+    // The process name.
+    optional string process_name = 2;
+
+    // The activity name.
+    optional string activity_name = 3;
+
+    // # of page-faults
+    optional int64 pgfault = 4;
+
+    // # of major page-faults
+    optional int64 pgmajfault = 5;
+
+    // RSS
+    optional int64 rss_in_bytes = 6;
+
+    // CACHE
+    optional int64 cache_in_bytes = 7;
+
+    // SWAP
+    optional int64 swap_in_bytes = 8;
+}
+
+/*
+ * Logs the change in Low Memory Killer Daemon (LMKD) state which is used as start/stop boundaries
+ * for LMK event.
+ * Logged from:
+ *      system/core/lmkd/lmkd.c
+ */
+message LmkStateChanged {
+    enum State {
+        UNKNOWN = 0;
+        START = 1;
+        STOP = 2;
+    }
+    optional State state = 1;
+}
+
+/*
+ * Logs the event when Low Memory Killer Daemon (LMKD) kills a process to reduce memory pressure.
+ * Logged from:
+ *      system/core/lmkd/lmkd.c
+ */
+message LmkKillOccurred {
+    // The uid if available. -1 means not available.
+    optional int32 uid = 1;
+
+    // The process name.
+    optional string process_name = 2;
+
+    // oom adj score.
+    optional int32 oom_score = 3;
+
+    // # of page-faults
+    optional int64 pgfault = 4;
+
+    // # of major page-faults
+    optional int64 pgmajfault = 5;
+
+    // RSS
+    optional int64 rss_in_bytes = 6;
+
+    // CACHE
+    optional int64 cache_in_bytes = 7;
+
+    // SWAP
+    optional int64 swap_in_bytes = 8;
+}
+
+//////////////////////////////////////////////////////////////////////
+// Pulled atoms below this line //
+//////////////////////////////////////////////////////////////////////
+
+/**
  * Pulls bytes transferred via wifi (Sum of foreground and background usage).
  *
  * Pulled from:
@@ -1134,37 +1296,15 @@
  *   hardware/interfaces/power/1.1/types.hal
  */
 message SubsystemSleepState {
-    // Name should be in the format of XXX.YYY where XXX is subsystem name,
-    // YYY is corresponding voter name.
-    // If there are no voters, the format should just be XXX (with no dot).
-    // XXX and YYY should not contain a "." in it.
-    optional string name = 1;
+    // Subsystem name
+    optional string subsystem_name = 1;
+    // For PlatformLowPowerStats (hal 1.0), this is the voter name, which could be empty.
+    // For SubsystemLowPowerStats (hal 1.1), this is the sleep state name.
+    optional string subname = 2;
     // The number of times it entered, or voted for entering the sleep state
-    optional uint64 count = 2;
+    optional uint64 count = 3;
     // The length of time spent in, or spent voting for, the sleep state
-    optional uint64 timeMs = 3;
-}
-
-/**
- * Logs creation or removal of an isolated uid. Isolated uid's are temporary uid's to sandbox risky
- * behavior in its own uid. However, the metrics of these isolated uid's almost always should be
- * attributed back to the parent (host) uid. One example is Chrome.
- *
- * Logged from:
- *   frameworks/base/core/java/com/android/internal/os/BatteryStatsImpl.java
- */
-message IsolatedUidChanged {
-    // The host UID. Generally, we should attribute metrics from the isolated uid to the host uid.
-    optional int32 parent_uid = 1;
-
-    optional int32 isolated_uid = 2;
-
-    // We expect an isolated uid to be removed before if it's used for another parent uid.
-    enum Event {
-        REMOVED = 0;
-        CREATED = 1;
-    }
-    optional Event event = 3;
+    optional uint64 time_millis = 4;
 }
 
 /**
@@ -1177,7 +1317,7 @@
 message CpuTimePerFreq {
     optional uint32 cluster = 1;
     optional uint32 freq_index = 2;
-    optional uint64 time_ms = 3;
+    optional uint64 time_millis = 3;
 }
 
 /**
@@ -1186,8 +1326,8 @@
  */
 message CpuTimePerUid {
     optional uint64 uid = 1;
-    optional uint64 user_time_ms = 2;
-    optional uint64 sys_time_ms = 3;
+    optional uint64 user_time_millis = 2;
+    optional uint64 sys_time_millis = 3;
 }
 
 /**
@@ -1198,36 +1338,7 @@
 message CpuTimePerUidFreq {
     optional uint64 uid = 1;
     optional uint64 freq_idx = 2;
-    optional uint64 time_ms = 3;
-}
-
-/*
- * Logs the reception of an incoming network packet causing the main system to wake up for
- * processing that packet. These events are notified by the kernel via Netlink NFLOG to Netd
- * and processed by WakeupController.cpp.
- */
-message PacketWakeupOccurred {
-    // The uid owning the socket into which the packet was delivered, or -1 if the packet was
-    // delivered nowhere.
-    optional int32 uid = 1;
-    // The interface name on which the packet was received.
-    optional string iface = 2;
-    // The ethertype value of the packet.
-    optional int32 ethertype = 3;
-    // String representation of the destination MAC address of the packet.
-    optional string destination_hardware_address = 4;
-    // String representation of the source address of the packet if this was an IP packet.
-    optional string source_ip = 5;
-    // String representation of the destination address of the packet if this was an IP packet.
-    optional string destination_ip = 6;
-    // The value of the protocol field if this was an IPv4 packet or the value of the Next Header
-    // field if this was an IPv6 packet. The range of possible values is the same for both IP
-    // families.
-    optional int32 ip_next_header = 7;
-    // The source port if this was a TCP or UDP packet.
-    optional int32 source_port = 8;
-    // The destination port if this was a TCP or UDP packet.
-    optional int32 destination_port = 9;
+    optional uint64 time_millis = 3;
 }
 
 /**
@@ -1235,16 +1346,16 @@
  */
 message WifiActivityEnergyInfo {
     // timestamp(wall clock) of record creation
-    optional uint64 timestamp_ms = 1;
+    optional uint64 timestamp_millis = 1;
     // stack reported state
     // TODO: replace this with proto enum
     optional int32 stack_state = 2;
     // tx time in ms
-    optional uint64 controller_tx_time_ms = 3;
+    optional uint64 controller_tx_time_millis = 3;
     // rx time in ms
-    optional uint64 controller_rx_time_ms = 4;
+    optional uint64 controller_rx_time_millis = 4;
     // idle time in ms
-    optional uint64 controller_idle_time_ms = 5;
+    optional uint64 controller_idle_time_millis = 5;
     // product of current(mA), voltage(V) and time(ms)
     optional uint64 controller_energy_used = 6;
 }
@@ -1254,11 +1365,11 @@
  */
 message ModemActivityInfo {
     // timestamp(wall clock) of record creation
-    optional uint64 timestamp_ms = 1;
+    optional uint64 timestamp_millis = 1;
     // sleep time in ms.
-    optional uint64 sleep_time_ms = 2;
+    optional uint64 sleep_time_millis = 2;
     // idle time in ms
-    optional uint64 controller_idle_time_ms = 3;
+    optional uint64 controller_idle_time_millis = 3;
     /**
      * Tx power index
      * index 0 = tx_power < 0dBm
@@ -1268,17 +1379,17 @@
      * index 4 = tx_power > 20dBm
      */
     // tx time in ms at power level 0
-    optional uint64 controller_tx_time_pl0_ms = 4;
+    optional uint64 controller_tx_time_pl0_millis = 4;
     // tx time in ms at power level 1
-    optional uint64 controller_tx_time_pl1_ms = 5;
+    optional uint64 controller_tx_time_pl1_millis = 5;
     // tx time in ms at power level 2
-    optional uint64 controller_tx_time_pl2_ms = 6;
+    optional uint64 controller_tx_time_pl2_millis = 6;
     // tx time in ms at power level 3
-    optional uint64 controller_tx_time_pl3_ms = 7;
+    optional uint64 controller_tx_time_pl3_millis = 7;
     // tx time in ms at power level 4
-    optional uint64 controller_tx_time_pl4_ms = 8;
+    optional uint64 controller_tx_time_pl4_millis = 8;
     // rx time in ms at power level 5
-    optional uint64 controller_rx_time_ms = 9;
+    optional uint64 controller_rx_time_millis = 9;
     // product of current(mA), voltage(V) and time(ms)
     optional uint64 energy_used = 10;
 }
@@ -1289,51 +1400,20 @@
  */
 message BluetoothActivityInfo {
     // timestamp(wall clock) of record creation
-    optional uint64 timestamp_ms = 1;
+    optional uint64 timestamp_millis = 1;
     // bluetooth stack state
     optional int32 bluetooth_stack_state = 2;
     // tx time in ms
-    optional uint64 controller_tx_time_ms = 3;
+    optional uint64 controller_tx_time_millis = 3;
     // rx time in ms
-    optional uint64 controller_rx_time_ms = 4;
+    optional uint64 controller_rx_time_millis = 4;
     // idle time in ms
-    optional uint64 controller_idle_time_ms = 5;
+    optional uint64 controller_idle_time_millis = 5;
     // product of current(mA), voltage(V) and time(ms)
     optional uint64 energy_used = 6;
 }
 
 /*
- * Logs the memory stats for an app on startup.
- * Logged from:
- *     frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
- */
-message AppStartMemoryStateCaptured {
-    // The uid if available. -1 means not available.
-    optional int32 uid = 1;
-
-    // The process name.
-    optional string process_name = 2;
-
-    // The activity name.
-    optional string activity_name = 3;
-
-    // # of page-faults
-    optional int64 pgfault = 4;
-
-    // # of major page-faults
-    optional int64 pgmajfault = 5;
-
-    // RSS
-    optional int64 rss_in_bytes = 6;
-
-    // CACHE
-    optional int64 cache_in_bytes = 7;
-
-    // SWAP
-    optional int64 swap_in_bytes = 8;
-}
-
-/*
  * Logs the memory stats for a process.
  */
 message ProcessMemoryState {
@@ -1363,56 +1443,10 @@
 }
 
 /*
- * Logs the change in Low Memory Killer Daemon (LMKD) state which is used as start/stop boundaries
- * for LMK event.
- * Logged from:
- *      system/core/lmkd/lmkd.c
- */
-message LmkStateChanged {
-    enum State {
-        UNKNOWN = 0;
-        START = 1;
-        STOP = 2;
-    }
-    optional State state = 1;
-}
-
-/*
- * Logs the event when Low Memory Killer Daemon (LMKD) kills a process to reduce memory pressure.
- * Logged from:
- *      system/core/lmkd/lmkd.c
- */
-message LmkKillOccurred {
-    // The uid if available. -1 means not available.
-    optional int32 uid = 1;
-
-    // The process name.
-    optional string process_name = 2;
-
-    // oom adj score.
-    optional int32 oom_score = 3;
-
-    // # of page-faults
-    optional int64 pgfault = 4;
-
-    // # of major page-faults
-    optional int64 pgmajfault = 5;
-
-    // RSS
-    optional int64 rss_in_bytes = 6;
-
-    // CACHE
-    optional int64 cache_in_bytes = 7;
-
-    // SWAP
-    optional int64 swap_in_bytes = 8;
-}
-
-/*
  * Elapsed real time from SystemClock.
  */
 message SystemElapsedRealtime {
-    optional uint64 time_ms = 1;
+    optional uint64 time_millis = 1;
 }
 
 /*
@@ -1423,7 +1457,7 @@
     // This clock stops when the system enters deep sleep (CPU off, display dark, device waiting
     // for external input).
     // It is not affected by clock scaling, idle, or other power saving mechanisms.
-    optional uint64 uptime_ms = 1;
+    optional uint64 uptime_millis = 1;
 }
 
 /*
@@ -1437,8 +1471,9 @@
  */
 message CpuActiveTime {
     optional uint64 uid = 1;
-    optional uint64 idx = 2;
-    optional uint64 time_ms = 3;
+    optional uint32 cluster_number = 2;
+    optional uint64 idx = 3;
+    optional uint64 time_millis = 4;
 }
 
 /**
@@ -1453,7 +1488,7 @@
 message CpuClusterTime {
     optional uint64 uid = 1;
     optional uint64 idx = 2;
-    optional uint64 time_ms = 3;
+    optional uint64 time_millis = 3;
 }
 
 /*
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/config/ConfigManager.cpp b/cmds/statsd/src/config/ConfigManager.cpp
index 61eeee3..d0f55ab 100644
--- a/cmds/statsd/src/config/ConfigManager.cpp
+++ b/cmds/statsd/src/config/ConfigManager.cpp
@@ -59,71 +59,106 @@
 }
 
 void ConfigManager::AddListener(const sp<ConfigListener>& listener) {
+    lock_guard<mutex> lock(mMutex);
     mListeners.push_back(listener);
 }
 
 void ConfigManager::UpdateConfig(const ConfigKey& key, const StatsdConfig& config) {
-    // Add to set
-    mConfigs.insert(key);
+    vector<sp<ConfigListener>> broadcastList;
+    {
+        lock_guard <mutex> lock(mMutex);
 
-    // Save to disk
-    update_saved_configs(key, config);
+        // Add to set
+        mConfigs.insert(key);
+
+        // Save to disk
+        update_saved_configs_locked(key, config);
+
+        for (sp<ConfigListener> listener : mListeners) {
+            broadcastList.push_back(listener);
+        }
+    }
 
     // Tell everyone
-    for (auto& listener : mListeners) {
+    for (sp<ConfigListener> listener:broadcastList) {
         listener->OnConfigUpdated(key, config);
     }
 }
 
-void ConfigManager::SetConfigReceiver(const ConfigKey& key, const string& pkg, const string& cls) {
-    mConfigReceivers[key] = pair<string, string>(pkg, cls);
+void ConfigManager::SetConfigReceiver(const ConfigKey& key, const sp<IBinder>& intentSender) {
+    lock_guard<mutex> lock(mMutex);
+    mConfigReceivers[key] = intentSender;
 }
 
 void ConfigManager::RemoveConfigReceiver(const ConfigKey& key) {
+    lock_guard<mutex> lock(mMutex);
     mConfigReceivers.erase(key);
 }
 
 void ConfigManager::RemoveConfig(const ConfigKey& key) {
-    auto it = mConfigs.find(key);
-    if (it != mConfigs.end()) {
-        // Remove from map
-        mConfigs.erase(it);
+    vector<sp<ConfigListener>> broadcastList;
+    {
+        lock_guard <mutex> lock(mMutex);
 
-        // Tell everyone
-        for (auto& listener : mListeners) {
-            listener->OnConfigRemoved(key);
+        auto it = mConfigs.find(key);
+        if (it != mConfigs.end()) {
+            // Remove from map
+            mConfigs.erase(it);
+
+            for (sp<ConfigListener> listener : mListeners) {
+                broadcastList.push_back(listener);
+            }
         }
+
+        auto itReceiver = mConfigReceivers.find(key);
+        if (itReceiver != mConfigReceivers.end()) {
+            // Remove from map
+            mConfigReceivers.erase(itReceiver);
+        }
+
+        // Remove from disk. There can still be a lingering file on disk so we check
+        // whether or not the config was on memory.
+        remove_saved_configs(key);
     }
 
-    // Remove from disk. There can still be a lingering file on disk so we check
-    // whether or not the config was on memory.
-    remove_saved_configs(key);
+    for (sp<ConfigListener> listener:broadcastList) {
+        listener->OnConfigRemoved(key);
+    }
 }
 
 void ConfigManager::remove_saved_configs(const ConfigKey& key) {
-    string suffix = StringPrintf("%d-%lld", key.GetUid(), (long long)key.GetId());
+    string suffix = StringPrintf("%d_%lld", key.GetUid(), (long long)key.GetId());
     StorageManager::deleteSuffixedFiles(STATS_SERVICE_DIR, suffix.c_str());
 }
 
 void ConfigManager::RemoveConfigs(int uid) {
     vector<ConfigKey> removed;
+    vector<sp<ConfigListener>> broadcastList;
+    {
+        lock_guard <mutex> lock(mMutex);
 
-    for (auto it = mConfigs.begin(); it != mConfigs.end();) {
-        // Remove from map
-        if (it->GetUid() == uid) {
-            remove_saved_configs(*it);
-            removed.push_back(*it);
-            mConfigReceivers.erase(*it);
-            it = mConfigs.erase(it);
-        } else {
-            it++;
+
+        for (auto it = mConfigs.begin(); it != mConfigs.end();) {
+            // Remove from map
+            if (it->GetUid() == uid) {
+                remove_saved_configs(*it);
+                removed.push_back(*it);
+                mConfigReceivers.erase(*it);
+                it = mConfigs.erase(it);
+            } else {
+                it++;
+            }
+        }
+
+        for (sp<ConfigListener> listener : mListeners) {
+            broadcastList.push_back(listener);
         }
     }
 
     // Remove separately so if they do anything in the callback they can't mess up our iteration.
     for (auto& key : removed) {
         // Tell everyone
-        for (auto& listener : mListeners) {
+        for (sp<ConfigListener> listener:broadcastList) {
             listener->OnConfigRemoved(key);
         }
     }
@@ -131,27 +166,38 @@
 
 void ConfigManager::RemoveAllConfigs() {
     vector<ConfigKey> removed;
+    vector<sp<ConfigListener>> broadcastList;
+    {
+        lock_guard <mutex> lock(mMutex);
 
-    for (auto it = mConfigs.begin(); it != mConfigs.end();) {
-        // Remove from map
-        removed.push_back(*it);
-        auto receiverIt = mConfigReceivers.find(*it);
-        if (receiverIt != mConfigReceivers.end()) {
-            mConfigReceivers.erase(*it);
+
+        for (auto it = mConfigs.begin(); it != mConfigs.end();) {
+            // Remove from map
+            removed.push_back(*it);
+            auto receiverIt = mConfigReceivers.find(*it);
+            if (receiverIt != mConfigReceivers.end()) {
+                mConfigReceivers.erase(*it);
+            }
+            it = mConfigs.erase(it);
         }
-        it = mConfigs.erase(it);
+
+        for (sp<ConfigListener> listener : mListeners) {
+            broadcastList.push_back(listener);
+        }
     }
 
     // Remove separately so if they do anything in the callback they can't mess up our iteration.
     for (auto& key : removed) {
         // Tell everyone
-        for (auto& listener : mListeners) {
+        for (sp<ConfigListener> listener:broadcastList) {
             listener->OnConfigRemoved(key);
         }
     }
 }
 
 vector<ConfigKey> ConfigManager::GetAllConfigKeys() const {
+    lock_guard<mutex> lock(mMutex);
+
     vector<ConfigKey> ret;
     for (auto it = mConfigs.cbegin(); it != mConfigs.cend(); ++it) {
         ret.push_back(*it);
@@ -159,29 +205,32 @@
     return ret;
 }
 
-const pair<string, string> ConfigManager::GetConfigReceiver(const ConfigKey& key) const {
+const sp<android::IBinder> ConfigManager::GetConfigReceiver(const ConfigKey& key) const {
+    lock_guard<mutex> lock(mMutex);
+
     auto it = mConfigReceivers.find(key);
     if (it == mConfigReceivers.end()) {
-        return pair<string,string>();
+        return nullptr;
     } else {
         return it->second;
     }
 }
 
 void ConfigManager::Dump(FILE* out) {
+    lock_guard<mutex> lock(mMutex);
+
     fprintf(out, "CONFIGURATIONS (%d)\n", (int)mConfigs.size());
     fprintf(out, "     uid name\n");
     for (const auto& key : mConfigs) {
         fprintf(out, "  %6d %lld\n", key.GetUid(), (long long)key.GetId());
         auto receiverIt = mConfigReceivers.find(key);
         if (receiverIt != mConfigReceivers.end()) {
-            fprintf(out, "    -> received by %s, %s\n", receiverIt->second.first.c_str(),
-                    receiverIt->second.second.c_str());
+            fprintf(out, "    -> received by PendingIntent as binder\n");
         }
     }
 }
 
-void ConfigManager::update_saved_configs(const ConfigKey& key, const StatsdConfig& config) {
+void ConfigManager::update_saved_configs_locked(const ConfigKey& key, const StatsdConfig& config) {
     // If there is a pre-existing config with same key we should first delete it.
     remove_saved_configs(key);
 
diff --git a/cmds/statsd/src/config/ConfigManager.h b/cmds/statsd/src/config/ConfigManager.h
index ad666bc..a0c1c1c 100644
--- a/cmds/statsd/src/config/ConfigManager.h
+++ b/cmds/statsd/src/config/ConfigManager.h
@@ -16,10 +16,12 @@
 
 #pragma once
 
+#include "binder/IBinder.h"
 #include "config/ConfigKey.h"
 #include "config/ConfigListener.h"
 
 #include <map>
+#include <mutex>
 #include <set>
 #include <string>
 
@@ -68,12 +70,12 @@
     /**
      * Sets the broadcast receiver for a configuration key.
      */
-    void SetConfigReceiver(const ConfigKey& key, const std::string& pkg, const std::string& cls);
+    void SetConfigReceiver(const ConfigKey& key, const sp<IBinder>& intentSender);
 
     /**
      * Returns the package name and class name representing the broadcast receiver for this config.
      */
-    const std::pair<std::string, std::string> GetConfigReceiver(const ConfigKey& key) const;
+    const sp<android::IBinder> GetConfigReceiver(const ConfigKey& key) const;
 
     /**
      * Returns all config keys registered.
@@ -108,10 +110,12 @@
     void Dump(FILE* out);
 
 private:
+    mutable std::mutex mMutex;
+
     /**
      * Save the configs to disk.
      */
-    void update_saved_configs(const ConfigKey& key, const StatsdConfig& config);
+    void update_saved_configs_locked(const ConfigKey& key, const StatsdConfig& config);
 
     /**
      * Remove saved configs from disk.
@@ -124,10 +128,10 @@
     std::set<ConfigKey> mConfigs;
 
     /**
-     * Each config key can be subscribed by up to one receiver, specified as the package name and
-     * class name.
+     * Each config key can be subscribed by up to one receiver, specified as IBinder from
+     * PendingIntent.
      */
-    std::map<ConfigKey, std::pair<std::string, std::string>> mConfigReceivers;
+    std::map<ConfigKey, sp<android::IBinder>> mConfigReceivers;
 
     /**
      * The ConfigListeners that will be told about changes.
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/CpuTimePerUidFreqPuller.cpp b/cmds/statsd/src/external/CpuTimePerUidFreqPuller.cpp
index a751273..d1d9d37 100644
--- a/cmds/statsd/src/external/CpuTimePerUidFreqPuller.cpp
+++ b/cmds/statsd/src/external/CpuTimePerUidFreqPuller.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#define DEBUG true  // STOPSHIP if true
+#define DEBUG false  // STOPSHIP if true
 #include "Log.h"
 
 #include <fstream>
@@ -25,6 +25,7 @@
 #include "guardrail/StatsdStats.h"
 #include "logd/LogEvent.h"
 #include "statslog.h"
+#include "stats_log_util.h"
 
 using std::make_shared;
 using std::shared_ptr;
@@ -62,7 +63,9 @@
         return false;
     }
 
-    uint64_t timestamp = time(nullptr) * NS_PER_SEC;
+    int64_t wallClockTimestampNs = getWallClockNs();
+    int64_t elapsedTimestampNs = getElapsedRealtimeNs();
+
     char buf[kLineBufferSize];
     // first line prints the format and frequencies
     fin.getline(buf, kLineBufferSize);
@@ -77,7 +80,8 @@
         int idx = 0;
         do {
             timeMs = std::stoull(pch);
-            auto ptr = make_shared<LogEvent>(android::util::CPU_TIME_PER_UID_FREQ, timestamp);
+            auto ptr = make_shared<LogEvent>(android::util::CPU_TIME_PER_UID_FREQ,
+                wallClockTimestampNs, elapsedTimestampNs);
             ptr->write(uid);
             ptr->write(idx);
             ptr->write(timeMs);
diff --git a/cmds/statsd/src/external/CpuTimePerUidPuller.cpp b/cmds/statsd/src/external/CpuTimePerUidPuller.cpp
index e7ea4b9..568b8f0 100644
--- a/cmds/statsd/src/external/CpuTimePerUidPuller.cpp
+++ b/cmds/statsd/src/external/CpuTimePerUidPuller.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#define DEBUG true  // STOPSHIP if true
+#define DEBUG false  // STOPSHIP if true
 #include "Log.h"
 
 #include <fstream>
@@ -24,6 +24,7 @@
 #include "guardrail/StatsdStats.h"
 #include "logd/LogEvent.h"
 #include "statslog.h"
+#include "stats_log_util.h"
 
 using std::make_shared;
 using std::shared_ptr;
@@ -57,7 +58,8 @@
         return false;
     }
 
-    uint64_t timestamp = time(nullptr) * NS_PER_SEC;
+    int64_t wallClockTimestampNs = getWallClockNs();
+    int64_t elapsedTimestampNs = getElapsedRealtimeNs();
     char buf[kLineBufferSize];
     char* pch;
     while (!fin.eof()) {
@@ -70,7 +72,8 @@
         pch = strtok(buf, " ");
         uint64_t sysTimeMs = std::stoull(pch);
 
-        auto ptr = make_shared<LogEvent>(android::util::CPU_TIME_PER_UID, timestamp);
+        auto ptr = make_shared<LogEvent>(android::util::CPU_TIME_PER_UID,
+            wallClockTimestampNs, elapsedTimestampNs);
         ptr->write(uid);
         ptr->write(userTimeMs);
         ptr->write(sysTimeMs);
diff --git a/cmds/statsd/src/external/KernelUidCpuActiveTimeReader.cpp b/cmds/statsd/src/external/KernelUidCpuActiveTimeReader.cpp
index 7a2d199..0b545cc 100644
--- a/cmds/statsd/src/external/KernelUidCpuActiveTimeReader.cpp
+++ b/cmds/statsd/src/external/KernelUidCpuActiveTimeReader.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#define DEBUG true  // STOPSHIP if true
+#define DEBUG false  // STOPSHIP if true
 #include "Log.h"
 
 #include <fstream>
@@ -23,6 +23,7 @@
 #include "guardrail/StatsdStats.h"
 #include "logd/LogEvent.h"
 #include "statslog.h"
+#include "stats_log_util.h"
 
 using std::make_shared;
 using std::shared_ptr;
@@ -57,7 +58,9 @@
         return false;
     }
 
-    uint64_t timestamp = time(nullptr) * NS_PER_SEC;
+    int64_t wallClockTimestampNs = getWallClockNs();
+    int64_t elapsedTimestampNs = getElapsedRealtimeNs();
+
     char buf[kLineBufferSize];
     char* pch;
     while (!fin.eof()) {
@@ -70,7 +73,7 @@
         int idx = 0;
         do {
             timeMs = std::stoull(pch);
-            auto ptr = make_shared<LogEvent>(mTagId, timestamp);
+            auto ptr = make_shared<LogEvent>(mTagId, wallClockTimestampNs, elapsedTimestampNs);
             ptr->write(uid);
             ptr->write(idx);
             ptr->write(timeMs);
diff --git a/cmds/statsd/src/external/KernelUidCpuClusterTimeReader.cpp b/cmds/statsd/src/external/KernelUidCpuClusterTimeReader.cpp
index 7426e74..cc80204 100644
--- a/cmds/statsd/src/external/KernelUidCpuClusterTimeReader.cpp
+++ b/cmds/statsd/src/external/KernelUidCpuClusterTimeReader.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#define DEBUG true  // STOPSHIP if true
+#define DEBUG false  // STOPSHIP if true
 #include "Log.h"
 
 #include <fstream>
@@ -22,6 +22,7 @@
 #include "guardrail/StatsdStats.h"
 #include "logd/LogEvent.h"
 #include "statslog.h"
+#include "stats_log_util.h"
 
 using std::make_shared;
 using std::shared_ptr;
@@ -56,7 +57,8 @@
         return false;
     }
 
-    uint64_t timestamp = time(nullptr) * NS_PER_SEC;
+    int64_t wallClockTimestampNs = getWallClockNs();
+    int64_t elapsedTimestampNs = getElapsedRealtimeNs();
     char buf[kLineBufferSize];
     char* pch;
     while (!fin.eof()) {
@@ -69,7 +71,7 @@
         int idx = 0;
         do {
             timeMs = std::stoull(pch);
-            auto ptr = make_shared<LogEvent>(mTagId, timestamp);
+            auto ptr = make_shared<LogEvent>(mTagId, wallClockTimestampNs, elapsedTimestampNs);
             ptr->write(uid);
             ptr->write(idx);
             ptr->write(timeMs);
diff --git a/cmds/statsd/src/external/Perfetto.cpp b/cmds/statsd/src/external/Perfetto.cpp
index 1d8a968..b09d373 100644
--- a/cmds/statsd/src/external/Perfetto.cpp
+++ b/cmds/statsd/src/external/Perfetto.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#define DEBUG false  // STOPSHIP if true
 #include "Log.h"
 
 #include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"  // Alert
@@ -36,7 +37,7 @@
 namespace statsd {
 
 bool CollectPerfettoTraceAndUploadToDropbox(const PerfettoDetails& config) {
-    ALOGD("Starting trace collection through perfetto");
+    VLOG("Starting trace collection through perfetto");
 
     if (!config.has_trace_config()) {
         ALOGE("The perfetto trace config is empty, aborting");
@@ -118,7 +119,7 @@
         return false;
     }
 
-    ALOGD("CollectPerfettoTraceAndUploadToDropbox() succeeded");
+    VLOG("CollectPerfettoTraceAndUploadToDropbox() succeeded");
     return true;
 }
 
diff --git a/cmds/statsd/src/external/ResourceHealthManagerPuller.cpp b/cmds/statsd/src/external/ResourceHealthManagerPuller.cpp
index 72fb5ff..261cb43 100644
--- a/cmds/statsd/src/external/ResourceHealthManagerPuller.cpp
+++ b/cmds/statsd/src/external/ResourceHealthManagerPuller.cpp
@@ -25,6 +25,7 @@
 #include "ResourceHealthManagerPuller.h"
 #include "logd/LogEvent.h"
 #include "statslog.h"
+#include "stats_log_util.h"
 
 using android::hardware::hidl_vec;
 using android::hardware::health::V2_0::get_health_service;
@@ -61,7 +62,8 @@
         return false;
     }
 
-    uint64_t timestamp = time(nullptr) * NS_PER_SEC;
+    int64_t wallClockTimestampNs = getWallClockNs();
+    int64_t elapsedTimestampNs = getElapsedRealtimeNs();
 
     data->clear();
     bool result_success = true;
@@ -72,12 +74,14 @@
             return;
         }
         if (mTagId == android::util::REMAINING_BATTERY_CAPACITY) {
-            auto ptr = make_shared<LogEvent>(android::util::REMAINING_BATTERY_CAPACITY, timestamp);
+            auto ptr = make_shared<LogEvent>(android::util::REMAINING_BATTERY_CAPACITY,
+                wallClockTimestampNs, elapsedTimestampNs);
             ptr->write(v.legacy.batteryChargeCounter);
             ptr->init();
             data->push_back(ptr);
         } else if (mTagId == android::util::FULL_BATTERY_CAPACITY) {
-            auto ptr = make_shared<LogEvent>(android::util::FULL_BATTERY_CAPACITY, timestamp);
+            auto ptr = make_shared<LogEvent>(android::util::FULL_BATTERY_CAPACITY,
+                wallClockTimestampNs, elapsedTimestampNs);
             ptr->write(v.legacy.batteryFullCharge);
             ptr->init();
             data->push_back(ptr);
diff --git a/cmds/statsd/src/external/StatsCompanionServicePuller.cpp b/cmds/statsd/src/external/StatsCompanionServicePuller.cpp
index b955f1c..bd859fd 100644
--- a/cmds/statsd/src/external/StatsCompanionServicePuller.cpp
+++ b/cmds/statsd/src/external/StatsCompanionServicePuller.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#define DEBUG true
+#define DEBUG false
 #include "Log.h"
 
 #include <android/os/IStatsCompanionService.h>
@@ -22,6 +22,7 @@
 #include <private/android_filesystem_config.h>
 #include "StatsCompanionServicePuller.h"
 #include "StatsService.h"
+#include "stats_log_util.h"
 #include "guardrail/StatsdStats.h"
 
 using namespace android;
@@ -53,18 +54,18 @@
             return false;
         }
         data->clear();
-        int timestamp = time(nullptr);
+        int32_t timestampSec = getWallClockSec();
         for (const StatsLogEventWrapper& it : returned_value) {
             log_msg tmp;
             tmp.entry_v1.len = it.bytes.size();
             // Manually set the header size to 28 bytes to match the pushed log events.
             tmp.entry.hdr_size = kLogMsgHeaderSize;
-            tmp.entry_v1.sec = timestamp;
+            tmp.entry_v1.sec = timestampSec;
             // And set the received bytes starting after the 28 bytes reserved for header.
             std::copy(it.bytes.begin(), it.bytes.end(), tmp.buf + kLogMsgHeaderSize);
             data->push_back(make_shared<LogEvent>(tmp));
         }
-        ALOGD("StatsCompanionServicePuller::pull succeeded for %d", mTagId);
+        VLOG("StatsCompanionServicePuller::pull succeeded for %d", mTagId);
         return true;
     } else {
         ALOGW("statsCompanion not found!");
diff --git a/cmds/statsd/src/external/StatsPuller.cpp b/cmds/statsd/src/external/StatsPuller.cpp
index da14434..9513cc5 100644
--- a/cmds/statsd/src/external/StatsPuller.cpp
+++ b/cmds/statsd/src/external/StatsPuller.cpp
@@ -19,6 +19,8 @@
 
 #include "StatsPuller.h"
 #include "guardrail/StatsdStats.h"
+#include "puller_util.h"
+#include "stats_log_util.h"
 
 namespace android {
 namespace os {
@@ -26,6 +28,9 @@
 
 using std::lock_guard;
 
+sp<UidMap> StatsPuller::mUidMap = nullptr;
+void StatsPuller::SetUidMap(const sp<UidMap>& uidMap) { mUidMap = uidMap; }
+
 // ValueMetric has a minimum bucket size of 10min so that we don't pull too frequently
 StatsPuller::StatsPuller(const int tagId)
     : mTagId(tagId) {
@@ -40,7 +45,7 @@
 bool StatsPuller::Pull(std::vector<std::shared_ptr<LogEvent>>* data) {
     lock_guard<std::mutex> lock(mLock);
     StatsdStats::getInstance().notePull(mTagId);
-    long curTime = time(nullptr);
+    long curTime = getElapsedRealtimeSec();
     if (curTime - mLastPullTimeSec < mCoolDownSec) {
         (*data) = mCachedData;
         StatsdStats::getInstance().notePullFromCache(mTagId);
@@ -54,14 +59,30 @@
     mLastPullTimeSec = curTime;
     bool ret = PullInternal(&mCachedData);
     if (ret) {
-        (*data) = mCachedData;
+      mergeIsolatedUidsToHostUid(mCachedData, mUidMap, mTagId);
+      (*data) = mCachedData;
     }
     return ret;
 }
 
-void StatsPuller::ClearCache() {
+int StatsPuller::ForceClearCache() {
+    return clearCache();
+}
+
+int StatsPuller::clearCache() {
     lock_guard<std::mutex> lock(mLock);
+    int ret = mCachedData.size();
     mCachedData.clear();
+    mLastPullTimeSec = 0;
+    return ret;
+}
+
+int StatsPuller::ClearCacheIfNecessary(long timestampSec) {
+    if (timestampSec - mLastPullTimeSec > mCoolDownSec) {
+        return clearCache();
+    } else {
+        return 0;
+    }
 }
 
 }  // namespace statsd
diff --git a/cmds/statsd/src/external/StatsPuller.h b/cmds/statsd/src/external/StatsPuller.h
index bc7c45f..82a8611 100644
--- a/cmds/statsd/src/external/StatsPuller.h
+++ b/cmds/statsd/src/external/StatsPuller.h
@@ -18,11 +18,14 @@
 
 #include <android/os/StatsLogEventWrapper.h>
 #include <utils/String16.h>
+#include <utils/RefBase.h>
 #include <mutex>
 #include <vector>
+#include "packages/UidMap.h"
 
-#include "logd/LogEvent.h"
 #include "guardrail/StatsdStats.h"
+#include "logd/LogEvent.h"
+#include "puller_util.h"
 
 using android::os::StatsLogEventWrapper;
 
@@ -30,7 +33,7 @@
 namespace os {
 namespace statsd {
 
-class StatsPuller {
+class StatsPuller : public virtual RefBase {
 public:
     StatsPuller(const int tagId);
 
@@ -38,9 +41,15 @@
 
     bool Pull(std::vector<std::shared_ptr<LogEvent>>* data);
 
-    void ClearCache();
+    // Clear cache immediately
+    int ForceClearCache();
 
-protected:
+    // Clear cache if elapsed time is more than cooldown time
+    int ClearCacheIfNecessary(long timestampSec);
+
+    static void SetUidMap(const sp<UidMap>& uidMap);
+
+   protected:
     // The atom tag id this puller pulls
     const int mTagId;
 
@@ -61,6 +70,10 @@
     std::vector<std::shared_ptr<LogEvent>> mCachedData;
 
     long mLastPullTimeSec;
+
+    int clearCache();
+
+    static sp<UidMap> mUidMap;
 };
 
 }  // namespace statsd
diff --git a/cmds/statsd/src/external/StatsPullerManager.h b/cmds/statsd/src/external/StatsPullerManager.h
index 4826d96..0dee342 100644
--- a/cmds/statsd/src/external/StatsPullerManager.h
+++ b/cmds/statsd/src/external/StatsPullerManager.h
@@ -54,8 +54,12 @@
         mPullerManager.SetTimeBaseSec(timeBaseSec);
     }
 
-    void ClearPullerCache() {
-        mPullerManager.ClearPullerCache();
+    int ForceClearPullerCache() {
+        return mPullerManager.ForceClearPullerCache();
+    }
+
+    int ClearPullerCacheIfNecessary(long timestampSec) {
+        return mPullerManager.ClearPullerCacheIfNecessary(timestampSec);
     }
 
  private:
diff --git a/cmds/statsd/src/external/StatsPullerManagerImpl.cpp b/cmds/statsd/src/external/StatsPullerManagerImpl.cpp
index 71b0abe..bee9939 100644
--- a/cmds/statsd/src/external/StatsPullerManagerImpl.cpp
+++ b/cmds/statsd/src/external/StatsPullerManagerImpl.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#define DEBUG true
+#define DEBUG false
 #include "Log.h"
 
 #include <android/os/IStatsCompanionService.h>
@@ -24,12 +24,16 @@
 #include "CpuTimePerUidFreqPuller.h"
 #include "CpuTimePerUidPuller.h"
 #include "ResourceHealthManagerPuller.h"
+#include "KernelUidCpuActiveTimeReader.h"
+#include "KernelUidCpuClusterTimeReader.h"
+#include "SubsystemSleepStatePuller.h"
 #include "StatsCompanionServicePuller.h"
 #include "StatsPullerManagerImpl.h"
 #include "StatsService.h"
 #include "SubsystemSleepStatePuller.h"
 #include "logd/LogEvent.h"
 #include "statslog.h"
+#include "stats_log_util.h"
 
 #include <iostream>
 
@@ -44,62 +48,92 @@
 namespace os {
 namespace statsd {
 
+const std::map<int, PullAtomInfo> StatsPullerManagerImpl::kAllPullAtomInfo = {
+        // wifi_bytes_transfer
+        {android::util::WIFI_BYTES_TRANSFER,
+         {{2, 3, 4, 5},
+          {},
+          1,
+          new StatsCompanionServicePuller(android::util::WIFI_BYTES_TRANSFER)}},
+        // wifi_bytes_transfer_by_fg_bg
+        {android::util::WIFI_BYTES_TRANSFER_BY_FG_BG,
+         {{3, 4, 5, 6},
+          {2},
+          1,
+          new StatsCompanionServicePuller(android::util::WIFI_BYTES_TRANSFER_BY_FG_BG)}},
+        // mobile_bytes_transfer
+        {android::util::MOBILE_BYTES_TRANSFER,
+         {{2, 3, 4, 5},
+          {},
+          1,
+          new StatsCompanionServicePuller(android::util::MOBILE_BYTES_TRANSFER)}},
+        // mobile_bytes_transfer_by_fg_bg
+        {android::util::MOBILE_BYTES_TRANSFER_BY_FG_BG,
+         {{3, 4, 5, 6},
+          {2},
+          1,
+          new StatsCompanionServicePuller(android::util::MOBILE_BYTES_TRANSFER_BY_FG_BG)}},
+        // bluetooth_bytes_transfer
+        {android::util::BLUETOOTH_BYTES_TRANSFER,
+         {{2, 3}, {}, 1, new StatsCompanionServicePuller(android::util::BLUETOOTH_BYTES_TRANSFER)}},
+        // kernel_wakelock
+        {android::util::KERNEL_WAKELOCK,
+         {{}, {}, 1, new StatsCompanionServicePuller(android::util::KERNEL_WAKELOCK)}},
+        // subsystem_sleep_state
+        {android::util::SUBSYSTEM_SLEEP_STATE, {{}, {}, 1, new SubsystemSleepStatePuller()}},
+        // cpu_time_per_freq
+        {android::util::CPU_TIME_PER_FREQ,
+         {{3}, {2}, 1, new StatsCompanionServicePuller(android::util::CPU_TIME_PER_FREQ)}},
+        // cpu_time_per_uid
+        {android::util::CPU_TIME_PER_UID, {{2, 3}, {}, 1, new CpuTimePerUidPuller()}},
+        // cpu_time_per_uid_freq
+        {android::util::CPU_TIME_PER_UID_FREQ, {{3}, {2}, 1, new CpuTimePerUidFreqPuller()}},
+        // wifi_activity_energy_info
+        {android::util::WIFI_ACTIVITY_ENERGY_INFO,
+         {{}, {}, 1, new StatsCompanionServicePuller(android::util::WIFI_ACTIVITY_ENERGY_INFO)}},
+        // modem_activity_info
+        {android::util::MODEM_ACTIVITY_INFO,
+         {{}, {}, 1, new StatsCompanionServicePuller(android::util::MODEM_ACTIVITY_INFO)}},
+        // bluetooth_activity_info
+        {android::util::BLUETOOTH_ACTIVITY_INFO,
+         {{}, {}, 1, new StatsCompanionServicePuller(android::util::BLUETOOTH_ACTIVITY_INFO)}},
+        // system_elapsed_realtime
+        {android::util::SYSTEM_ELAPSED_REALTIME,
+         {{}, {}, 1, new StatsCompanionServicePuller(android::util::SYSTEM_ELAPSED_REALTIME)}},
+        // system_uptime
+        {android::util::SYSTEM_UPTIME,
+         {{}, {}, 1, new StatsCompanionServicePuller(android::util::SYSTEM_UPTIME)}},
+        // cpu_active_time
+        {android::util::CPU_ACTIVE_TIME, {{3}, {2}, 1, new KernelUidCpuActiveTimeReader()}},
+        // cpu_cluster_time
+        {android::util::CPU_CLUSTER_TIME, {{3}, {2}, 1, new KernelUidCpuClusterTimeReader()}},
+        // disk_space
+        {android::util::DISK_SPACE,
+         {{}, {}, 1, new StatsCompanionServicePuller(android::util::DISK_SPACE)}},
+        // remaining_battery_capacity
+        {android::util::REMAINING_BATTERY_CAPACITY,
+         {{}, {}, 1, new ResourceHealthManagerPuller(android::util::REMAINING_BATTERY_CAPACITY)}},
+        // full_battery_capacity
+        {android::util::FULL_BATTERY_CAPACITY,
+         {{}, {}, 1, new ResourceHealthManagerPuller(android::util::FULL_BATTERY_CAPACITY)}},
+        // process_memory_state
+        {android::util::PROCESS_MEMORY_STATE,
+         {{4,5,6,7,8}, {2,3}, 0, new StatsCompanionServicePuller(android::util::PROCESS_MEMORY_STATE)}}};
+
 StatsPullerManagerImpl::StatsPullerManagerImpl()
     : mCurrentPullingInterval(LONG_MAX) {
-    mPullers.insert({android::util::KERNEL_WAKELOCK,
-                     make_shared<StatsCompanionServicePuller>(android::util::KERNEL_WAKELOCK)});
-    mPullers.insert({android::util::WIFI_BYTES_TRANSFER,
-                     make_shared<StatsCompanionServicePuller>(android::util::WIFI_BYTES_TRANSFER)});
-    mPullers.insert(
-            {android::util::MOBILE_BYTES_TRANSFER,
-             make_shared<StatsCompanionServicePuller>(android::util::MOBILE_BYTES_TRANSFER)});
-    mPullers.insert({android::util::WIFI_BYTES_TRANSFER_BY_FG_BG,
-                     make_shared<StatsCompanionServicePuller>(
-                             android::util::WIFI_BYTES_TRANSFER_BY_FG_BG)});
-    mPullers.insert({android::util::MOBILE_BYTES_TRANSFER_BY_FG_BG,
-                     make_shared<StatsCompanionServicePuller>(
-                             android::util::MOBILE_BYTES_TRANSFER_BY_FG_BG)});
-    mPullers.insert(
-            {android::util::SUBSYSTEM_SLEEP_STATE,
-             make_shared<SubsystemSleepStatePuller>()});
-    mPullers.insert({android::util::CPU_TIME_PER_FREQ, make_shared<StatsCompanionServicePuller>(android::util::CPU_TIME_PER_FREQ)});
-    mPullers.insert({android::util::CPU_TIME_PER_UID, make_shared<CpuTimePerUidPuller>()});
-    mPullers.insert({android::util::CPU_TIME_PER_UID_FREQ, make_shared<CpuTimePerUidFreqPuller>()});
-    mPullers.insert(
-            {android::util::SYSTEM_ELAPSED_REALTIME,
-             make_shared<StatsCompanionServicePuller>(android::util::SYSTEM_ELAPSED_REALTIME)});
-    mPullers.insert({android::util::SYSTEM_UPTIME,
-                     make_shared<StatsCompanionServicePuller>(android::util::SYSTEM_UPTIME)});
-    mPullers.insert({android::util::DISK_SPACE,
-                     make_shared<StatsCompanionServicePuller>(android::util::DISK_SPACE)});
-    mPullers.insert(
-            {android::util::BLUETOOTH_ACTIVITY_INFO,
-             make_shared<StatsCompanionServicePuller>(android::util::BLUETOOTH_ACTIVITY_INFO)});
-
-    mPullers.insert(
-            {android::util::BLUETOOTH_BYTES_TRANSFER,
-             make_shared<StatsCompanionServicePuller>(android::util::BLUETOOTH_BYTES_TRANSFER)});
-    mPullers.insert(
-            {android::util::WIFI_ACTIVITY_ENERGY_INFO,
-             make_shared<StatsCompanionServicePuller>(android::util::WIFI_ACTIVITY_ENERGY_INFO)});
-    mPullers.insert({android::util::MODEM_ACTIVITY_INFO,
-                     make_shared<StatsCompanionServicePuller>(android::util::MODEM_ACTIVITY_INFO)});
-    mPullers.insert({android::util::REMAINING_BATTERY_CAPACITY,
-                     make_shared<ResourceHealthManagerPuller>(android::util::REMAINING_BATTERY_CAPACITY)});
-    mPullers.insert({android::util::FULL_BATTERY_CAPACITY,
-                     make_shared<ResourceHealthManagerPuller>(android::util::FULL_BATTERY_CAPACITY)});
     mStatsCompanionService = StatsService::getStatsCompanionService();
 }
 
 bool StatsPullerManagerImpl::Pull(int tagId, vector<shared_ptr<LogEvent>>* data) {
-    if (DEBUG) ALOGD("Initiating pulling %d", tagId);
+    VLOG("Initiating pulling %d", tagId);
 
-    if (mPullers.find(tagId) != mPullers.end()) {
-        bool ret = mPullers.find(tagId)->second->Pull(data);
-        ALOGD("pulled %d items", (int)data->size());
+    if (kAllPullAtomInfo.find(tagId) != kAllPullAtomInfo.end()) {
+        bool ret = kAllPullAtomInfo.find(tagId)->second.puller->Pull(data);
+        VLOG("pulled %d items", (int)data->size());
         return ret;
     } else {
-        ALOGD("Unknown tagId %d", tagId);
+        VLOG("Unknown tagId %d", tagId);
         return false;  // Return early since we don't know what to pull.
     }
 }
@@ -110,7 +144,7 @@
 }
 
 bool StatsPullerManagerImpl::PullerForMatcherExists(int tagId) const {
-    return mPullers.find(tagId) != mPullers.end();
+    return kAllPullAtomInfo.find(tagId) != kAllPullAtomInfo.end();
 }
 
 void StatsPullerManagerImpl::RegisterReceiver(int tagId, wp<PullDataReceiver> receiver,
@@ -135,8 +169,9 @@
     if (roundedIntervalMs < mCurrentPullingInterval) {
         VLOG("Updating pulling interval %ld", intervalMs);
         mCurrentPullingInterval = roundedIntervalMs;
-        long currentTimeMs = time(nullptr) * 1000;
-        long nextAlarmTimeMs = currentTimeMs + mCurrentPullingInterval - (currentTimeMs - mTimeBaseSec * 1000) % mCurrentPullingInterval;
+        long currentTimeMs = getElapsedRealtimeMillis();
+        long nextAlarmTimeMs = currentTimeMs + mCurrentPullingInterval -
+            (currentTimeMs - mTimeBaseSec * 1000) % mCurrentPullingInterval;
         if (mStatsCompanionService != nullptr) {
             mStatsCompanionService->setPullingAlarms(nextAlarmTimeMs, mCurrentPullingInterval);
         } else {
@@ -165,7 +200,7 @@
 void StatsPullerManagerImpl::OnAlarmFired() {
     AutoMutex _l(mReceiversLock);
 
-    uint64_t currentTimeMs = time(nullptr) /60 * 60 * 1000;
+    uint64_t currentTimeMs = getElapsedRealtimeMillis();
 
     vector<pair<int, vector<ReceiverInfo*>>> needToPull =
             vector<pair<int, vector<ReceiverInfo*>>>();
@@ -199,10 +234,20 @@
     }
 }
 
-void StatsPullerManagerImpl::ClearPullerCache() {
-    for (auto puller : mPullers) {
-        puller.second->ClearCache();
+int StatsPullerManagerImpl::ForceClearPullerCache() {
+    int totalCleared = 0;
+    for (const auto& pulledAtom : kAllPullAtomInfo) {
+        totalCleared += pulledAtom.second.puller->ForceClearCache();
     }
+    return totalCleared;
+}
+
+int StatsPullerManagerImpl::ClearPullerCacheIfNecessary(long timestampSec) {
+    int totalCleared = 0;
+    for (const auto& pulledAtom : kAllPullAtomInfo) {
+        totalCleared += pulledAtom.second.puller->ClearCacheIfNecessary(timestampSec);
+    }
+    return totalCleared;
 }
 
 }  // namespace statsd
diff --git a/cmds/statsd/src/external/StatsPullerManagerImpl.h b/cmds/statsd/src/external/StatsPullerManagerImpl.h
index fba3ade..76a4c14 100644
--- a/cmds/statsd/src/external/StatsPullerManagerImpl.h
+++ b/cmds/statsd/src/external/StatsPullerManagerImpl.h
@@ -32,6 +32,20 @@
 namespace os {
 namespace statsd {
 
+typedef struct {
+  // The field numbers of the fields that need to be summed when merging
+  // isolated uid with host uid.
+  std::vector<int> additiveFields;
+  // The field numbers of the fields that can't be merged when merging
+  // data belong to isolated uid and host uid.
+  std::vector<int> nonAdditiveFields;
+  // How long should the puller wait before doing an actual pull again. Default
+  // 1 sec. Set this to 0 if this is handled elsewhere.
+  long coolDownSec = 1;
+  // The actual puller
+  sp<StatsPuller> puller;
+} PullAtomInfo;
+
 class StatsPullerManagerImpl : public virtual RefBase {
 public:
     static StatsPullerManagerImpl& GetInstance();
@@ -49,9 +63,13 @@
 
     void SetTimeBaseSec(long timeBaseSec) {mTimeBaseSec = timeBaseSec;};
 
-    void ClearPullerCache();
+    int ForceClearPullerCache();
 
-private:
+    int ClearPullerCacheIfNecessary(long timestampSec);
+
+    const static std::map<int, PullAtomInfo> kAllPullAtomInfo;
+
+   private:
     StatsPullerManagerImpl();
 
     // use this to update alarm
@@ -59,9 +77,6 @@
 
     sp<IStatsCompanionService> get_stats_companion_service();
 
-    // mapping from simple matcher tagId to puller
-    std::map<int, std::shared_ptr<StatsPuller>> mPullers;
-
     typedef struct {
         // pull_interval_sec : last_pull_time_sec
         std::pair<uint64_t, uint64_t> timeInfo;
@@ -79,8 +94,6 @@
     // bucket size. All pulled metrics start pulling based on this time, so that they can be
     // correctly attributed to the correct buckets.
     long mTimeBaseSec;
-
-    LogEvent parse_pulled_data(String16 data);
 };
 
 }  // namespace statsd
diff --git a/cmds/statsd/src/external/SubsystemSleepStatePuller.cpp b/cmds/statsd/src/external/SubsystemSleepStatePuller.cpp
index 6d12e25..4501b64 100644
--- a/cmds/statsd/src/external/SubsystemSleepStatePuller.cpp
+++ b/cmds/statsd/src/external/SubsystemSleepStatePuller.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#define DEBUG true  // STOPSHIP if true
+#define DEBUG false  // STOPSHIP if true
 #include "Log.h"
 
 #include <android/hardware/power/1.0/IPower.h>
@@ -36,6 +36,7 @@
 #include "SubsystemSleepStatePuller.h"
 #include "logd/LogEvent.h"
 #include "statslog.h"
+#include "stats_log_util.h"
 
 using android::hardware::hidl_vec;
 using android::hardware::power::V1_0::IPower;
@@ -84,21 +85,24 @@
         return false;
     }
 
-    uint64_t timestamp = time(nullptr) * NS_PER_SEC;
+    int64_t wallClockTimestampNs = getWallClockNs();
+    int64_t elapsedTimestampNs = getElapsedRealtimeNs();
 
     data->clear();
 
     Return<void> ret;
         ret = gPowerHalV1_0->getPlatformLowPowerStats(
-                [&data, timestamp](hidl_vec<PowerStatePlatformSleepState> states, Status status) {
+                [&data, wallClockTimestampNs, elapsedTimestampNs](hidl_vec<PowerStatePlatformSleepState> states, Status status) {
                     if (status != Status::SUCCESS) return;
 
                     for (size_t i = 0; i < states.size(); i++) {
                         const PowerStatePlatformSleepState& state = states[i];
 
-                        auto statePtr = make_shared<LogEvent>(android::util::SUBSYSTEM_SLEEP_STATE,
-                                                              timestamp);
+                        auto statePtr = make_shared<LogEvent>(
+                            android::util::SUBSYSTEM_SLEEP_STATE,
+                            wallClockTimestampNs, elapsedTimestampNs);
                         statePtr->write(state.name);
+                        statePtr->write("");
                         statePtr->write(state.totalTransitions);
                         statePtr->write(state.residencyInMsecSinceBoot);
                         statePtr->init();
@@ -108,9 +112,11 @@
                              (long long)state.totalTransitions,
                              state.supportedOnlyInSuspend ? 1 : 0);
                         for (auto voter : state.voters) {
-                            auto voterPtr = make_shared<LogEvent>(android::util::SUBSYSTEM_SLEEP_STATE,
-                                                                  timestamp);
-                            voterPtr->write((std::string)state.name + "." + (std::string)voter.name);
+                            auto voterPtr = make_shared<LogEvent>(
+                                android::util::SUBSYSTEM_SLEEP_STATE,
+                                wallClockTimestampNs, elapsedTimestampNs);
+                            voterPtr->write(state.name);
+                            voterPtr->write(voter.name);
                             voterPtr->write(voter.totalNumberOfTimesVotedSinceBoot);
                             voterPtr->write(voter.totalTimeInMsecVotedForSinceBoot);
                             voterPtr->init();
@@ -133,7 +139,7 @@
                 android::hardware::power::V1_1::IPower::castFrom(gPowerHalV1_0);
         if (gPowerHal_1_1 != nullptr) {
             ret = gPowerHal_1_1->getSubsystemLowPowerStats(
-                    [&data, timestamp](hidl_vec<PowerStateSubsystem> subsystems, Status status) {
+                    [&data, wallClockTimestampNs, elapsedTimestampNs](hidl_vec<PowerStateSubsystem> subsystems, Status status) {
                         if (status != Status::SUCCESS) return;
 
                         if (subsystems.size() > 0) {
@@ -143,8 +149,10 @@
                                     const PowerStateSubsystemSleepState& state =
                                             subsystem.states[j];
                                     auto subsystemStatePtr = make_shared<LogEvent>(
-                                        android::util::SUBSYSTEM_SLEEP_STATE, timestamp);
-                                    subsystemStatePtr->write((std::string)subsystem.name + "." + (std::string)state.name);
+                                        android::util::SUBSYSTEM_SLEEP_STATE,
+                                        wallClockTimestampNs, elapsedTimestampNs);
+                                    subsystemStatePtr->write(subsystem.name);
+                                    subsystemStatePtr->write(state.name);
                                     subsystemStatePtr->write(state.totalTransitions);
                                     subsystemStatePtr->write(state.residencyInMsecSinceBoot);
                                     subsystemStatePtr->init();
diff --git a/cmds/statsd/src/external/puller_util.cpp b/cmds/statsd/src/external/puller_util.cpp
new file mode 100644
index 0000000..0b0c5c4
--- /dev/null
+++ b/cmds/statsd/src/external/puller_util.cpp
@@ -0,0 +1,166 @@
+/*
+ * 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  // STOPSHIP if true
+#include "Log.h"
+
+#include "StatsPullerManagerImpl.h"
+#include "puller_util.h"
+#include "statslog.h"
+
+namespace android {
+namespace os {
+namespace statsd {
+
+using std::map;
+using std::shared_ptr;
+using std::vector;
+
+namespace {
+bool shouldMerge(shared_ptr<LogEvent>& lhs, shared_ptr<LogEvent>& rhs,
+                 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;
+}
+
+// merge rhs to lhs
+// 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;
+}
+
+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;
+        }
+    }
+    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;
+    }
+    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
+}  // namespace os
+}  // namespace android
diff --git a/cmds/statsd/src/external/puller_util.h b/cmds/statsd/src/external/puller_util.h
new file mode 100644
index 0000000..fd4a4a2
--- /dev/null
+++ b/cmds/statsd/src/external/puller_util.h
@@ -0,0 +1,33 @@
+/*
+ * 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 <vector>
+#include "StatsPuller.h"
+#include "logd/LogEvent.h"
+#include "packages/UidMap.h"
+
+namespace android {
+namespace os {
+namespace statsd {
+
+void mergeIsolatedUidsToHostUid(std::vector<std::shared_ptr<LogEvent>>& data,
+                                const sp<UidMap>& uidMap, int tagId);
+
+}  // namespace statsd
+}  // namespace os
+}  // namespace android
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/guardrail/MemoryLeakTrackUtil.cpp b/cmds/statsd/src/guardrail/MemoryLeakTrackUtil.cpp
index e1947c4..01c7587 100644
--- a/cmds/statsd/src/guardrail/MemoryLeakTrackUtil.cpp
+++ b/cmds/statsd/src/guardrail/MemoryLeakTrackUtil.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#define DEBUG true  // STOPSHIP if true
+#define DEBUG false  // STOPSHIP if true
 #include "Log.h"
 
 #include <sstream>
@@ -63,7 +63,7 @@
     size_t count;
     if (info == nullptr || overallSize == 0 || infoSize == 0 ||
         (count = overallSize / infoSize) == 0) {
-        ALOGD("no malloc info, libc.debug.malloc.program property should be set");
+        VLOG("no malloc info, libc.debug.malloc.program property should be set");
         return std::string();
     }
 
diff --git a/cmds/statsd/src/guardrail/StatsdStats.cpp b/cmds/statsd/src/guardrail/StatsdStats.cpp
index 77f5456..66cb1d0 100644
--- a/cmds/statsd/src/guardrail/StatsdStats.cpp
+++ b/cmds/statsd/src/guardrail/StatsdStats.cpp
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#define DEBUG true  // STOPSHIP if true
+#define DEBUG false  // STOPSHIP if true
 #include "Log.h"
 
 #include "StatsdStats.h"
@@ -45,18 +45,9 @@
 const int FIELD_ID_ATOM_STATS = 7;
 const int FIELD_ID_UIDMAP_STATS = 8;
 const int FIELD_ID_ANOMALY_ALARM_STATS = 9;
-const int FIELD_ID_PULLED_ATOM_STATS = 10;
+// const int FIELD_ID_PULLED_ATOM_STATS = 10; // The proto is written in stats_log_util.cpp
 const int FIELD_ID_LOGGER_ERROR_STATS = 11;
 
-const int FIELD_ID_MATCHER_STATS_NAME = 1;
-const int FIELD_ID_MATCHER_STATS_COUNT = 2;
-
-const int FIELD_ID_CONDITION_STATS_NAME = 1;
-const int FIELD_ID_CONDITION_STATS_COUNT = 2;
-
-const int FIELD_ID_METRIC_STATS_NAME = 1;
-const int FIELD_ID_METRIC_STATS_COUNT = 2;
-
 const int FIELD_ID_ATOM_STATS_TAG = 1;
 const int FIELD_ID_ATOM_STATS_COUNT = 2;
 
@@ -80,7 +71,7 @@
 // TODO: add stats for pulled atoms.
 StatsdStats::StatsdStats() {
     mPushedAtomStats.resize(android::util::kMaxPushedAtomId + 1);
-    mStartTimeSec = time(nullptr);
+    mStartTimeSec = getWallClockSec();
 }
 
 StatsdStats& StatsdStats::getInstance() {
@@ -99,7 +90,7 @@
 void StatsdStats::noteConfigReceived(const ConfigKey& key, int metricsCount, int conditionsCount,
                                      int matchersCount, int alertsCount, bool isValid) {
     lock_guard<std::mutex> lock(mLock);
-    int32_t nowTimeSec = time(nullptr);
+    int32_t nowTimeSec = getWallClockSec();
 
     // If there is an existing config for the same key, icebox the old config.
     noteConfigRemovedInternalLocked(key);
@@ -125,7 +116,7 @@
 void StatsdStats::noteConfigRemovedInternalLocked(const ConfigKey& key) {
     auto it = mConfigStats.find(key);
     if (it != mConfigStats.end()) {
-        int32_t nowTimeSec = time(nullptr);
+        int32_t nowTimeSec = getWallClockSec();
         it->second.set_deletion_time_sec(nowTimeSec);
         // Add condition stats, metrics stats, matcher stats, alert stats
         addSubStatsToConfigLocked(key, it->second);
@@ -145,7 +136,7 @@
 }
 
 void StatsdStats::noteBroadcastSent(const ConfigKey& key) {
-    noteBroadcastSent(key, time(nullptr));
+    noteBroadcastSent(key, getWallClockSec());
 }
 
 void StatsdStats::noteBroadcastSent(const ConfigKey& key, int32_t timeSec) {
@@ -164,7 +155,7 @@
 }
 
 void StatsdStats::noteDataDropped(const ConfigKey& key) {
-    noteDataDropped(key, time(nullptr));
+    noteDataDropped(key, getWallClockSec());
 }
 
 void StatsdStats::noteDataDropped(const ConfigKey& key, int32_t timeSec) {
@@ -183,7 +174,7 @@
 }
 
 void StatsdStats::noteMetricsReportSent(const ConfigKey& key) {
-    noteMetricsReportSent(key, time(nullptr));
+    noteMetricsReportSent(key, getWallClockSec());
 }
 
 void StatsdStats::noteMetricsReportSent(const ConfigKey& key, int32_t timeSec) {
@@ -275,10 +266,6 @@
 void StatsdStats::noteAtomLogged(int atomId, int32_t timeSec) {
     lock_guard<std::mutex> lock(mLock);
 
-    if (timeSec < mStartTimeSec) {
-        return;
-    }
-
     if (atomId > android::util::kMaxPushedAtomId) {
         ALOGW("not interested in atom %d", atomId);
         return;
@@ -293,7 +280,7 @@
     if (mLoggerErrors.size() == kMaxLoggerErrors) {
         mLoggerErrors.pop_front();
     }
-    mLoggerErrors.push_back(std::make_pair(time(nullptr), error));
+    mLoggerErrors.push_back(std::make_pair(getWallClockSec(), error));
 }
 
 void StatsdStats::reset() {
@@ -303,7 +290,7 @@
 
 void StatsdStats::resetInternalLocked() {
     // Reset the historical data, but keep the active ConfigStats
-    mStartTimeSec = time(nullptr);
+    mStartTimeSec = getWallClockSec();
     mIceBox.clear();
     mConditionStats.clear();
     mMetricsStats.clear();
@@ -495,7 +482,7 @@
 
     ProtoOutputStream proto;
     proto.write(FIELD_TYPE_INT32 | FIELD_ID_BEGIN_TIME, mStartTimeSec);
-    proto.write(FIELD_TYPE_INT32 | FIELD_ID_END_TIME, (int32_t)time(nullptr));
+    proto.write(FIELD_TYPE_INT32 | FIELD_ID_END_TIME, (int32_t)getWallClockSec());
 
     for (const auto& configStats : mIceBox) {
         const int numBytes = configStats.ByteSize();
diff --git a/cmds/statsd/src/guardrail/StatsdStats.h b/cmds/statsd/src/guardrail/StatsdStats.h
index 1f4bfa6..7baa5e5 100644
--- a/cmds/statsd/src/guardrail/StatsdStats.h
+++ b/cmds/statsd/src/guardrail/StatsdStats.h
@@ -42,6 +42,7 @@
     const static int kDimensionKeySizeHardLimit = 500;
 
     const static int kMaxConfigCount = 10;
+    const static int kMaxAlertCountPerConfig = 100;
     const static int kMaxConditionCountPerConfig = 200;
     const static int kMaxMetricCountPerConfig = 300;
     const static int kMaxMatcherCountPerConfig = 500;
@@ -85,6 +86,9 @@
     // Maximum size of all files that can be written to stats directory on disk.
     static const int kMaxFileSize = 50 * 1024 * 1024;
 
+    // How long to try to clear puller cache from last time
+    static const long kPullerCacheClearIntervalSec = 1;
+
     /**
      * Report a new config has been received and report the static stats about the config.
      *
diff --git a/cmds/statsd/src/logd/LogEvent.cpp b/cmds/statsd/src/logd/LogEvent.cpp
index 1dcd853..f07fc66 100644
--- a/cmds/statsd/src/logd/LogEvent.cpp
+++ b/cmds/statsd/src/logd/LogEvent.cpp
@@ -14,16 +14,11 @@
  * limitations under the License.
  */
 
-#define DEBUG true  // STOPSHIP if true
+#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 {
@@ -38,7 +33,7 @@
 LogEvent::LogEvent(log_msg& msg) {
     mContext =
             create_android_log_parser(msg.msg() + sizeof(uint32_t), msg.len() - sizeof(uint32_t));
-    mTimestampNs = msg.entry_v1.sec * NS_PER_SEC + msg.entry_v1.nsec;
+    mLogdTimestampNs = msg.entry_v1.sec * NS_PER_SEC + msg.entry_v1.nsec;
     mLogUid = msg.entry_v4.uid;
     init(mContext);
     if (mContext) {
@@ -47,12 +42,24 @@
     }
 }
 
-LogEvent::LogEvent(int32_t tagId, uint64_t timestampNs) {
-    mTimestampNs = timestampNs;
+LogEvent::LogEvent(int32_t tagId, int64_t wallClockTimestampNs, int64_t elapsedTimestampNs) {
+    mLogdTimestampNs = wallClockTimestampNs;
     mTagId = tagId;
     mLogUid = 0;
     mContext = create_android_logger(1937006964); // the event tag shared by all stats logs
     if (mContext) {
+        android_log_write_int64(mContext, elapsedTimestampNs);
+        android_log_write_int32(mContext, tagId);
+    }
+}
+
+LogEvent::LogEvent(int32_t tagId, int64_t timestampNs) {
+    mLogdTimestampNs = timestampNs;
+    mTagId = tagId;
+    mLogUid = 0;
+    mContext = create_android_logger(1937006964); // the event tag shared by all stats logs
+    if (mContext) {
+        android_log_write_int64(mContext, timestampNs);
         android_log_write_int32(mContext, tagId);
     }
 }
@@ -152,9 +159,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,103 +167,104 @@
     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();
+    int depth = -1;
+    int pos[] = {1, 1, 1};
     do {
         elem = android_log_read_next(context);
         switch ((int)elem.type) {
             case EVENT_TYPE_INT:
-                // elem at [0] is EVENT_TYPE_LIST, [1] is the tag id.
-                if (i == 1) {
+                // elem at [0] is EVENT_TYPE_LIST, [1] is the timestamp, [2] is tag id.
+                if (i == 2) {
                     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 */);
+                    if (depth < 0 || depth > 2) {
+                        return;
                     }
-                    seenListStart++;
-                    if (seenListStart >= 3) {
+
+                    mValues.push_back(
+                            FieldValue(Field(mTagId, pos, depth), Value((int32_t)elem.data.int32)));
+
+                    pos[depth]++;
+                }
+                break;
+            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 (i == 1) {
+                    mElapsedTimestampNs = elem.data.int64;
+                } else {
+                    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:
-                seenListStart--;
-                if (seenListStart == 0) {
-                    atomField->clear_position_index();
-                } else {
-                    if (atomField->child_size() > 0) {
-                       atomField->mutable_child(0)->clear_field();
+            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,140 +275,117 @@
 }
 
 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() == LONG) {
+                return value.mValue.long_value;
+            } else 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 {
+    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 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);
+    result << "{ " << mLogdTimestampNs << " "  << mElapsedTimestampNs << " (" << mTagId << ")";
+    for (const auto& value : mValues) {
+        result << StringPrintf("%#x", value.mField.getField());
         result << "->";
-        result << DimensionsValueToString(itr.second);
+        result << value.mValue.toString();
         result << " ";
     }
     result << " }";
@@ -411,7 +393,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 eb2c008..b3084d5 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.
  */
@@ -51,14 +47,18 @@
     /**
      * Constructs a LogEvent with synthetic data for testing. Must call init() before reading.
      */
-    explicit LogEvent(int32_t tagId, uint64_t timestampNs);
+    explicit LogEvent(int32_t tagId, int64_t wallClockTimestampNs, int64_t elapsedTimestampNs);
+
+    // For testing. The timestamp is used as both elapsed real time and logd timestamp.
+    explicit LogEvent(int32_t tagId, int64_t timestampNs);
 
     ~LogEvent();
 
     /**
      * Get the timestamp associated with this event.
      */
-    inline uint64_t GetTimestampNs() const { return mTimestampNs; }
+    inline int64_t GetLogdTimestampNs() const { return mLogdTimestampNs; }
+    inline int64_t GetElapsedTimestampNs() const { return mElapsedTimestampNs; }
 
     /**
      * Get the tag for this event.
@@ -76,23 +76,11 @@
      * Returns BAD_TYPE if the index is available but the data is the wrong type.
      */
     int64_t GetLong(size_t key, status_t* err) const;
+    int GetInt(size_t key, status_t* err) const;
     const char* GetString(size_t key, status_t* err) const;
     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.
@@ -123,20 +111,30 @@
     void init();
 
     /**
-     * Set timestamp if the original timestamp is missing.
+     * Set elapsed timestamp if the original timestamp is missing.
      */
-    void setTimestampNs(uint64_t timestampNs) {mTimestampNs = timestampNs;}
-
-    inline int size() const {
-        return mFieldValueMap.size();
+    void setElapsedTimestampNs(int64_t timestampNs) {
+        mElapsedTimestampNs = timestampNs;
     }
 
     /**
-     * Returns the mutable DimensionsValue proto for the specific the field.
+     * Set the timestamp if the original logd timestamp is missing.
      */
-    DimensionsValue* findFieldValueOrNull(const Field& field);
+    void setLogdWallClockTimestampNs(int64_t timestampNs) {
+        mLogdTimestampNs = timestampNs;
+    }
 
-    inline const FieldValueMap& getFieldValueMap() const { return mFieldValueMap; }
+    inline int size() const {
+        return mValues.size();
+    }
+
+    const std::vector<FieldValue>& getValues() const {
+        return mValues;
+    }
+
+    std::vector<FieldValue>* getMutableValues() {
+        return &mValues;
+    }
 
 private:
     /**
@@ -150,14 +148,20 @@
      */
     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.
     // When the log event is created from log msg, this field is never initiated.
     android_log_context mContext = NULL;
 
-    uint64_t mTimestampNs;
+    // The timestamp set by the logd.
+    int64_t mLogdTimestampNs;
+
+    // The elapsed timestamp set by statsd log writer.
+    int64_t mElapsedTimestampNs;
 
     int mTagId;
 
diff --git a/cmds/statsd/src/matchers/matcher_util.cpp b/cmds/statsd/src/matchers/matcher_util.cpp
index fae9172..4612009 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,249 @@
     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;
+                }
+                // eq_int covers both int and long.
+                if (values[i].mValue.getType() == LONG &&
+                    (matcher.eq_int() == values[i].mValue.long_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;
+                }
+                // lt_int covers both int and long.
+                if (values[i].mValue.getType() == LONG &&
+                    (values[i].mValue.long_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;
+                }
+                // gt_int covers both int and long.
+                if (values[i].mValue.getType() == LONG &&
+                    (values[i].mValue.long_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;
+                }
+                // lte_int covers both int and long.
+                if (values[i].mValue.getType() == LONG &&
+                    (values[i].mValue.long_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;
+                }
+                // gte_int covers both int and long.
+                if (values[i].mValue.getType() == LONG &&
+                    (values[i].mValue.long_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 ae4df3e..af2e362 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>
@@ -45,8 +44,6 @@
 
 // for StatsLogReport
 const int FIELD_ID_ID = 1;
-const int FIELD_ID_START_REPORT_NANOS = 2;
-const int FIELD_ID_END_REPORT_NANOS = 3;
 const int FIELD_ID_COUNT_METRICS = 5;
 // for CountMetricDataWrapper
 const int FIELD_ID_DATA = 1;
@@ -55,8 +52,8 @@
 const int FIELD_ID_DIMENSION_IN_CONDITION = 2;
 const int FIELD_ID_BUCKET_INFO = 3;
 // for CountBucketInfo
-const int FIELD_ID_START_BUCKET_NANOS = 1;
-const int FIELD_ID_END_BUCKET_NANOS = 2;
+const int FIELD_ID_START_BUCKET_ELAPSED_NANOS = 1;
+const int FIELD_ID_END_BUCKET_ELAPSED_NANOS = 2;
 const int FIELD_ID_COUNT = 3;
 
 CountMetricProducer::CountMetricProducer(const ConfigKey& key, const CountMetric& metric,
@@ -66,21 +63,32 @@
     : MetricProducer(metric.id(), key, startTimeNs, conditionIndex, wizard) {
     // TODO: evaluate initial conditions. and set mConditionMet.
     if (metric.has_bucket()) {
-        mBucketSizeNs = TimeUnitToBucketSizeInMillis(metric.bucket()) * 1000000;
+        mBucketSizeNs =
+                TimeUnitToBucketSizeInMillisGuardrailed(key.GetUid(), metric.bucket()) * 1000000;
     } else {
         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);
@@ -94,40 +102,15 @@
     VLOG("Metric %lld onSlicedConditionMayChange", (long long)mMetricId);
 }
 
-void CountMetricProducer::onDumpReportLocked(const uint64_t dumpTimeNs, StatsLogReport* report) {
-    flushIfNeededLocked(dumpTimeNs);
-    report->set_metric_id(mMetricId);
-    report->set_start_report_nanos(mStartTimeNs);
-
-    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);
     if (mPastBuckets.empty()) {
         return;
     }
-
     protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_ID, (long long)mMetricId);
-    protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_START_REPORT_NANOS, (long long)mStartTimeNs);
     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());
@@ -138,25 +121,24 @@
         // 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);
         }
 
         // Then fill bucket_info (CountBucketInfo).
+
         for (const auto& bucket : counter.second) {
             long long bucketInfoToken = protoOutput->start(
                     FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_BUCKET_INFO);
-            protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_START_BUCKET_NANOS,
+            protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_START_BUCKET_ELAPSED_NANOS,
                                (long long)bucket.mBucketStartNs);
-            protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_END_BUCKET_NANOS,
+            protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_END_BUCKET_ELAPSED_NANOS,
                                (long long)bucket.mBucketEndNs);
             protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_COUNT, (long long)bucket.mCount);
             protoOutput->end(bucketInfoToken);
@@ -167,10 +149,8 @@
     }
 
     protoOutput->end(protoToken);
-    protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_END_REPORT_NANOS, (long long)dumpTimeNs);
 
     mPastBuckets.clear();
-    mStartTimeNs = mCurrentBucketStartTimeNs;
 
     // TODO: Clear mDimensionKeyMap once the report is dumped.
 }
@@ -205,8 +185,7 @@
         const size_t matcherIndex, const MetricDimensionKey& eventKey,
         const ConditionKey& conditionKey, bool condition,
         const LogEvent& event) {
-    uint64_t eventTimeNs = event.GetTimestampNs();
-
+    uint64_t eventTimeNs = event.GetElapsedTimestampNs();
     flushIfNeededLocked(eventTimeNs);
 
     if (condition == false) {
@@ -214,13 +193,11 @@
     }
 
     auto it = mCurrentSlicedCounter->find(eventKey);
-
     if (it == mCurrentSlicedCounter->end()) {
         // ===========GuardRail==============
         if (hitGuardRailLocked(eventKey)) {
             return;
         }
-
         // create a counter for the new key
         (*mCurrentSlicedCounter)[eventKey] = 1;
     } else {
@@ -228,10 +205,14 @@
         auto& count = it->second;
         count++;
     }
-
     for (auto& tracker : mAnomalyTrackers) {
+        int64_t countWholeBucket = mCurrentSlicedCounter->find(eventKey)->second;
+        auto prev = mCurrentFullCounters->find(eventKey);
+        if (prev != mCurrentFullCounters->end()) {
+            countWholeBucket += prev->second;
+        }
         tracker->detectAndDeclareAnomaly(eventTimeNs, mCurrentBucketNum, eventKey,
-                                         mCurrentSlicedCounter->find(eventKey)->second);
+                                         countWholeBucket);
     }
 
     VLOG("metric %lld %s->%lld", (long long)mMetricId, eventKey.c_str(),
@@ -241,33 +222,65 @@
 // When a new matched event comes in, we check if event falls into the current
 // bucket. If not, flush the old counter to past buckets and initialize the new bucket.
 void CountMetricProducer::flushIfNeededLocked(const uint64_t& eventTimeNs) {
-    if (eventTimeNs < mCurrentBucketStartTimeNs + mBucketSizeNs) {
+    uint64_t currentBucketEndTimeNs = getCurrentBucketEndTimeNs();
+    if (eventTimeNs < currentBucketEndTimeNs) {
         return;
     }
 
+    flushCurrentBucketLocked(eventTimeNs);
+    // Setup the bucket start time and number.
+    uint64_t numBucketsForward = 1 + (eventTimeNs - currentBucketEndTimeNs) / mBucketSizeNs;
+    mCurrentBucketStartTimeNs = currentBucketEndTimeNs + (numBucketsForward - 1) * mBucketSizeNs;
+    mCurrentBucketNum += numBucketsForward;
+    VLOG("metric %lld: new bucket start time: %lld", (long long)mMetricId,
+         (long long)mCurrentBucketStartTimeNs);
+}
+
+void CountMetricProducer::flushCurrentBucketLocked(const uint64_t& eventTimeNs) {
+    uint64_t fullBucketEndTimeNs = getCurrentBucketEndTimeNs();
     CountBucket info;
     info.mBucketStartNs = mCurrentBucketStartTimeNs;
-    info.mBucketEndNs = mCurrentBucketStartTimeNs + mBucketSizeNs;
+    if (eventTimeNs < fullBucketEndTimeNs) {
+        info.mBucketEndNs = eventTimeNs;
+    } else {
+        info.mBucketEndNs = fullBucketEndTimeNs;
+    }
     info.mBucketNum = mCurrentBucketNum;
     for (const auto& counter : *mCurrentSlicedCounter) {
         info.mCount = counter.second;
         auto& bucketList = mPastBuckets[counter.first];
         bucketList.push_back(info);
-        VLOG("metric %lld, dump key value: %s -> %lld",
-            (long long)mMetricId, counter.first.c_str(), (long long)counter.second);
+        VLOG("metric %lld, dump key value: %s -> %lld", (long long)mMetricId, counter.first.c_str(),
+             (long long)counter.second);
     }
 
-    for (auto& tracker : mAnomalyTrackers) {
-        tracker->addPastBucket(mCurrentSlicedCounter, mCurrentBucketNum);
+    // If we have finished a full bucket, then send this to anomaly tracker.
+    if (eventTimeNs > fullBucketEndTimeNs) {
+        // Accumulate partial buckets with current value and then send to anomaly tracker.
+        if (mCurrentFullCounters->size() > 0) {
+            for (const auto& keyValuePair : *mCurrentSlicedCounter) {
+                (*mCurrentFullCounters)[keyValuePair.first] += keyValuePair.second;
+            }
+            for (auto& tracker : mAnomalyTrackers) {
+                tracker->addPastBucket(mCurrentFullCounters, mCurrentBucketNum);
+            }
+            mCurrentFullCounters = std::make_shared<DimToValMap>();
+        } else {
+            // Skip aggregating the partial buckets since there's no previous partial bucket.
+            for (auto& tracker : mAnomalyTrackers) {
+                tracker->addPastBucket(mCurrentSlicedCounter, mCurrentBucketNum);
+            }
+        }
+    } else {
+        // Accumulate partial bucket.
+        for (const auto& keyValuePair : *mCurrentSlicedCounter) {
+            (*mCurrentFullCounters)[keyValuePair.first] += keyValuePair.second;
+        }
     }
 
-    // Reset counters (do not clear, since the old one is still referenced in mAnomalyTrackers).
+    // Only resets the counters, but doesn't setup the times nor numbers.
+    // (Do not clear since the old one is still referenced in mAnomalyTrackers).
     mCurrentSlicedCounter = std::make_shared<DimToValMap>();
-    uint64_t numBucketsForward = (eventTimeNs - mCurrentBucketStartTimeNs) / mBucketSizeNs;
-    mCurrentBucketStartTimeNs = mCurrentBucketStartTimeNs + numBucketsForward * mBucketSizeNs;
-    mCurrentBucketNum += numBucketsForward;
-    VLOG("metric %lld: new bucket start time: %lld", (long long)mMetricId,
-         (long long)mCurrentBucketStartTimeNs);
 }
 
 // Rough estimate of CountMetricProducer buffer stored. This number will be
diff --git a/cmds/statsd/src/metrics/CountMetricProducer.h b/cmds/statsd/src/metrics/CountMetricProducer.h
index 8659d47..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;
@@ -71,14 +70,20 @@
     void dumpStatesLocked(FILE* out, bool verbose) const override{};
 
     // Util function to flush the old packet.
-    void flushIfNeededLocked(const uint64_t& newEventTime);
+    void flushIfNeededLocked(const uint64_t& newEventTime) override;
+
+    void flushCurrentBucketLocked(const uint64_t& eventTimeNs) override;
 
     // TODO: Add a lock to mPastBuckets.
     std::unordered_map<MetricDimensionKey, std::vector<CountBucket>> mPastBuckets;
 
-    // The current bucket.
+    // The current bucket (may be a partial bucket).
     std::shared_ptr<DimToValMap> mCurrentSlicedCounter = std::make_shared<DimToValMap>();
 
+    // The sum of previous partial buckets in the current full bucket (excluding the current
+    // partial bucket). This is only updated while flushing the current bucket.
+    std::shared_ptr<DimToValMap> mCurrentFullCounters = std::make_shared<DimToValMap>();
+
     static const size_t kBucketSize = sizeof(CountBucket{});
 
     bool hitGuardRailLocked(const MetricDimensionKey& newKey);
@@ -87,6 +92,8 @@
     FRIEND_TEST(CountMetricProducerTest, TestEventsWithNonSlicedCondition);
     FRIEND_TEST(CountMetricProducerTest, TestEventsWithSlicedCondition);
     FRIEND_TEST(CountMetricProducerTest, TestAnomalyDetectionUnSliced);
+    FRIEND_TEST(CountMetricProducerTest, TestEventWithAppUpgrade);
+    FRIEND_TEST(CountMetricProducerTest, TestEventWithAppUpgradeInNextBucket);
 };
 
 }  // namespace statsd
diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.cpp b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
index efbdae1..9c65371 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>
@@ -44,8 +43,6 @@
 
 // for StatsLogReport
 const int FIELD_ID_ID = 1;
-const int FIELD_ID_START_REPORT_NANOS = 2;
-const int FIELD_ID_END_REPORT_NANOS = 3;
 const int FIELD_ID_DURATION_METRICS = 6;
 // for DurationMetricDataWrapper
 const int FIELD_ID_DATA = 1;
@@ -54,8 +51,8 @@
 const int FIELD_ID_DIMENSION_IN_CONDITION = 2;
 const int FIELD_ID_BUCKET_INFO = 3;
 // for DurationBucketInfo
-const int FIELD_ID_START_BUCKET_NANOS = 1;
-const int FIELD_ID_END_BUCKET_NANOS = 2;
+const int FIELD_ID_START_BUCKET_ELAPSED_NANOS = 1;
+const int FIELD_ID_END_BUCKET_ELAPSED_NANOS = 2;
 const int FIELD_ID_DURATION = 3;
 
 DurationMetricProducer::DurationMetricProducer(const ConfigKey& key, const DurationMetric& metric,
@@ -70,27 +67,39 @@
       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??
     if (metric.has_bucket()) {
-        mBucketSizeNs = TimeUnitToBucketSizeInMillis(metric.bucket()) * 1000000;
+        mBucketSizeNs =
+                TimeUnitToBucketSizeInMillisGuardrailed(key.GetUid(), metric.bucket()) * 1000000;
     } else {
         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);
@@ -102,12 +111,6 @@
 
 sp<AnomalyTracker> DurationMetricProducer::addAnomalyTracker(const Alert &alert) {
     std::lock_guard<std::mutex> lock(mMutex);
-    if (alert.trigger_if_sum_gt() > alert.num_buckets() * mBucketSizeNs) {
-        ALOGW("invalid alert: threshold (%f) > possible recordable value (%d x %lld)",
-              alert.trigger_if_sum_gt(), alert.num_buckets(),
-              (long long)mBucketSizeNs);
-        return nullptr;
-    }
     sp<DurationAnomalyTracker> anomalyTracker = new DurationAnomalyTracker(alert, mConfigKey);
     if (anomalyTracker != nullptr) {
         mAnomalyTrackers.push_back(anomalyTracker);
@@ -121,13 +124,13 @@
         case DurationMetric_AggregationType_SUM:
             return make_unique<OringDurationTracker>(
                     mConfigKey, mMetricId, eventKey, mWizard, mConditionTrackerIndex,
-                    mDimensionsInCondition, mNested,
-                    mCurrentBucketStartTimeNs, mBucketSizeNs, mConditionSliced, mAnomalyTrackers);
+                    mDimensionsInCondition, mNested, mCurrentBucketStartTimeNs, mCurrentBucketNum,
+                    mStartTimeNs, mBucketSizeNs, mConditionSliced, mAnomalyTrackers);
         case DurationMetric_AggregationType_MAX_SPARSE:
             return make_unique<MaxDurationTracker>(
                     mConfigKey, mMetricId, eventKey, mWizard, mConditionTrackerIndex,
-                    mDimensionsInCondition, mNested,
-                    mCurrentBucketStartTimeNs, mBucketSizeNs, mConditionSliced, mAnomalyTrackers);
+                    mDimensionsInCondition, mNested, mCurrentBucketStartTimeNs, mCurrentBucketNum,
+                    mStartTimeNs, mBucketSizeNs, mConditionSliced, mAnomalyTrackers);
     }
 }
 
@@ -142,10 +145,9 @@
 
 
     std::unordered_set<HashableDimensionKey> conditionDimensionsKeySet;
-    ConditionState conditionState = mWizard->getMetConditionDimension(
-        mConditionTrackerIndex, mDimensionsInCondition, &conditionDimensionsKeySet);
+    mWizard->getMetConditionDimension(mConditionTrackerIndex, mDimensionsInCondition,
+                                      &conditionDimensionsKeySet);
 
-    bool condition = (conditionState == ConditionState::kTrue);
     for (auto& pair : mCurrentSlicedDurationTrackerMap) {
         conditionDimensionsKeySet.erase(pair.first.getDimensionKeyInCondition());
     }
@@ -176,39 +178,18 @@
     }
 }
 
-void DurationMetricProducer::onDumpReportLocked(const uint64_t dumpTimeNs, StatsLogReport* report) {
-    flushIfNeededLocked(dumpTimeNs);
-    report->set_metric_id(mMetricId);
-    report->set_start_report_nanos(mStartTimeNs);
-
-    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);
-    protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_START_REPORT_NANOS, (long long)mStartTimeNs);
     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;
@@ -220,15 +201,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);
         }
 
@@ -236,9 +215,9 @@
         for (const auto& bucket : pair.second) {
             long long bucketInfoToken = protoOutput->start(
                     FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_BUCKET_INFO);
-            protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_START_BUCKET_NANOS,
+            protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_START_BUCKET_ELAPSED_NANOS,
                                (long long)bucket.mBucketStartNs);
-            protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_END_BUCKET_NANOS,
+            protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_END_BUCKET_ELAPSED_NANOS,
                                (long long)bucket.mBucketEndNs);
             protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_DURATION, (long long)bucket.mDuration);
             protoOutput->end(bucketInfoToken);
@@ -250,19 +229,19 @@
     }
 
     protoOutput->end(protoToken);
-    protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_END_REPORT_NANOS, (long long)dumpTimeNs);
     mPastBuckets.clear();
-    mStartTimeNs = mCurrentBucketStartTimeNs;
 }
 
-void DurationMetricProducer::flushIfNeededLocked(const uint64_t& eventTime) {
-    if (mCurrentBucketStartTimeNs + mBucketSizeNs > eventTime) {
+void DurationMetricProducer::flushIfNeededLocked(const uint64_t& eventTimeNs) {
+    uint64_t currentBucketEndTimeNs = getCurrentBucketEndTimeNs();
+
+    if (currentBucketEndTimeNs > eventTimeNs) {
         return;
     }
     VLOG("flushing...........");
     for (auto it = mCurrentSlicedDurationTrackerMap.begin();
             it != mCurrentSlicedDurationTrackerMap.end();) {
-        if (it->second->flushIfNeeded(eventTime, &mPastBuckets)) {
+        if (it->second->flushIfNeeded(eventTimeNs, &mPastBuckets)) {
             VLOG("erase bucket for key %s", it->first.c_str());
             it = mCurrentSlicedDurationTrackerMap.erase(it);
         } else {
@@ -270,11 +249,23 @@
         }
     }
 
-    int numBucketsForward = (eventTime - mCurrentBucketStartTimeNs) / mBucketSizeNs;
-    mCurrentBucketStartTimeNs += numBucketsForward * mBucketSizeNs;
+    int numBucketsForward = 1 + (eventTimeNs - currentBucketEndTimeNs) / mBucketSizeNs;
+    mCurrentBucketStartTimeNs = currentBucketEndTimeNs + (numBucketsForward - 1) * mBucketSizeNs;
     mCurrentBucketNum += numBucketsForward;
 }
 
+void DurationMetricProducer::flushCurrentBucketLocked(const uint64_t& eventTimeNs) {
+    for (auto it = mCurrentSlicedDurationTrackerMap.begin();
+         it != mCurrentSlicedDurationTrackerMap.end();) {
+        if (it->second->flushCurrentBucket(eventTimeNs, &mPastBuckets)) {
+            VLOG("erase bucket for key %s", it->first.c_str());
+            it = mCurrentSlicedDurationTrackerMap.erase(it);
+        } else {
+            ++it;
+        }
+    }
+}
+
 void DurationMetricProducer::dumpStatesLocked(FILE* out, bool verbose) const {
     if (mCurrentSlicedDurationTrackerMap.size() == 0) {
         return;
@@ -313,11 +304,11 @@
         const size_t matcherIndex, const MetricDimensionKey& eventKey,
         const ConditionKey& conditionKeys, bool condition,
         const LogEvent& event) {
-    flushIfNeededLocked(event.GetTimestampNs());
+    flushIfNeededLocked(event.GetElapsedTimestampNs());
 
     if (matcherIndex == mStopAllIndex) {
         for (auto& pair : mCurrentSlicedDurationTrackerMap) {
-            pair.second->noteStopAll(event.GetTimestampNs());
+            pair.second->noteStopAll(event.GetElapsedTimestampNs());
         }
         return;
     }
@@ -331,23 +322,21 @@
 
     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,
-                                  event.GetTimestampNs(), conditionKeys);
+                                  event.GetElapsedTimestampNs(), conditionKeys);
         } else if (matcherIndex == mStopIndex) {
-            it->second->noteStop(DEFAULT_DIMENSION_KEY, event.GetTimestampNs(), false);
+            it->second->noteStop(DEFAULT_DIMENSION_KEY, event.GetElapsedTimestampNs(), 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.GetElapsedTimestampNs(), conditionKeys);
             } else if (matcherIndex == mStopIndex) {
-                it->second->noteStop(
-                   HashableDimensionKey(value), event.GetTimestampNs(), false);
+                it->second->noteStop(value, event.GetElapsedTimestampNs(), false);
             }
         }
     }
diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.h b/cmds/statsd/src/metrics/DurationMetricProducer.h
index 152e570..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;
@@ -73,6 +72,8 @@
     // Util function to flush the old packet.
     void flushIfNeededLocked(const uint64_t& eventTime);
 
+    void flushCurrentBucketLocked(const uint64_t& eventTimeNs) override;
+
     const DurationMetric_AggregationType mAggregationType;
 
     // Index of the SimpleAtomMatcher which defines the start.
@@ -88,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.
@@ -112,6 +113,10 @@
 
     FRIEND_TEST(DurationMetricTrackerTest, TestNoCondition);
     FRIEND_TEST(DurationMetricTrackerTest, TestNonSlicedCondition);
+    FRIEND_TEST(DurationMetricTrackerTest, TestSumDurationWithUpgrade);
+    FRIEND_TEST(DurationMetricTrackerTest, TestSumDurationWithUpgradeInFollowingBucket);
+    FRIEND_TEST(DurationMetricTrackerTest, TestMaxDurationWithUpgrade);
+    FRIEND_TEST(DurationMetricTrackerTest, TestMaxDurationWithUpgradeInNextBucket);
     FRIEND_TEST(WakelockDurationE2eTest, TestAggregatedPredicates);
 };
 
diff --git a/cmds/statsd/src/metrics/EventMetricProducer.cpp b/cmds/statsd/src/metrics/EventMetricProducer.cpp
index 820d591..2585aa3 100644
--- a/cmds/statsd/src/metrics/EventMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/EventMetricProducer.cpp
@@ -19,6 +19,7 @@
 
 #include "EventMetricProducer.h"
 #include "stats_util.h"
+#include "stats_log_util.h"
 
 #include <limits.h>
 #include <stdlib.h>
@@ -42,14 +43,13 @@
 
 // for StatsLogReport
 const int FIELD_ID_ID = 1;
-const int FIELD_ID_START_REPORT_NANOS = 2;
-const int FIELD_ID_END_REPORT_NANOS = 3;
 const int FIELD_ID_EVENT_METRICS = 4;
 // for EventMetricDataWrapper
 const int FIELD_ID_DATA = 1;
 // for EventMetricData
-const int FIELD_ID_TIMESTAMP_NANOS = 1;
+const int FIELD_ID_ELAPSED_TIMESTAMP_NANOS = 1;
 const int FIELD_ID_ATOMS = 2;
+const int FIELD_ID_WALL_CLOCK_TIMESTAMP_NANOS = 3;
 
 EventMetricProducer::EventMetricProducer(const ConfigKey& key, const EventMetric& metric,
                                          const int conditionIndex,
@@ -57,13 +57,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);
 }
@@ -72,10 +75,6 @@
     VLOG("~EventMetricProducer() called");
 }
 
-void EventMetricProducer::startNewProtoOutputStreamLocked() {
-    mProto = std::make_unique<ProtoOutputStream>();
-}
-
 void EventMetricProducer::onSlicedConditionMayChangeLocked(const uint64_t eventTime) {
 }
 
@@ -96,18 +95,12 @@
     return buffer;
 }
 
-void EventMetricProducer::onDumpReportLocked(const uint64_t dumpTimeNs, StatsLogReport* report) {
-
-}
-
 void EventMetricProducer::onDumpReportLocked(const uint64_t dumpTimeNs,
                                              ProtoOutputStream* protoOutput) {
     if (mProto->size() <= 0) {
         return;
     }
     protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_ID, (long long)mMetricId);
-    protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_START_REPORT_NANOS, (long long)mStartTimeNs);
-    protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_END_REPORT_NANOS, (long long)dumpTimeNs);
 
     size_t bufferSize = mProto->size();
     VLOG("metric %lld dump report now... proto size: %zu ",
@@ -117,8 +110,7 @@
     protoOutput->write(FIELD_TYPE_MESSAGE | FIELD_ID_EVENT_METRICS,
                        reinterpret_cast<char*>(buffer.get()->data()), buffer.get()->size());
 
-    startNewProtoOutputStreamLocked();
-    mStartTimeNs = dumpTimeNs;
+    mProto->clear();
 }
 
 void EventMetricProducer::onConditionChangedLocked(const bool conditionMet,
@@ -137,9 +129,12 @@
 
     long long wrapperToken =
             mProto->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_DATA);
-    mProto->write(FIELD_TYPE_INT64 | FIELD_ID_TIMESTAMP_NANOS, (long long)event.GetTimestampNs());
+    mProto->write(FIELD_TYPE_INT64 | FIELD_ID_ELAPSED_TIMESTAMP_NANOS,
+        (long long)event.GetElapsedTimestampNs());
     long long eventToken = mProto->start(FIELD_TYPE_MESSAGE | FIELD_ID_ATOMS);
     event.ToProto(*mProto);
+    mProto->write(FIELD_TYPE_INT64 | FIELD_ID_WALL_CLOCK_TIMESTAMP_NANOS,
+        (long long)getWallClockNs());
     mProto->end(eventToken);
     mProto->end(wrapperToken);
 }
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 d6cb189..0daa506 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>
@@ -45,8 +44,6 @@
 
 // for StatsLogReport
 const int FIELD_ID_ID = 1;
-const int FIELD_ID_START_REPORT_NANOS = 2;
-const int FIELD_ID_END_REPORT_NANOS = 3;
 const int FIELD_ID_GAUGE_METRICS = 8;
 // for GaugeMetricDataWrapper
 const int FIELD_ID_DATA = 1;
@@ -55,10 +52,10 @@
 const int FIELD_ID_DIMENSION_IN_CONDITION = 2;
 const int FIELD_ID_BUCKET_INFO = 3;
 // for GaugeBucketInfo
-const int FIELD_ID_START_BUCKET_NANOS = 1;
-const int FIELD_ID_END_BUCKET_NANOS = 2;
+const int FIELD_ID_START_BUCKET_ELAPSED_NANOS = 1;
+const int FIELD_ID_END_BUCKET_ELAPSED_NANOS = 2;
 const int FIELD_ID_ATOM = 3;
-const int FIELD_ID_TIMESTAMP = 4;
+const int FIELD_ID_ELAPSED_ATOM_TIMESTAMP = 4;
 
 GaugeMetricProducer::GaugeMetricProducer(const ConfigKey& key, const GaugeMetric& metric,
                                          const int conditionIndex,
@@ -72,25 +69,36 @@
     mCurrentSlicedBucketForAnomaly = std::make_shared<DimToValMap>();
     int64_t bucketSizeMills = 0;
     if (metric.has_bucket()) {
-        bucketSizeMills = TimeUnitToBucketSizeInMillis(metric.bucket());
+        bucketSizeMills = TimeUnitToBucketSizeInMillisGuardrailed(key.GetUid(), metric.bucket());
     } else {
         bucketSizeMills = TimeUnitToBucketSizeInMillis(ONE_HOUR);
     }
     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) {
@@ -117,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);
@@ -134,7 +135,6 @@
     }
 
     protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_ID, (long long)mMetricId);
-    protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_START_REPORT_NANOS, (long long)mStartTimeNs);
     long long protoToken = protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_ID_GAUGE_METRICS);
 
     for (const auto& pair : mPastBuckets) {
@@ -147,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);
         }
 
@@ -163,22 +161,23 @@
         for (const auto& bucket : pair.second) {
             long long bucketInfoToken = protoOutput->start(
                     FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_BUCKET_INFO);
-            protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_START_BUCKET_NANOS,
+            protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_START_BUCKET_ELAPSED_NANOS,
                                (long long)bucket.mBucketStartNs);
-            protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_END_BUCKET_NANOS,
+            protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_END_BUCKET_ELAPSED_NANOS,
                                (long long)bucket.mBucketEndNs);
 
             if (!bucket.mGaugeAtoms.empty()) {
                 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);
 
                 for (const auto& atom : bucket.mGaugeAtoms) {
-                    protoOutput->write(FIELD_TYPE_INT64 | FIELD_COUNT_REPEATED | FIELD_ID_TIMESTAMP,
-                                       (long long)atom.mTimestamps);
+                    protoOutput->write(
+                        FIELD_TYPE_INT64 | FIELD_COUNT_REPEATED | FIELD_ID_ELAPSED_ATOM_TIMESTAMP,
+                        (long long)atom.mTimestamps);
                 }
             }
             protoOutput->end(bucketInfoToken);
@@ -188,13 +187,22 @@
         protoOutput->end(wrapperToken);
     }
     protoOutput->end(protoToken);
-    protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_END_REPORT_NANOS, (long long)dumpTimeNs);
 
     mPastBuckets.clear();
-    mStartTimeNs = mCurrentBucketStartTimeNs;
     // TODO: Clear mDimensionKeyMap once the report is dumped.
 }
 
+void GaugeMetricProducer::pullLocked() {
+    vector<std::shared_ptr<LogEvent>> allData;
+    if (!mStatsPullerManager->Pull(mPullTagId, &allData)) {
+        ALOGE("Stats puller failed for tag: %d", mPullTagId);
+        return;
+    }
+    for (const auto& data : allData) {
+        onMatchedLogEventLocked(0, *data);
+    }
+}
+
 void GaugeMetricProducer::onConditionChangedLocked(const bool conditionMet,
                                                    const uint64_t eventTime) {
     VLOG("Metric %lld onConditionChanged", (long long)mMetricId);
@@ -240,13 +248,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) {
@@ -285,7 +294,8 @@
     if (condition == false) {
         return;
     }
-    uint64_t eventTimeNs = event.GetTimestampNs();
+    uint64_t eventTimeNs = event.GetElapsedTimestampNs();
+    mTagId = event.GetTagId();
     if (eventTimeNs < mCurrentBucketStartTimeNs) {
         VLOG("Skip event due to late arrival: %lld vs %lld", (long long)eventTimeNs,
              (long long)mCurrentBucketStartTimeNs);
@@ -302,20 +312,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,
@@ -326,18 +334,16 @@
 }
 
 void GaugeMetricProducer::updateCurrentSlicedBucketForAnomaly() {
-    mCurrentSlicedBucketForAnomaly->clear();
-    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;
     }
@@ -349,42 +355,57 @@
 // if data is pushed, onMatchedLogEvent will only be called through onConditionChanged() inside
 // the GaugeMetricProducer while holding the lock.
 void GaugeMetricProducer::flushIfNeededLocked(const uint64_t& eventTimeNs) {
-    if (eventTimeNs < mCurrentBucketStartTimeNs + mBucketSizeNs) {
+    uint64_t currentBucketEndTimeNs = getCurrentBucketEndTimeNs();
+
+    if (eventTimeNs < currentBucketEndTimeNs) {
         VLOG("eventTime is %lld, less than next bucket start time %lld", (long long)eventTimeNs,
              (long long)(mCurrentBucketStartTimeNs + mBucketSizeNs));
         return;
     }
 
+    flushCurrentBucketLocked(eventTimeNs);
+
+    // Adjusts the bucket start and end times.
+    int64_t numBucketsForward = 1 + (eventTimeNs - currentBucketEndTimeNs) / mBucketSizeNs;
+    mCurrentBucketStartTimeNs = currentBucketEndTimeNs + (numBucketsForward - 1) * mBucketSizeNs;
+    mCurrentBucketNum += numBucketsForward;
+    VLOG("metric %lld: new bucket start time: %lld", (long long)mMetricId,
+         (long long)mCurrentBucketStartTimeNs);
+}
+
+void GaugeMetricProducer::flushCurrentBucketLocked(const uint64_t& eventTimeNs) {
+    uint64_t fullBucketEndTimeNs = getCurrentBucketEndTimeNs();
+
     GaugeBucket info;
     info.mBucketStartNs = mCurrentBucketStartTimeNs;
-    info.mBucketEndNs = mCurrentBucketStartTimeNs + mBucketSizeNs;
+    if (eventTimeNs < fullBucketEndTimeNs) {
+        info.mBucketEndNs = eventTimeNs;
+    } else {
+        info.mBucketEndNs = fullBucketEndTimeNs;
+    }
     info.mBucketNum = mCurrentBucketNum;
 
     for (const auto& slice : *mCurrentSlicedBucket) {
         info.mGaugeAtoms = slice.second;
         auto& bucketList = mPastBuckets[slice.first];
         bucketList.push_back(info);
-        VLOG("gauge metric %lld, dump key value: %s",
-            (long long)mMetricId, slice.first.c_str());
+        VLOG("gauge metric %lld, dump key value: %s", (long long)mMetricId, slice.first.c_str());
     }
 
-    // Reset counters
+    // If we have anomaly trackers, we need to update the partial bucket values.
     if (mAnomalyTrackers.size() > 0) {
         updateCurrentSlicedBucketForAnomaly();
-        for (auto& tracker : mAnomalyTrackers) {
-            tracker->addPastBucket(mCurrentSlicedBucketForAnomaly, mCurrentBucketNum);
+
+        if (eventTimeNs > fullBucketEndTimeNs) {
+            // This is known to be a full bucket, so send this data to the anomaly tracker.
+            for (auto& tracker : mAnomalyTrackers) {
+                tracker->addPastBucket(mCurrentSlicedBucketForAnomaly, mCurrentBucketNum);
+            }
+            mCurrentSlicedBucketForAnomaly = std::make_shared<DimToValMap>();
         }
     }
 
-    mCurrentSlicedBucketForAnomaly = std::make_shared<DimToValMap>();
     mCurrentSlicedBucket = std::make_shared<DimToGaugeAtomsMap>();
-
-    // Adjusts the bucket start time
-    int64_t numBucketsForward = (eventTimeNs - mCurrentBucketStartTimeNs) / mBucketSizeNs;
-    mCurrentBucketStartTimeNs = mCurrentBucketStartTimeNs + numBucketsForward * mBucketSizeNs;
-    mCurrentBucketNum += numBucketsForward;
-    VLOG("metric %lld: new bucket start time: %lld", (long long)mMetricId,
-         (long long)mCurrentBucketStartTimeNs);
 }
 
 size_t GaugeMetricProducer::byteSizeLocked() const {
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.h b/cmds/statsd/src/metrics/GaugeMetricProducer.h
index 86d0ccd..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;
 };
 
@@ -62,6 +65,22 @@
     // Handles when the pulled data arrives.
     void onDataPulled(const std::vector<std::shared_ptr<LogEvent>>& data) override;
 
+    // GaugeMetric needs to immediately trigger another pull when we create the partial bucket.
+    void notifyAppUpgrade(const uint64_t& eventTimeNs, const string& apk, const int uid,
+                          const int64_t version) override {
+        std::lock_guard<std::mutex> lock(mMutex);
+
+        if (eventTimeNs > getCurrentBucketEndTimeNs()) {
+            // Flush full buckets on the normal path up to the latest bucket boundary.
+            flushIfNeededLocked(eventTimeNs);
+        }
+        flushCurrentBucketLocked(eventTimeNs);
+        mCurrentBucketStartTimeNs = eventTimeNs;
+        if (mPullTagId != -1) {
+            pullLocked();
+        }
+    };
+
 protected:
     void onMatchedLogEventInternalLocked(
             const size_t matcherIndex, const MetricDimensionKey& eventKey,
@@ -71,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,
@@ -91,7 +109,13 @@
     void dumpStatesLocked(FILE* out, bool verbose) const override{};
 
     // Util function to flush the old packet.
-    void flushIfNeededLocked(const uint64_t& eventTime);
+    void flushIfNeededLocked(const uint64_t& eventTime) override;
+
+    void flushCurrentBucketLocked(const uint64_t& eventTimeNs) override;
+
+    void pullLocked();
+
+    int mTagId;
 
     std::shared_ptr<StatsPullerManager> mStatsPullerManager;
     // tagId for pulled data. -1 if this is not pulled
@@ -101,22 +125,24 @@
     // TODO: Add a lock to mPastBuckets.
     std::unordered_map<MetricDimensionKey, std::vector<GaugeBucket>> mPastBuckets;
 
-    // The current bucket.
+    // The current partial bucket.
     std::shared_ptr<DimToGaugeAtomsMap> mCurrentSlicedBucket;
 
-    // The current bucket for anomaly detection.
+    // The current full bucket for anomaly detection. This is updated to the latest value seen for
+    // this slice (ie, for partial buckets, we use the last partial bucket in this full bucket).
     std::shared_ptr<DimToValMap> mCurrentSlicedBucketForAnomaly;
 
-    // Translate Atom based bucket to single numeric value bucket for anomaly
+    // Translate Atom based bucket to single numeric value bucket for anomaly and updates the map
+    // for each slice with the latest value.
     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);
@@ -125,6 +151,8 @@
 
     FRIEND_TEST(GaugeMetricProducerTest, TestWithCondition);
     FRIEND_TEST(GaugeMetricProducerTest, TestNoCondition);
+    FRIEND_TEST(GaugeMetricProducerTest, TestPushedEventsWithUpgrade);
+    FRIEND_TEST(GaugeMetricProducerTest, TestPulledWithUpgrade);
     FRIEND_TEST(GaugeMetricProducerTest, TestAnomalyDetection);
 };
 
diff --git a/cmds/statsd/src/metrics/MetricProducer.cpp b/cmds/statsd/src/metrics/MetricProducer.cpp
index 85e655b..f3307dc 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 {
@@ -24,7 +25,7 @@
 using std::map;
 
 void MetricProducer::onMatchedLogEventLocked(const size_t matcherIndex, const LogEvent& event) {
-    uint64_t eventTimeNs = event.GetTimestampNs();
+    uint64_t eventTimeNs = event.GetElapsedTimestampNs();
     // this is old event, maybe statsd restarted?
     if (eventTimeNs < mStartTimeNs) {
         return;
@@ -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 3b1498f..8663e5e 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"
@@ -53,15 +54,32 @@
 
     virtual ~MetricProducer(){};
 
-    void notifyAppUpgrade(const string& apk, const int uid, const int64_t version) override{
+    /**
+     * Forces this metric to split into a partial bucket right now. If we're past a full bucket, we
+     * first call the standard flushing code to flush up to the latest full bucket. Then we call
+     * the flush again when the end timestamp is forced to be now, and then after flushing, update
+     * the start timestamp to be now.
+     */
+    void notifyAppUpgrade(const uint64_t& eventTimeNs, const string& apk, const int uid,
+                          const int64_t version) override {
+        std::lock_guard<std::mutex> lock(mMutex);
+
+        if (eventTimeNs > getCurrentBucketEndTimeNs()) {
+            // Flush full buckets on the normal path up to the latest bucket boundary.
+            flushIfNeededLocked(eventTimeNs);
+        }
+        // Now flush a partial bucket.
+        flushCurrentBucketLocked(eventTimeNs);
+        mCurrentBucketStartTimeNs = eventTimeNs;
+        // Don't update the current bucket number so that the anomaly tracker knows this bucket
+        // is a partial bucket and can merge it with the previous bucket.
+    };
+
+    void notifyAppRemoved(const uint64_t& eventTimeNs, const string& apk, const int uid) override{
             // TODO: Implement me.
     };
 
-    void notifyAppRemoved(const string& apk, const int uid) override{
-            // TODO: Implement me.
-    };
-
-    void onUidMapReceived() override{
+    void onUidMapReceived(const uint64_t& eventTimeNs) override{
             // TODO: Implement me.
     };
 
@@ -87,16 +105,12 @@
     };
 
     // Output the metrics data to [protoOutput]. All metrics reports end with the same timestamp.
+    // This method clears all the past buckets.
     void onDumpReport(const uint64_t dumpTimeNs, android::util::ProtoOutputStream* protoOutput) {
         std::lock_guard<std::mutex> lock(mMutex);
         return onDumpReportLocked(dumpTimeNs, protoOutput);
     }
 
-    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);
         dumpStatesLocked(out, verbose);
@@ -109,6 +123,7 @@
         return byteSizeLocked();
     }
 
+    /* If alert is valid, adds an AnomalyTracker and returns it. If invalid, returns nullptr. */
     virtual sp<AnomalyTracker> addAnomalyTracker(const Alert &alert) {
         std::lock_guard<std::mutex> lock(mMutex);
         sp<AnomalyTracker> anomalyTracker = new AnomalyTracker(alert, mConfigKey);
@@ -123,6 +138,11 @@
         return mBucketSizeNs;
     }
 
+    // Only needed for unit-testing to override guardrail.
+    void setBucketSize(int64_t bucketSize) {
+        mBucketSizeNs = bucketSize;
+    }
+
     inline const int64_t& getMetricId() {
         return mMetricId;
     }
@@ -132,19 +152,46 @@
     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;
 
+    /**
+     * Flushes the current bucket if the eventTime is after the current bucket's end time.
+     */
+    virtual void flushIfNeededLocked(const uint64_t& eventTime){};
+
+    /**
+     * For metrics that aggregate (ie, every metric producer except for EventMetricProducer),
+     * we need to be able to flush the current buckets on demand (ie, end the current bucket and
+     * start new bucket). If this function is called when eventTimeNs is greater than the current
+     * bucket's end timestamp, than we flush up to the end of the latest full bucket; otherwise,
+     * we assume that we want to flush a partial bucket. The bucket start timestamp and bucket
+     * number are not changed by this function. This method should only be called by
+     * flushIfNeededLocked or the app upgrade handler; the caller MUST update the bucket timestamp
+     * and bucket number as needed.
+     */
+    virtual void flushCurrentBucketLocked(const uint64_t& eventTimeNs){};
+
+    // Convenience to compute the current bucket's end time, which is always aligned with the
+    // start time of the metric.
+    uint64_t getCurrentBucketEndTimeNs() {
+        return mStartTimeNs + (mCurrentBucketNum + 1) * mBucketSizeNs;
+    }
+
     const int64_t mMetricId;
 
     const ConfigKey mConfigKey;
 
-    // The start time for the current in memory metrics data.
+    // The time when this metric producer was first created. The end time for the current bucket
+    // can be computed from this based on mCurrentBucketNum.
     uint64_t mStartTimeNs;
 
+    // Start time may not be aligned with the start of statsd if there is an app upgrade in the
+    // middle of a bucket.
     uint64_t mCurrentBucketStartTimeNs;
 
+    // Used by anomaly detector to track which bucket we are in. This is not sent with the produced
+    // report.
     uint64_t mCurrentBucketNum;
 
     int64_t mBucketSizeNs;
@@ -157,10 +204,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 5f0619a..e75b710 100644
--- a/cmds/statsd/src/metrics/MetricsManager.cpp
+++ b/cmds/statsd/src/metrics/MetricsManager.cpp
@@ -26,9 +26,11 @@
 #include "matchers/SimpleLogMatchingTracker.h"
 #include "metrics_manager_util.h"
 #include "stats_util.h"
+#include "stats_log_util.h"
 
 #include <log/logprint.h>
 #include <private/android_filesystem_config.h>
+#include <utils/SystemClock.h>
 
 using android::util::FIELD_COUNT_REPEATED;
 using android::util::FIELD_TYPE_MESSAGE;
@@ -48,9 +50,10 @@
 
 MetricsManager::MetricsManager(const ConfigKey& key, const StatsdConfig& config,
                                const long timeBaseSec, sp<UidMap> uidMap)
-    : mConfigKey(key), mUidMap(uidMap) {
+    : mConfigKey(key), mUidMap(uidMap), mLastReportTimeNs(timeBaseSec * NS_PER_SEC) {
     mConfigValid =
-            initStatsdConfig(key, config, *uidMap, timeBaseSec, mTagIds, mAllAtomMatchers, mAllConditionTrackers,
+            initStatsdConfig(key, config, *uidMap, timeBaseSec, mTagIds, mAllAtomMatchers,
+                             mAllConditionTrackers,
                              mAllMetricProducers, mAllAnomalyTrackers, mConditionToMetricMap,
                              mTrackerToMetricMap, mTrackerToConditionMap, mNoReportMetricIds);
 
@@ -89,8 +92,10 @@
         ALOGE("This config is too big! Reject!");
         mConfigValid = false;
     }
-
-    // TODO: add alert size.
+    if (mAllAnomalyTrackers.size() > StatsdStats::kMaxAlertCountPerConfig) {
+        ALOGE("This config has too many alerts! Reject!");
+        mConfigValid = false;
+    }
     // no matter whether this config is valid, log it in the stats.
     StatsdStats::getInstance().noteConfigReceived(key, mAllMetricProducers.size(),
                                                   mAllConditionTrackers.size(),
@@ -121,7 +126,8 @@
     return mConfigValid;
 }
 
-void MetricsManager::notifyAppUpgrade(const string& apk, const int uid, const int64_t version) {
+void MetricsManager::notifyAppUpgrade(const uint64_t& eventTimeNs, const string& apk, const int uid,
+                                      const int64_t version) {
     // check if we care this package
     if (std::find(mAllowedPkg.begin(), mAllowedPkg.end(), apk) == mAllowedPkg.end()) {
         return;
@@ -131,7 +137,8 @@
     initLogSourceWhiteList();
 }
 
-void MetricsManager::notifyAppRemoved(const string& apk, const int uid) {
+void MetricsManager::notifyAppRemoved(const uint64_t& eventTimeNs, const string& apk,
+                                      const int uid) {
     // check if we care this package
     if (std::find(mAllowedPkg.begin(), mAllowedPkg.end(), apk) == mAllowedPkg.end()) {
         return;
@@ -141,21 +148,13 @@
     initLogSourceWhiteList();
 }
 
-void MetricsManager::onUidMapReceived() {
+void MetricsManager::onUidMapReceived(const uint64_t& eventTimeNs) {
     if (mAllowedPkg.size() == 0) {
         return;
     }
     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());
     {
@@ -170,9 +169,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()) {
@@ -182,6 +180,7 @@
             protoOutput->end(token);
         }
     }
+    mLastReportTimeNs = dumpTimeStampNs;
     VLOG("=========================Metric Reports End==========================");
 }
 
@@ -191,8 +190,9 @@
         return;
     }
 
-    if (event.GetTagId() == android::util::APP_HOOK) { // Check that app hook fields are valid.
-        // TODO: Find a way to make these checks easier to maintain if the app hooks get changed.
+    if (event.GetTagId() == android::util::APP_BREADCRUMB_REPORTED) {
+        // Check that app breadcrumb reported fields are valid.
+        // TODO: Find a way to make these checks easier to maintain.
         status_t err = NO_ERROR;
 
         // Uid is 3rd from last field and must match the caller's uid,
@@ -235,7 +235,7 @@
     }
 
     int tagId = event.GetTagId();
-    uint64_t eventTime = event.GetTimestampNs();
+    uint64_t eventTime = event.GetElapsedTimestampNs();
     if (mTagIds.find(tagId) == mTagIds.end()) {
         // not interesting...
         return;
diff --git a/cmds/statsd/src/metrics/MetricsManager.h b/cmds/statsd/src/metrics/MetricsManager.h
index d4b9102..d4f844f 100644
--- a/cmds/statsd/src/metrics/MetricsManager.h
+++ b/cmds/statsd/src/metrics/MetricsManager.h
@@ -51,11 +51,12 @@
 
     void setAnomalyMonitor(const sp<AnomalyMonitor>& anomalyMonitor);
 
-    void notifyAppUpgrade(const string& apk, const int uid, const int64_t version) override;
+    void notifyAppUpgrade(const uint64_t& eventTimeNs, const string& apk, const int uid,
+                          const int64_t version) override;
 
-    void notifyAppRemoved(const string& apk, const int uid) override;
+    void notifyAppRemoved(const uint64_t& eventTimeNs, const string& apk, const int uid) override;
 
-    void onUidMapReceived() override;
+    void onUidMapReceived(const uint64_t& eventTimeNs) override;
 
     bool shouldAddUidMapListener() const {
         return !mAllowedPkg.empty();
@@ -63,9 +64,14 @@
 
     void dumpStates(FILE* out, bool verbose);
 
+    // Returns the elapsed realtime when this metric manager last reported metrics.
+    uint64_t getLastReportTimeNs() {
+        return mLastReportTimeNs;
+    };
+
     // 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.
@@ -77,6 +83,8 @@
 
     bool mConfigValid = false;
 
+    uint64_t mLastReportTimeNs;
+
     // The uid log sources from StatsdConfig.
     std::vector<int32_t> mAllowedUid;
 
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.cpp b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
index c9cc7bb..35fcdc4 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"
@@ -48,8 +47,6 @@
 
 // for StatsLogReport
 const int FIELD_ID_ID = 1;
-const int FIELD_ID_START_REPORT_NANOS = 2;
-const int FIELD_ID_END_REPORT_NANOS = 3;
 const int FIELD_ID_VALUE_METRICS = 7;
 // for ValueMetricDataWrapper
 const int FIELD_ID_DATA = 1;
@@ -75,21 +72,34 @@
     // TODO: valuemetric for pushed events may need unlimited bucket length
     int64_t bucketSizeMills = 0;
     if (metric.has_bucket()) {
-        bucketSizeMills = TimeUnitToBucketSizeInMillis(metric.bucket());
+        bucketSizeMills = TimeUnitToBucketSizeInMillisGuardrailed(key.GetUid(), metric.bucket());
     } else {
         bucketSizeMills = TimeUnitToBucketSizeInMillis(ONE_HOUR);
     }
 
     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);
@@ -119,26 +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);
-    report->set_start_report_nanos(mStartTimeNs);
-    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);
@@ -147,7 +137,6 @@
         return;
     }
     protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_ID, (long long)mMetricId);
-    protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_START_REPORT_NANOS, (long long)mStartTimeNs);
     long long protoToken = protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_ID_VALUE_METRICS);
 
     for (const auto& pair : mPastBuckets) {
@@ -159,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);
         }
 
@@ -186,11 +173,9 @@
         protoOutput->end(wrapperToken);
     }
     protoOutput->end(protoToken);
-    protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_END_REPORT_NANOS, (long long)dumpTimeNs);
 
     VLOG("metric %lld dump report now...", (long long)mMetricId);
     mPastBuckets.clear();
-    mStartTimeNs = mCurrentBucketStartTimeNs;
     // TODO: Clear mDimensionKeyMap once the report is dumped.
 }
 
@@ -234,19 +219,19 @@
         }
         // For scheduled pulled data, the effective event time is snap to the nearest
         // bucket boundary to make bucket finalize.
-        uint64_t realEventTime = allData.at(0)->GetTimestampNs();
+        uint64_t realEventTime = allData.at(0)->GetElapsedTimestampNs();
         uint64_t eventTime = mStartTimeNs +
-            ((realEventTime - mStartTimeNs)/mBucketSizeNs) * mBucketSizeNs;
+            ((realEventTime - mStartTimeNs) / mBucketSizeNs) * mBucketSizeNs;
 
         mCondition = false;
         for (const auto& data : allData) {
-            data->setTimestampNs(eventTime-1);
+            data->setElapsedTimestampNs(eventTime - 1);
             onMatchedLogEventLocked(0, *data);
         }
 
         mCondition = true;
         for (const auto& data : allData) {
-            data->setTimestampNs(eventTime);
+            data->setElapsedTimestampNs(eventTime);
             onMatchedLogEventLocked(0, *data);
         }
     }
@@ -276,7 +261,7 @@
         const size_t matcherIndex, const MetricDimensionKey& eventKey,
         const ConditionKey& conditionKey, bool condition,
         const LogEvent& event) {
-    uint64_t eventTimeNs = event.GetTimestampNs();
+    uint64_t eventTimeNs = event.GetElapsedTimestampNs();
     if (eventTimeNs < mCurrentBucketStartTimeNs) {
         VLOG("Skip event due to late arrival: %lld vs %lld", (long long)eventTimeNs,
              (long long)mCurrentBucketStartTimeNs);
@@ -290,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) {
@@ -320,29 +305,50 @@
         interval.sum += value;
     }
 
-    for (auto& tracker : mAnomalyTrackers) {
-        tracker->detectAndDeclareAnomaly(eventTimeNs, mCurrentBucketNum, eventKey, interval.sum);
+    long wholeBucketVal = interval.sum;
+    auto prev = mCurrentFullBucket.find(eventKey);
+    if (prev != mCurrentFullBucket.end()) {
+        wholeBucketVal += prev->second;
     }
-}
-
-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;
+    for (auto& tracker : mAnomalyTrackers) {
+        tracker->detectAndDeclareAnomaly(eventTimeNs, mCurrentBucketNum, eventKey, wholeBucketVal);
+    }
 }
 
 void ValueMetricProducer::flushIfNeededLocked(const uint64_t& eventTimeNs) {
-    if (mCurrentBucketStartTimeNs + mBucketSizeNs > eventTimeNs) {
+    uint64_t currentBucketEndTimeNs = getCurrentBucketEndTimeNs();
+
+    if (currentBucketEndTimeNs > eventTimeNs) {
         VLOG("eventTime is %lld, less than next bucket start time %lld", (long long)eventTimeNs,
-             (long long)(mCurrentBucketStartTimeNs + mBucketSizeNs));
+             (long long)(currentBucketEndTimeNs));
         return;
     }
+
+    flushCurrentBucketLocked(eventTimeNs);
+
+    int64_t numBucketsForward = 1 + (eventTimeNs - currentBucketEndTimeNs) / mBucketSizeNs;
+    mCurrentBucketStartTimeNs = currentBucketEndTimeNs + (numBucketsForward - 1) * mBucketSizeNs;
+    mCurrentBucketNum += numBucketsForward;
+
+    if (numBucketsForward > 1) {
+        VLOG("Skipping forward %lld buckets", (long long)numBucketsForward);
+    }
+    VLOG("metric %lld: new bucket start time: %lld", (long long)mMetricId,
+         (long long)mCurrentBucketStartTimeNs);
+}
+
+void ValueMetricProducer::flushCurrentBucketLocked(const uint64_t& eventTimeNs) {
     VLOG("finalizing bucket for %ld, dumping %d slices", (long)mCurrentBucketStartTimeNs,
          (int)mCurrentSlicedBucket.size());
+    uint64_t fullBucketEndTimeNs = getCurrentBucketEndTimeNs();
+
     ValueBucket info;
     info.mBucketStartNs = mCurrentBucketStartTimeNs;
-    info.mBucketEndNs = mCurrentBucketStartTimeNs + mBucketSizeNs;
+    if (eventTimeNs < fullBucketEndTimeNs) {
+        info.mBucketEndNs = eventTimeNs;
+    } else {
+        info.mBucketEndNs = fullBucketEndTimeNs;
+    }
     info.mBucketNum = mCurrentBucketNum;
 
     int tainted = 0;
@@ -352,27 +358,42 @@
         // it will auto create new vector of ValuebucketInfo if the key is not found.
         auto& bucketList = mPastBuckets[slice.first];
         bucketList.push_back(info);
-
-        for (auto& tracker : mAnomalyTrackers) {
-            if (tracker != nullptr) {
-                tracker->addPastBucket(slice.first, info.mValue, info.mBucketNum);
-            }
-        }
     }
     VLOG("%d tainted pairs in the bucket", tainted);
 
+    if (eventTimeNs > fullBucketEndTimeNs) {  // If full bucket, send to anomaly tracker.
+        // Accumulate partial buckets with current value and then send to anomaly tracker.
+        if (mCurrentFullBucket.size() > 0) {
+            for (const auto& slice : mCurrentSlicedBucket) {
+                mCurrentFullBucket[slice.first] += slice.second.sum;
+            }
+            for (const auto& slice : mCurrentFullBucket) {
+                for (auto& tracker : mAnomalyTrackers) {
+                    if (tracker != nullptr) {
+                        tracker->addPastBucket(slice.first, slice.second, mCurrentBucketNum);
+                    }
+                }
+            }
+            mCurrentFullBucket.clear();
+        } else {
+            // Skip aggregating the partial buckets since there's no previous partial bucket.
+            for (const auto& slice : mCurrentSlicedBucket) {
+                for (auto& tracker : mAnomalyTrackers) {
+                    if (tracker != nullptr) {
+                        tracker->addPastBucket(slice.first, slice.second.sum, mCurrentBucketNum);
+                    }
+                }
+            }
+        }
+    } else {
+        // Accumulate partial bucket.
+        for (const auto& slice : mCurrentSlicedBucket) {
+            mCurrentFullBucket[slice.first] += slice.second.sum;
+        }
+    }
+
     // Reset counters
     mCurrentSlicedBucket.clear();
-
-    int64_t numBucketsForward = (eventTimeNs - mCurrentBucketStartTimeNs) / mBucketSizeNs;
-    mCurrentBucketStartTimeNs = mCurrentBucketStartTimeNs + numBucketsForward * mBucketSizeNs;
-    mCurrentBucketNum += numBucketsForward;
-
-    if (numBucketsForward > 1) {
-        VLOG("Skipping forward %lld buckets", (long long)numBucketsForward);
-    }
-    VLOG("metric %lld: new bucket start time: %lld", (long long)mMetricId,
-         (long long)mCurrentBucketStartTimeNs);
 }
 
 size_t ValueMetricProducer::byteSizeLocked() const {
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.h b/cmds/statsd/src/metrics/ValueMetricProducer.h
index 121ec7d..b518f2f 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.h
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.h
@@ -47,6 +47,39 @@
 
     void onDataPulled(const std::vector<std::shared_ptr<LogEvent>>& data) override;
 
+    // ValueMetric needs special logic if it's a pulled atom.
+    void notifyAppUpgrade(const uint64_t& eventTimeNs, const string& apk, const int uid,
+                          const int64_t version) override {
+        std::lock_guard<std::mutex> lock(mMutex);
+
+        if (mPullTagId != -1) {
+            vector<shared_ptr<LogEvent>> allData;
+            mStatsPullerManager->Pull(mPullTagId, &allData);
+            if (allData.size() == 0) {
+                // This shouldn't happen since this valuemetric is not useful now.
+            }
+
+            // Pretend the pulled data occurs right before the app upgrade event.
+            mCondition = false;
+            for (const auto& data : allData) {
+                data->setElapsedTimestampNs(eventTimeNs - 1);
+                onMatchedLogEventLocked(0, *data);
+            }
+
+            flushCurrentBucketLocked(eventTimeNs);
+            mCurrentBucketStartTimeNs = eventTimeNs;
+
+            mCondition = true;
+            for (const auto& data : allData) {
+                data->setElapsedTimestampNs(eventTimeNs);
+                onMatchedLogEventLocked(0, *data);
+            }
+        } else {  // For pushed value metric, we simply flush and reset the current bucket start.
+            flushCurrentBucketLocked(eventTimeNs);
+            mCurrentBucketStartTimeNs = eventTimeNs;
+        }
+    };
+
 protected:
     void onMatchedLogEventInternalLocked(
             const size_t matcherIndex, const MetricDimensionKey& eventKey,
@@ -56,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;
@@ -70,7 +102,9 @@
     void dumpStatesLocked(FILE* out, bool verbose) const override{};
 
     // Util function to flush the old packet.
-    void flushIfNeededLocked(const uint64_t& eventTime);
+    void flushIfNeededLocked(const uint64_t& eventTime) override;
+
+    void flushCurrentBucketLocked(const uint64_t& eventTimeNs) override;
 
     const FieldMatcher mValueField;
 
@@ -85,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
@@ -101,12 +137,12 @@
 
     std::unordered_map<MetricDimensionKey, Interval> mCurrentSlicedBucket;
 
+    std::unordered_map<MetricDimensionKey, long> mCurrentFullBucket;
+
     // Save the past buckets and we can clear when the StatsLogReport is dumped.
     // 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);
 
@@ -114,6 +150,8 @@
 
     FRIEND_TEST(ValueMetricProducerTest, TestNonDimensionalEvents);
     FRIEND_TEST(ValueMetricProducerTest, TestEventsWithNonSlicedCondition);
+    FRIEND_TEST(ValueMetricProducerTest, TestPushedEventsWithUpgrade);
+    FRIEND_TEST(ValueMetricProducerTest, TestPulledValueWithUpgrade);
     FRIEND_TEST(ValueMetricProducerTest, TestPushedEventsWithoutCondition);
     FRIEND_TEST(ValueMetricProducerTest, TestAnomalyDetection);
 };
diff --git a/cmds/statsd/src/metrics/duration_helper/DurationTracker.h b/cmds/statsd/src/metrics/duration_helper/DurationTracker.h
index 45735a8..8f236fa 100644
--- a/cmds/statsd/src/metrics/duration_helper/DurationTracker.h
+++ b/cmds/statsd/src/metrics/duration_helper/DurationTracker.h
@@ -62,8 +62,9 @@
 public:
     DurationTracker(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 bucketSizeNs, bool conditionSliced,
+                    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)
         : mConfigKey(key),
           mTrackerId(id),
@@ -75,7 +76,9 @@
           mNested(nesting),
           mCurrentBucketStartTimeNs(currentBucketStartNs),
           mDuration(0),
-          mCurrentBucketNum(0),
+          mDurationFullBucket(0),
+          mCurrentBucketNum(currentBucketNum),
+          mStartTimeNs(startTimeNs),
           mConditionSliced(conditionSliced),
           mAnomalyTrackers(anomalyTrackers){};
 
@@ -98,6 +101,12 @@
             uint64_t timestampNs,
             std::unordered_map<MetricDimensionKey, std::vector<DurationBucket>>* output) = 0;
 
+    // Should only be called during an app upgrade or from this tracker's flushIfNeeded. If from
+    // an app upgrade, we assume that we're trying to form a partial bucket.
+    virtual bool flushCurrentBucket(
+            const uint64_t& eventTimeNs,
+            std::unordered_map<MetricDimensionKey, std::vector<DurationBucket>>* output) = 0;
+
     // Predict the anomaly timestamp given the current status.
     virtual int64_t predictAnomalyTimestampNs(const DurationAnomalyTracker& anomalyTracker,
                                               const uint64_t currentTimestamp) const = 0;
@@ -153,6 +162,13 @@
             }
         }
     }
+
+    // Convenience to compute the current bucket's end time, which is always aligned with the
+    // start time of the metric.
+    uint64_t getCurrentBucketEndTimeNs() {
+        return mStartTimeNs + (mCurrentBucketNum + 1) * mBucketSizeNs;
+    }
+
     // A reference to the DurationMetricProducer's config key.
     const ConfigKey& mConfigKey;
 
@@ -166,16 +182,20 @@
 
     const int64_t mBucketSizeNs;
 
-    const FieldMatcher mDimensionInCondition;
+    const std::vector<Matcher>& mDimensionInCondition;
 
     const bool mNested;
 
     uint64_t mCurrentBucketStartTimeNs;
 
-    int64_t mDuration;  // current recorded duration result
+    int64_t mDuration;  // current recorded duration result (for partial bucket)
+
+    int64_t mDurationFullBucket;  // Sum of past partial buckets in current full bucket.
 
     uint64_t mCurrentBucketNum;
 
+    const uint64_t mStartTimeNs;
+
     const bool mConditionSliced;
 
     std::vector<sp<DurationAnomalyTracker>> mAnomalyTrackers;
diff --git a/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.cpp b/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.cpp
index db7dea4..95df5ae6 100644
--- a/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.cpp
+++ b/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.cpp
@@ -27,12 +27,14 @@
 MaxDurationTracker::MaxDurationTracker(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 bucketSizeNs,
+                                       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)
     : DurationTracker(key, id, eventKey, wizard, conditionIndex, dimensionInCondition, nesting,
-                      currentBucketStartNs, bucketSizeNs, conditionSliced, anomalyTrackers) {
+                      currentBucketStartNs, currentBucketNum, startTimeNs, bucketSizeNs,
+                      conditionSliced, anomalyTrackers) {
 }
 
 unique_ptr<DurationTracker> MaxDurationTracker::clone(const uint64_t eventTime) {
@@ -53,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",
@@ -102,7 +102,6 @@
 
 void MaxDurationTracker::noteStop(const HashableDimensionKey& key, const uint64_t eventTime,
                                   bool forceStop) {
-    declareAnomalyIfAlarmExpired(eventTime);
     VLOG("MaxDuration: key %s stop", key.c_str());
     if (mInfos.find(key) == mInfos.end()) {
         // we didn't see a start event before. do nothing.
@@ -122,7 +121,7 @@
                 VLOG("Max, key %s, Stop %lld %lld %lld", key.c_str(),
                      (long long)duration.lastStartTime, (long long)eventTime,
                      (long long)durationTime);
-                duration.lastDuration = duration.lastDuration + durationTime;
+                duration.lastDuration += durationTime;
                 VLOG("  record duration: %lld ", (long long)duration.lastDuration);
             }
             break;
@@ -138,7 +137,6 @@
 
     if (duration.lastDuration > mDuration) {
         mDuration = duration.lastDuration;
-        detectAndDeclareAnomaly(eventTime, mCurrentBucketNum, mDuration);
         VLOG("Max: new max duration: %lld", (long long)mDuration);
     }
     // Once an atom duration ends, we erase it. Next time, if we see another atom event with the
@@ -158,88 +156,66 @@
     }
 }
 
-bool MaxDurationTracker::flushIfNeeded(
-        uint64_t eventTime, unordered_map<MetricDimensionKey, vector<DurationBucket>>* output) {
-    if (mCurrentBucketStartTimeNs + mBucketSizeNs > eventTime) {
-        return false;
-    }
-
+bool MaxDurationTracker::flushCurrentBucket(
+        const uint64_t& eventTimeNs,
+        std::unordered_map<MetricDimensionKey, std::vector<DurationBucket>>* output) {
     VLOG("MaxDurationTracker flushing.....");
 
     // adjust the bucket start time
-    int numBucketsForward = (eventTime - mCurrentBucketStartTimeNs) / mBucketSizeNs;
+    int numBucketsForward = 0;
+    uint64_t fullBucketEnd = getCurrentBucketEndTimeNs();
+    uint64_t currentBucketEndTimeNs;
+    if (eventTimeNs >= fullBucketEnd) {
+        numBucketsForward = 1 + (eventTimeNs - fullBucketEnd) / mBucketSizeNs;
+        currentBucketEndTimeNs = fullBucketEnd;
+    } else {
+        // This must be a partial bucket.
+        currentBucketEndTimeNs = eventTimeNs;
+    }
 
-    uint64_t endTime = mCurrentBucketStartTimeNs + mBucketSizeNs;
-
-    DurationBucket info;
-    info.mBucketStartNs = mCurrentBucketStartTimeNs;
-    info.mBucketEndNs = endTime;
-    info.mBucketNum = mCurrentBucketNum;
-
-    uint64_t oldBucketStartTimeNs = mCurrentBucketStartTimeNs;
-    mCurrentBucketStartTimeNs += (numBucketsForward)*mBucketSizeNs;
-
-    bool hasOnGoingStartedEvent = false;  // a kStarted event last across bucket boundaries.
     bool hasPendingEvent =
             false;  // has either a kStarted or kPaused event across bucket boundaries
-                    // meaning we need to carry them over to the new bucket.
+    // meaning we need to carry them over to the new bucket.
     for (auto it = mInfos.begin(); it != mInfos.end(); ++it) {
-        int64_t finalDuration = it->second.lastDuration;
-        if (it->second.state == kStarted) {
-            // the event is still on-going, duration needs to be updated.
-            // |..lastDurationTime_recorded...last_start -----|bucket_end. We need to record the
-            // duration between lastStartTime and bucketEnd.
-            int64_t durationTime = endTime - it->second.lastStartTime;
-
-            finalDuration += durationTime;
-            VLOG("  unrecorded %lld -> %lld", (long long)(durationTime), (long long)finalDuration);
-            // if the event is still on-going, we need to fill the buckets between prev_bucket and
-            // now_bucket. |prev_bucket|...|..|...|now_bucket|
-            hasOnGoingStartedEvent = true;
-        }
-
-        if (finalDuration > mDuration) {
-            mDuration = finalDuration;
-        }
-
         if (it->second.state == DurationState::kStopped) {
             // No need to keep buckets for events that were stopped before.
             mInfos.erase(it);
         } else {
             hasPendingEvent = true;
-            // for kPaused, and kStarted event, we will keep track of them, and reset the start time
-            // and duration.
-            it->second.lastStartTime = mCurrentBucketStartTimeNs;
-            it->second.lastDuration = 0;
         }
     }
 
+    // mDuration is updated in noteStop to the maximum duration that ended in the current bucket.
     if (mDuration != 0) {
+        DurationBucket info;
+        info.mBucketStartNs = mCurrentBucketStartTimeNs;
+        info.mBucketEndNs = currentBucketEndTimeNs;
+        info.mBucketNum = mCurrentBucketNum;
         info.mDuration = mDuration;
         (*output)[mEventKey].push_back(info);
-        addPastBucketToAnomalyTrackers(info.mDuration, info.mBucketNum);
         VLOG("  final duration for last bucket: %lld", (long long)mDuration);
     }
 
-    mDuration = 0;
-    if (hasOnGoingStartedEvent) {
-        for (int i = 1; i < numBucketsForward; i++) {
-            DurationBucket info;
-            info.mBucketStartNs = oldBucketStartTimeNs + mBucketSizeNs * i;
-            info.mBucketEndNs = endTime + mBucketSizeNs * i;
-            info.mBucketNum = mCurrentBucketNum + i;
-            info.mDuration = mBucketSizeNs;
-            (*output)[mEventKey].push_back(info);
-            addPastBucketToAnomalyTrackers(info.mDuration, info.mBucketNum);
-            VLOG("  filling gap bucket with duration %lld", (long long)mBucketSizeNs);
-        }
+    if (numBucketsForward > 0) {
+        mCurrentBucketStartTimeNs = fullBucketEnd + (numBucketsForward - 1) * mBucketSizeNs;
+        mCurrentBucketNum += numBucketsForward;
+    } else {  // We must be forming a partial bucket.
+        mCurrentBucketStartTimeNs = eventTimeNs;
     }
 
-    mCurrentBucketNum += numBucketsForward;
+    mDuration = 0;
     // If this tracker has no pending events, tell owner to remove.
     return !hasPendingEvent;
 }
 
+bool MaxDurationTracker::flushIfNeeded(
+        uint64_t eventTimeNs, unordered_map<MetricDimensionKey, vector<DurationBucket>>* output) {
+    if (eventTimeNs < getCurrentBucketEndTimeNs()) {
+        return false;
+    }
+    return flushCurrentBucket(eventTimeNs, output);
+}
+
 void MaxDurationTracker::onSlicedConditionMayChange(const uint64_t timestamp) {
     // Now for each of the on-going event, check if the condition has changed for them.
     for (auto& pair : mInfos) {
@@ -250,10 +226,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);
     }
@@ -267,7 +244,6 @@
 
 void MaxDurationTracker::noteConditionChanged(const HashableDimensionKey& key, bool conditionMet,
                                               const uint64_t timestamp) {
-    declareAnomalyIfAlarmExpired(timestamp);
     auto it = mInfos.find(key);
     if (it == mInfos.end()) {
         return;
@@ -297,7 +273,6 @@
     }
     if (it->second.lastDuration > mDuration) {
         mDuration = it->second.lastDuration;
-        detectAndDeclareAnomaly(timestamp, mCurrentBucketNum, mDuration);
     }
 }
 
diff --git a/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.h b/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.h
index 4d32a06..95863b6 100644
--- a/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.h
+++ b/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.h
@@ -28,10 +28,11 @@
 // they stop or bucket expires.
 class MaxDurationTracker : public DurationTracker {
 public:
-    MaxDurationTracker(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 bucketSizeNs, bool conditionSliced,
+    MaxDurationTracker(const ConfigKey& key, const int64_t& id, const MetricDimensionKey& eventKey,
+                       sp<ConditionWizard> wizard, 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);
 
     MaxDurationTracker(const MaxDurationTracker& tracker) = default;
@@ -47,6 +48,9 @@
     bool flushIfNeeded(
             uint64_t timestampNs,
             std::unordered_map<MetricDimensionKey, std::vector<DurationBucket>>* output) override;
+    bool flushCurrentBucket(
+            const uint64_t& eventTimeNs,
+            std::unordered_map<MetricDimensionKey, std::vector<DurationBucket>>*) override;
 
     void onSlicedConditionMayChange(const uint64_t timestamp) override;
     void onConditionChanged(bool condition, const uint64_t timestamp) override;
@@ -68,7 +72,6 @@
     FRIEND_TEST(MaxDurationTrackerTest, TestCrossBucketBoundary);
     FRIEND_TEST(MaxDurationTrackerTest, TestMaxDurationWithCondition);
     FRIEND_TEST(MaxDurationTrackerTest, TestStopAll);
-    FRIEND_TEST(MaxDurationTrackerTest, TestAnomalyDetection);
 };
 
 }  // namespace statsd
diff --git a/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.cpp b/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.cpp
index 0feae36..f583f91 100644
--- a/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.cpp
+++ b/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.cpp
@@ -26,12 +26,13 @@
 
 OringDurationTracker::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 bucketSizeNs, bool conditionSliced,
+        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)
     : DurationTracker(key, id, eventKey, wizard, conditionIndex, dimensionInCondition, nesting,
-                      currentBucketStartNs, bucketSizeNs, conditionSliced, anomalyTrackers),
+                      currentBucketStartNs, currentBucketNum, startTimeNs, bucketSizeNs,
+                      conditionSliced, anomalyTrackers),
       mStarted(),
       mPaused() {
     mLastStartTime = 0;
@@ -52,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",
@@ -100,7 +99,7 @@
         }
         if (mStarted.empty()) {
             mDuration += (timestamp - mLastStartTime);
-            detectAndDeclareAnomaly(timestamp, mCurrentBucketNum, mDuration);
+            detectAndDeclareAnomaly(timestamp, mCurrentBucketNum, mDuration + mDurationFullBucket);
             VLOG("record duration %lld, total %lld ", (long long)timestamp - mLastStartTime,
                  (long long)mDuration);
         }
@@ -125,7 +124,7 @@
         mDuration += (timestamp - mLastStartTime);
         VLOG("Oring Stop all: record duration %lld %lld ", (long long)timestamp - mLastStartTime,
              (long long)mDuration);
-        detectAndDeclareAnomaly(timestamp, mCurrentBucketNum, mDuration);
+        detectAndDeclareAnomaly(timestamp, mCurrentBucketNum, mDuration + mDurationFullBucket);
     }
 
     stopAnomalyAlarm();
@@ -134,51 +133,83 @@
     mConditionKeyMap.clear();
 }
 
-bool OringDurationTracker::flushIfNeeded(
-        uint64_t eventTime, unordered_map<MetricDimensionKey, vector<DurationBucket>>* output) {
-    if (eventTime < mCurrentBucketStartTimeNs + mBucketSizeNs) {
-        return false;
-    }
+bool OringDurationTracker::flushCurrentBucket(
+        const uint64_t& eventTimeNs,
+        std::unordered_map<MetricDimensionKey, std::vector<DurationBucket>>* output) {
     VLOG("OringDurationTracker Flushing.............");
-    // adjust the bucket start time
-    int numBucketsForward = (eventTime - mCurrentBucketStartTimeNs) / mBucketSizeNs;
-    DurationBucket current_info;
-    current_info.mBucketStartNs = mCurrentBucketStartTimeNs;
-    current_info.mBucketEndNs = current_info.mBucketStartNs + mBucketSizeNs;
-    current_info.mBucketNum = mCurrentBucketNum;
+
+    // Note that we have to mimic the bucket time changes we do in the
+    // MetricProducer#notifyAppUpgrade.
+
+    int numBucketsForward = 0;
+    uint64_t fullBucketEnd = getCurrentBucketEndTimeNs();
+    uint64_t currentBucketEndTimeNs;
+
+    if (eventTimeNs >= fullBucketEnd) {
+        numBucketsForward = 1 + (eventTimeNs - fullBucketEnd) / mBucketSizeNs;
+        currentBucketEndTimeNs = fullBucketEnd;
+    } else {
+        // This must be a partial bucket.
+        currentBucketEndTimeNs = eventTimeNs;
+    }
+
     // Process the current bucket.
     if (mStarted.size() > 0) {
-        mDuration += (current_info.mBucketEndNs - mLastStartTime);
+        mDuration += (currentBucketEndTimeNs - mLastStartTime);
     }
     if (mDuration > 0) {
+        DurationBucket current_info;
+        current_info.mBucketStartNs = mCurrentBucketStartTimeNs;
+        current_info.mBucketEndNs = currentBucketEndTimeNs;
+        current_info.mBucketNum = mCurrentBucketNum;
         current_info.mDuration = mDuration;
         (*output)[mEventKey].push_back(current_info);
-        addPastBucketToAnomalyTrackers(current_info.mDuration, current_info.mBucketNum);
+        mDurationFullBucket += mDuration;
+        if (eventTimeNs > fullBucketEnd) {
+            // End of full bucket, can send to anomaly tracker now.
+            addPastBucketToAnomalyTrackers(mDurationFullBucket, current_info.mBucketNum);
+            mDurationFullBucket = 0;
+        }
         VLOG("  duration: %lld", (long long)current_info.mDuration);
     }
 
     if (mStarted.size() > 0) {
         for (int i = 1; i < numBucketsForward; i++) {
             DurationBucket info;
-            info.mBucketStartNs = mCurrentBucketStartTimeNs + mBucketSizeNs * i;
+            info.mBucketStartNs = fullBucketEnd + mBucketSizeNs * (i - 1);
             info.mBucketEndNs = info.mBucketStartNs + mBucketSizeNs;
             info.mBucketNum = mCurrentBucketNum + i;
             info.mDuration = mBucketSizeNs;
             (*output)[mEventKey].push_back(info);
+            // Safe to send these buckets to anomaly tracker since they must be full buckets.
+            // If it's a partial bucket, numBucketsForward would be 0.
             addPastBucketToAnomalyTrackers(info.mDuration, info.mBucketNum);
             VLOG("  add filling bucket with duration %lld", (long long)info.mDuration);
         }
     }
-    mCurrentBucketStartTimeNs += numBucketsForward * mBucketSizeNs;
-    mCurrentBucketNum += numBucketsForward;
 
-    mLastStartTime = mCurrentBucketStartTimeNs;
     mDuration = 0;
 
+    if (numBucketsForward > 0) {
+        mCurrentBucketStartTimeNs = fullBucketEnd + (numBucketsForward - 1) * mBucketSizeNs;
+        mCurrentBucketNum += numBucketsForward;
+    } else {  // We must be forming a partial bucket.
+        mCurrentBucketStartTimeNs = eventTimeNs;
+    }
+    mLastStartTime = mCurrentBucketStartTimeNs;
+
     // if all stopped, then tell owner it's safe to remove this tracker.
     return mStarted.empty() && mPaused.empty();
 }
 
+bool OringDurationTracker::flushIfNeeded(
+        uint64_t eventTimeNs, unordered_map<MetricDimensionKey, vector<DurationBucket>>* output) {
+    if (eventTimeNs < getCurrentBucketEndTimeNs()) {
+        return false;
+    }
+    return flushCurrentBucket(eventTimeNs, output);
+}
+
 void OringDurationTracker::onSlicedConditionMayChange(const uint64_t timestamp) {
     declareAnomalyIfAlarmExpired(timestamp);
     vector<pair<HashableDimensionKey, int>> startedToPaused;
@@ -196,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());
@@ -211,7 +242,7 @@
             mDuration += (timestamp - mLastStartTime);
             VLOG("Duration add %lld , to %lld ", (long long)(timestamp - mLastStartTime),
                  (long long)mDuration);
-            detectAndDeclareAnomaly(timestamp, mCurrentBucketNum, mDuration);
+            detectAndDeclareAnomaly(timestamp, mCurrentBucketNum, mDuration + mDurationFullBucket);
         }
     }
 
@@ -228,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());
@@ -275,7 +306,7 @@
             mDuration += (timestamp - mLastStartTime);
             mPaused.insert(mStarted.begin(), mStarted.end());
             mStarted.clear();
-            detectAndDeclareAnomaly(timestamp, mCurrentBucketNum, mDuration);
+            detectAndDeclareAnomaly(timestamp, mCurrentBucketNum, mDuration + mDurationFullBucket);
         }
     }
     if (mStarted.empty()) {
@@ -298,7 +329,7 @@
     // As we move into the future, old buckets get overwritten (so their old data is erased).
 
     // Sum of past durations. Will change as we overwrite old buckets.
-    int64_t pastNs = mDuration;
+    int64_t pastNs = mDuration + mDurationFullBucket;
     pastNs += anomalyTracker.getSumOverPastBuckets(mEventKey);
 
     // How much of the threshold is still unaccounted after considering pastNs.
diff --git a/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.h b/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.h
index 75b5a81..07c1329 100644
--- a/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.h
+++ b/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.h
@@ -29,8 +29,9 @@
 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 bucketSizeNs, bool conditionSliced,
+                         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);
 
     OringDurationTracker(const OringDurationTracker& tracker) = default;
@@ -46,6 +47,9 @@
     void onSlicedConditionMayChange(const uint64_t timestamp) override;
     void onConditionChanged(bool condition, const uint64_t timestamp) override;
 
+    bool flushCurrentBucket(
+            const uint64_t& eventTimeNs,
+            std::unordered_map<MetricDimensionKey, std::vector<DurationBucket>>* output) override;
     bool flushIfNeeded(
             uint64_t timestampNs,
             std::unordered_map<MetricDimensionKey, std::vector<DurationBucket>>* output) override;
diff --git a/cmds/statsd/src/metrics/metrics_manager_util.cpp b/cmds/statsd/src/metrics/metrics_manager_util.cpp
index a0173ee..71e5c33 100644
--- a/cmds/statsd/src/metrics/metrics_manager_util.cpp
+++ b/cmds/statsd/src/metrics/metrics_manager_util.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#define DEBUG true  // STOPSHIP if true
+#define DEBUG false  // STOPSHIP if true
 #include "Log.h"
 
 #include "../condition/CombinationConditionTracker.h"
@@ -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,
@@ -497,10 +513,12 @@
         const int metricIndex = itr->second;
         sp<MetricProducer> metric = allMetricProducers[metricIndex];
         sp<AnomalyTracker> anomalyTracker = metric->addAnomalyTracker(alert);
-        if (anomalyTracker != nullptr) {
-            anomalyTrackerMap.insert(std::make_pair(alert.id(), allAnomalyTrackers.size()));
-            allAnomalyTrackers.push_back(anomalyTracker);
+        if (anomalyTracker == nullptr) {
+            // The ALOGW for this invalid alert was already displayed in addAnomalyTracker().
+            return false;
         }
+        anomalyTrackerMap.insert(std::make_pair(alert.id(), allAnomalyTrackers.size()));
+        allAnomalyTrackers.push_back(anomalyTracker);
     }
     for (int i = 0; i < config.subscription_size(); ++i) {
         const Subscription& subscription = config.subscription(i);
@@ -541,7 +559,7 @@
         ALOGE("initLogMatchingTrackers failed");
         return false;
     }
-    ALOGD("initLogMatchingTrackers succeed...");
+    VLOG("initLogMatchingTrackers succeed...");
 
     if (!initConditions(key, config, logTrackerMap, conditionTrackerMap, allConditionTrackers,
                         trackerToConditionMap)) {
diff --git a/cmds/statsd/src/packages/PackageInfoListener.h b/cmds/statsd/src/packages/PackageInfoListener.h
index df29eb0..03cb364 100644
--- a/cmds/statsd/src/packages/PackageInfoListener.h
+++ b/cmds/statsd/src/packages/PackageInfoListener.h
@@ -28,13 +28,15 @@
 public:
     // Uid map will notify this listener that the app with apk name and uid has been upgraded to
     // the specified version.
-    virtual void notifyAppUpgrade(const std::string& apk, const int uid, const int64_t version) = 0;
+    virtual void notifyAppUpgrade(const uint64_t& eventTimeNs, const std::string& apk,
+                                  const int uid, const int64_t version) = 0;
 
     // Notify interested listeners that the given apk and uid combination no longer exits.
-    virtual void notifyAppRemoved(const std::string& apk, const int uid) = 0;
+    virtual void notifyAppRemoved(const uint64_t& eventTimeNs, const std::string& apk,
+                                  const int uid) = 0;
 
     // Notify the listener that the UidMap snapshot is available.
-    virtual void onUidMapReceived() = 0;
+    virtual void onUidMapReceived(const uint64_t& eventTimeNs) = 0;
 };
 
 }  // namespace statsd
diff --git a/cmds/statsd/src/packages/UidMap.cpp b/cmds/statsd/src/packages/UidMap.cpp
index 91279661..e322ca4 100644
--- a/cmds/statsd/src/packages/UidMap.cpp
+++ b/cmds/statsd/src/packages/UidMap.cpp
@@ -16,6 +16,7 @@
 #define DEBUG true  // STOPSHIP if true
 #include "Log.h"
 
+#include "stats_log_util.h"
 #include "guardrail/StatsdStats.h"
 #include "packages/UidMap.h"
 
@@ -82,7 +83,7 @@
 
 void UidMap::updateMap(const vector<int32_t>& uid, const vector<int64_t>& versionCode,
                        const vector<String16>& packageName) {
-    updateMap(time(nullptr) * NS_PER_SEC, uid, versionCode, packageName);
+    updateMap(getElapsedRealtimeNs(), uid, versionCode, packageName);
 }
 
 void UidMap::updateMap(const int64_t& timestamp, const vector<int32_t>& uid,
@@ -98,7 +99,7 @@
         }
 
         auto snapshot = mOutput.add_snapshots();
-        snapshot->set_timestamp_nanos(timestamp);
+        snapshot->set_elapsed_timestamp_nanos(timestamp);
         for (size_t j = 0; j < uid.size(); j++) {
             auto t = snapshot->add_package_info();
             t->set_name(string(String8(packageName[j]).string()));
@@ -119,13 +120,13 @@
     for (auto weakPtr : broadcastList) {
         auto strongPtr = weakPtr.promote();
         if (strongPtr != NULL) {
-            strongPtr->onUidMapReceived();
+            strongPtr->onUidMapReceived(timestamp);
         }
     }
 }
 
 void UidMap::updateApp(const String16& app_16, const int32_t& uid, const int64_t& versionCode) {
-    updateApp(time(nullptr) * NS_PER_SEC, app_16, uid, versionCode);
+    updateApp(getElapsedRealtimeNs(), app_16, uid, versionCode);
 }
 
 void UidMap::updateApp(const int64_t& timestamp, const String16& app_16, const int32_t& uid,
@@ -137,7 +138,7 @@
 
         auto log = mOutput.add_changes();
         log->set_deletion(false);
-        log->set_timestamp_nanos(timestamp);
+        log->set_elapsed_timestamp_nanos(timestamp);
         log->set_app(appName);
         log->set_uid(uid);
         log->set_version(versionCode);
@@ -166,7 +167,7 @@
     for (auto weakPtr : broadcastList) {
         auto strongPtr = weakPtr.promote();
         if (strongPtr != NULL) {
-            strongPtr->notifyAppUpgrade(appName, uid, versionCode);
+            strongPtr->notifyAppUpgrade(timestamp, appName, uid, versionCode);
         }
     }
 }
@@ -194,7 +195,7 @@
 }
 
 void UidMap::removeApp(const String16& app_16, const int32_t& uid) {
-    removeApp(time(nullptr) * NS_PER_SEC, app_16, uid);
+    removeApp(getElapsedRealtimeNs(), app_16, uid);
 }
 
 void UidMap::getListenerListCopyLocked(vector<wp<PackageInfoListener>>* output) {
@@ -218,7 +219,7 @@
 
         auto log = mOutput.add_changes();
         log->set_deletion(true);
-        log->set_timestamp_nanos(timestamp);
+        log->set_elapsed_timestamp_nanos(timestamp);
         log->set_app(app);
         log->set_uid(uid);
         mBytesUsed += log->ByteSize();
@@ -239,7 +240,7 @@
     for (auto weakPtr : broadcastList) {
         auto strongPtr = weakPtr.promote();
         if (strongPtr != NULL) {
-            strongPtr->notifyAppRemoved(app, uid);
+            strongPtr->notifyAppRemoved(timestamp, app, uid);
         }
     }
 }
@@ -305,7 +306,7 @@
 }
 
 UidMapping UidMap::getOutput(const ConfigKey& key) {
-    return getOutput(time(nullptr) * NS_PER_SEC, key);
+    return getOutput(getElapsedRealtimeNs(), key);
 }
 
 UidMapping UidMap::getOutput(const int64_t& timestamp, const ConfigKey& key) {
@@ -316,13 +317,13 @@
     mLastUpdatePerConfigKey[key] = timestamp;
     int64_t newMin = getMinimumTimestampNs();
 
-    if (newMin > prevMin) {
+    if (newMin > prevMin) {  // Delete anything possible now that the minimum has moved forward.
         int64_t cutoff_nanos = newMin;
         auto snapshots = mOutput.mutable_snapshots();
         auto it_snapshots = snapshots->cbegin();
         while (it_snapshots != snapshots->cend()) {
-            if (it_snapshots->timestamp_nanos() < cutoff_nanos) {
-                // it_snapshots now points to the following element.
+            if (it_snapshots->elapsed_timestamp_nanos() < cutoff_nanos) {
+                // it_snapshots points to the following element after erasing.
                 it_snapshots = snapshots->erase(it_snapshots);
             } else {
                 ++it_snapshots;
@@ -331,8 +332,8 @@
         auto deltas = mOutput.mutable_changes();
         auto it_deltas = deltas->cbegin();
         while (it_deltas != deltas->cend()) {
-            if (it_deltas->timestamp_nanos() < cutoff_nanos) {
-                // it_deltas now points to the following element.
+            if (it_deltas->elapsed_timestamp_nanos() < cutoff_nanos) {
+                // it_snapshots points to the following element after erasing.
                 it_deltas = deltas->erase(it_deltas);
             } else {
                 ++it_deltas;
@@ -343,7 +344,7 @@
             // Produce another snapshot. This results in extra data being uploaded but helps
             // ensure we can re-construct the UID->app name, versionCode mapping in server.
             auto snapshot = mOutput.add_snapshots();
-            snapshot->set_timestamp_nanos(timestamp);
+            snapshot->set_elapsed_timestamp_nanos(timestamp);
             for (auto it : mMap) {
                 auto t = snapshot->add_package_info();
                 t->set_name(it.second.packageName);
diff --git a/cmds/statsd/src/packages/UidMap.h b/cmds/statsd/src/packages/UidMap.h
index 3304f6c..f1da452 100644
--- a/cmds/statsd/src/packages/UidMap.h
+++ b/cmds/statsd/src/packages/UidMap.h
@@ -91,7 +91,7 @@
     void removeIsolatedUid(int isolatedUid, int parentUid);
 
     // Returns the host uid if it exists. Otherwise, returns the same uid that was passed-in.
-    int getHostUidOrSelf(int uid) const;
+    virtual int getHostUidOrSelf(int uid) const;
 
     // Gets the output. If every config key has received the output, then the output is cleared.
     UidMapping getOutput(const ConfigKey& key);
diff --git a/cmds/statsd/src/stats_log.proto b/cmds/statsd/src/stats_log.proto
index af21ca4..b427485 100644
--- a/cmds/statsd/src/stats_log.proto
+++ b/cmds/statsd/src/stats_log.proto
@@ -42,15 +42,17 @@
 }
 
 message EventMetricData {
-  optional int64 timestamp_nanos = 1;
+  optional int64 elapsed_timestamp_nanos = 1;
 
   optional Atom atom = 2;
+
+  optional int64 wall_clock_timestamp_sec = 3;
 }
 
 message CountBucketInfo {
-  optional int64 start_bucket_nanos = 1;
+  optional int64 start_bucket_elapsed_nanos = 1;
 
-  optional int64 end_bucket_nanos = 2;
+  optional int64 end_bucket_elapsed_nanos = 2;
 
   optional int64 count = 3;
 }
@@ -64,9 +66,9 @@
 }
 
 message DurationBucketInfo {
-  optional int64 start_bucket_nanos = 1;
+  optional int64 start_bucket_elapsed_nanos = 1;
 
-  optional int64 end_bucket_nanos = 2;
+  optional int64 end_bucket_elapsed_nanos = 2;
 
   optional int64 duration_nanos = 3;
 }
@@ -80,9 +82,9 @@
 }
 
 message ValueBucketInfo {
-  optional int64 start_bucket_nanos = 1;
+  optional int64 start_bucket_elapsed_nanos = 1;
 
-  optional int64 end_bucket_nanos = 2;
+  optional int64 end_bucket_elapsed_nanos = 2;
 
   optional int64 value = 3;
 }
@@ -102,7 +104,7 @@
 
   repeated Atom atom = 3;
 
-  repeated int64 timestamp_nanos = 4;
+  repeated int64 elapsed_timestamp_nanos = 4;
 }
 
 message GaugeMetricData {
@@ -122,7 +124,7 @@
 
       optional int32 uid = 3;
     }
-    optional int64 timestamp_nanos = 1;
+    optional int64 elapsed_timestamp_nanos = 1;
 
     repeated PackageInfo package_info = 2;
   }
@@ -131,7 +133,7 @@
   message Change {
     optional bool deletion = 1;
 
-    optional int64 timestamp_nanos = 2;
+    optional int64 elapsed_timestamp_nanos = 2;
     optional string app = 3;
     optional int32 uid = 4;
 
@@ -143,9 +145,7 @@
 message StatsLogReport {
   optional int64 metric_id = 1;
 
-  optional int64 start_report_nanos = 2;
-
-  optional int64 end_report_nanos = 3;
+  // Fields 2 and 3 are reserved.
 
   message EventMetricDataWrapper {
     repeated EventMetricData data = 1;
@@ -177,6 +177,10 @@
   repeated StatsLogReport metrics = 1;
 
   optional UidMapping uid_map = 2;
+
+  optional int64 last_report_elapsed_nanos = 3;
+
+  optional int64 current_report_elapsed_nanos = 4;
 }
 
 message ConfigMetricsReportList {
diff --git a/cmds/statsd/src/stats_log_util.cpp b/cmds/statsd/src/stats_log_util.cpp
index 6c61400..30eef4f 100644
--- a/cmds/statsd/src/stats_log_util.cpp
+++ b/cmds/statsd/src/stats_log_util.cpp
@@ -16,9 +16,13 @@
 
 #include "stats_log_util.h"
 
+#include <logd/LogEvent.h>
+#include <private/android_filesystem_config.h>
+#include <utils/Log.h>
 #include <set>
 #include <stack>
 #include <utils/Log.h>
+#include <utils/SystemClock.h>
 
 using android::util::FIELD_COUNT_REPEATED;
 using android::util::FIELD_TYPE_BOOL;
@@ -38,12 +42,11 @@
 const int DIMENSIONS_VALUE_VALUE_STR = 2;
 const int DIMENSIONS_VALUE_VALUE_INT = 3;
 const int DIMENSIONS_VALUE_VALUE_LONG = 4;
-const int DIMENSIONS_VALUE_VALUE_BOOL = 5;
+// const int DIMENSIONS_VALUE_VALUE_BOOL = 5; // logd doesn't have bool data type.
 const int DIMENSIONS_VALUE_VALUE_FLOAT = 6;
 const int DIMENSIONS_VALUE_VALUE_TUPLE = 7;
 
-// for MessageValue Proto
-const int FIELD_ID_FIELD_VALUE_IN_MESSAGE_VALUE_PROTO = 1;
+const int DIMENSIONS_VALUE_TUPLE_VALUE = 1;
 
 // for PulledAtomStats proto
 const int FIELD_ID_PULLED_ATOM_STATS = 10;
@@ -51,186 +54,175 @@
 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;
-
-void writeDimensionsValueProtoToStream(const DimensionsValue& dimensionsValue,
-                                       ProtoOutputStream* protoOutput) {
-    if (!dimensionsValue.has_field()) {
-        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;
-    }
-}
-
-// for Field Proto
-const int FIELD_FIELD = 1;
-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());
+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;
         }
-        it->second.insert(childNode);
-        addOrUpdateChildrenMap(parentNode, child, childrenMap);
+
+        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;
+        }
     }
 }
 
-void addOrUpdateChildrenMap(
-    const Field& field,
-    std::map<Field, std::set<Field, FieldCmp>, FieldCmp> *childrenMap) {
-    Field root;
-    addOrUpdateChildrenMap(root, field, childrenMap);
+}  // namespace
+
+void writeDimensionToProto(const HashableDimensionKey& dimension, ProtoOutputStream* protoOutput) {
+    if (dimension.getValues().size() == 0) {
+        return;
+    }
+    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);
 }
 
-} // namespace
+// 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;
+        }
 
-void writeFieldValueTreeToStream(const FieldValueMap &fieldValueMap,
+        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 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 TimeUnitToBucketSizeInMillisGuardrailed(int uid, TimeUnit unit) {
+    int64_t bucketSizeMillis = TimeUnitToBucketSizeInMillis(unit);
+    if (bucketSizeMillis > 1000 && bucketSizeMillis < 5 * 60 * 1000LL && uid != AID_SHELL) {
+        bucketSizeMillis = 5 * 60 * 1000LL;
     }
+    return bucketSizeMillis;
 }
 
 int64_t TimeUnitToBucketSizeInMillis(TimeUnit unit) {
@@ -274,6 +266,30 @@
     protoOutput->end(token);
 }
 
+int64_t getElapsedRealtimeNs() {
+    return ::android::elapsedRealtimeNano();
+}
+
+int64_t getElapsedRealtimeSec() {
+    return ::android::elapsedRealtimeNano() / NS_PER_SEC;
+}
+
+int64_t getElapsedRealtimeMillis() {
+    return ::android::elapsedRealtime();
+}
+
+int64_t getWallClockNs() {
+    return time(nullptr) * NS_PER_SEC;
+}
+
+int64_t getWallClockSec() {
+    return time(nullptr);
+}
+
+int64_t getWallClockMillis() {
+    return time(nullptr) * MS_PER_SEC;
+}
+
 }  // namespace statsd
 }  // namespace os
-}  // namespace android
\ No newline at end of file
+}  // namespace android
diff --git a/cmds/statsd/src/stats_log_util.h b/cmds/statsd/src/stats_log_util.h
index cee9200..6a5123d 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,20 +27,36 @@
 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 with a guardrail on
+// bucket size.
+int64_t TimeUnitToBucketSizeInMillisGuardrailed(int uid, TimeUnit unit);
 
 // Convert the TimeUnit enum to the bucket size in millis.
 int64_t TimeUnitToBucketSizeInMillis(TimeUnit unit);
 
+// Gets the elapsed timestamp in ns.
+int64_t getElapsedRealtimeNs();
+
+// Gets the elapsed timestamp in millis.
+int64_t getElapsedRealtimeMillis();
+
+// Gets the elapsed timestamp in seconds.
+int64_t getElapsedRealtimeSec();
+
+// Gets the wall clock timestamp in ns.
+int64_t getWallClockNs();
+
+// Gets the wall clock timestamp in millis.
+int64_t getWallClockMillis();
+
+// Gets the wall clock timestamp in seconds.
+int64_t getWallClockSec();
+
 // Helper function to write PulledAtomStats to ProtoOutputStream
 void writePullerStatsToStream(const std::pair<int, StatsdStats::PulledAtomStats>& pair,
                               util::ProtoOutputStream* protoOutput);
@@ -58,4 +75,4 @@
 
 }  // namespace statsd
 }  // namespace os
-}  // namespace android
\ No newline at end of file
+}  // namespace android
diff --git a/cmds/statsd/src/statsd_config.proto b/cmds/statsd/src/statsd_config.proto
index 3eaf7a1..5a326a4 100644
--- a/cmds/statsd/src/statsd_config.proto
+++ b/cmds/statsd/src/statsd_config.proto
@@ -275,6 +275,12 @@
 
 message IncidentdDetails {
   repeated int32 section = 1;
+
+  enum Destination {
+    AUTOMATIC = 0;
+    EXPLICIT = 1;
+  }
+  optional Destination dest = 2;
 }
 
 message PerfettoDetails {
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/storage/StorageManager.cpp b/cmds/statsd/src/storage/StorageManager.cpp
index 00d8658..6a1db72 100644
--- a/cmds/statsd/src/storage/StorageManager.cpp
+++ b/cmds/statsd/src/storage/StorageManager.cpp
@@ -14,12 +14,13 @@
  * limitations under the License.
  */
 
-#define DEBUG true  // STOPSHIP if true
+#define DEBUG false  // STOPSHIP if true
 #include "Log.h"
 
 #include "android-base/stringprintf.h"
 #include "guardrail/StatsdStats.h"
 #include "storage/StorageManager.h"
+#include "stats_log_util.h"
 
 #include <android-base/file.h>
 #include <dirent.h>
@@ -252,7 +253,7 @@
         string file_name = getFilePath(path, timestamp, uid, configID);
 
         // Check for timestamp and delete if it's too old.
-        long fileAge = time(nullptr) - timestamp;
+        long fileAge = getWallClockSec() - timestamp;
         if (fileAge > StatsdStats::kMaxAgeSecond) {
             deleteFile(file_name.c_str());
         }
diff --git a/cmds/statsd/src/subscriber/IncidentdReporter.cpp b/cmds/statsd/src/subscriber/IncidentdReporter.cpp
new file mode 100644
index 0000000..d9a8fc8
--- /dev/null
+++ b/cmds/statsd/src/subscriber/IncidentdReporter.cpp
@@ -0,0 +1,78 @@
+/*
+ * 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 true
+#include "Log.h"
+
+#include "IncidentdReporter.h"
+#include "frameworks/base/libs/incident/proto/android/os/header.pb.h"
+
+#include <android/os/IIncidentManager.h>
+#include <android/os/IncidentReportArgs.h>
+#include <binder/IBinder.h>
+#include <binder/IServiceManager.h>
+
+namespace android {
+namespace os {
+namespace statsd {
+
+bool GenerateIncidentReport(const IncidentdDetails& config, const Alert& alert,
+                            const ConfigKey& configKey) {
+    if (config.section_size() == 0) {
+        VLOG("The alert %lld contains zero section in config(%d,%lld)", alert.id(),
+            configKey.GetUid(), (long long) configKey.GetId());
+        return false;
+    }
+
+    IncidentReportArgs incidentReport;
+
+    android::os::IncidentHeaderProto header;
+    header.set_alert_id(alert.id());
+    header.mutable_config_key()->set_uid(configKey.GetUid());
+    header.mutable_config_key()->set_id(configKey.GetId());
+    incidentReport.addHeader(header);
+
+    for (int i = 0; i < config.section_size(); i++) {
+        incidentReport.addSection(config.section(i));
+    }
+
+    uint8_t dest;
+    switch (config.dest()) {
+        case IncidentdDetails_Destination_AUTOMATIC:
+            dest = android::os::DEST_AUTOMATIC;
+            break;
+        case IncidentdDetails_Destination_EXPLICIT:
+            dest = android::os::DEST_EXPLICIT;
+            break;
+        default:
+            dest = android::os::DEST_AUTOMATIC;
+    }
+    incidentReport.setDest(dest);
+
+    sp<IIncidentManager> service = interface_cast<IIncidentManager>(
+            defaultServiceManager()->getService(android::String16("incident")));
+    if (service == nullptr) {
+        ALOGW("Failed to fetch incident service.");
+        return false;
+    }
+    VLOG("Calling incidentd %p", service.get());
+    binder::Status s = service->reportIncident(incidentReport);
+    VLOG("Report incident status: %s", s.toString8().string());
+    return s.isOk();
+}
+
+}  // namespace statsd
+}  // namespace os
+}  // namespace android
diff --git a/cmds/statsd/src/subscriber/IncidentdReporter.h b/cmds/statsd/src/subscriber/IncidentdReporter.h
new file mode 100644
index 0000000..229ed77
--- /dev/null
+++ b/cmds/statsd/src/subscriber/IncidentdReporter.h
@@ -0,0 +1,34 @@
+/*
+ * 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 "config/ConfigKey.h"
+#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"  // Alert, IncidentdDetails
+
+namespace android {
+namespace os {
+namespace statsd {
+
+/**
+ * Calls incidentd to trigger an incident report and put in dropbox for uploading.
+ */
+bool GenerateIncidentReport(const IncidentdDetails& config, const Alert& alert,
+                            const ConfigKey& configKey);
+
+}  // namespace statsd
+}  // namespace os
+}  // namespace android
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..0228004 100644
--- a/cmds/statsd/tests/e2e/Attribution_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/Attribution_e2e_test.cpp
@@ -47,7 +47,7 @@
     *countMetric->mutable_dimensions_in_what() =
         CreateAttributionUidAndTagDimensions(
             android::util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
-    countMetric->set_bucket(ONE_MINUTE);
+    countMetric->set_bucket(FIVE_MINUTES);
     return config;
 }
 
@@ -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);
@@ -159,11 +163,11 @@
             "App1");
     EXPECT_EQ(data.bucket_info_size(), 2);
     EXPECT_EQ(data.bucket_info(0).count(), 2);
-    EXPECT_EQ(data.bucket_info(0).start_bucket_nanos(), bucketStartTimeNs);
-    EXPECT_EQ(data.bucket_info(0).end_bucket_nanos(), bucketStartTimeNs + bucketSizeNs);
+    EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
+    EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs);
     EXPECT_EQ(data.bucket_info(1).count(), 1);
-    EXPECT_EQ(data.bucket_info(1).start_bucket_nanos(), bucketStartTimeNs + 2 * bucketSizeNs);
-    EXPECT_EQ(data.bucket_info(1).end_bucket_nanos(), bucketStartTimeNs + 3 * bucketSizeNs);
+    EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), bucketStartTimeNs + 2 * bucketSizeNs);
+    EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), bucketStartTimeNs + 3 * bucketSizeNs);
 
     data = countMetrics.data(1);
     ValidateAttributionUidAndTagDimension(
@@ -171,11 +175,11 @@
             "GMSCoreModule1");
     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);
-    EXPECT_EQ(data.bucket_info(0).end_bucket_nanos(), bucketStartTimeNs + bucketSizeNs);
+    EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
+    EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs);
     EXPECT_EQ(data.bucket_info(1).count(), 1);
-    EXPECT_EQ(data.bucket_info(1).start_bucket_nanos(), bucketStartTimeNs + bucketSizeNs);
-    EXPECT_EQ(data.bucket_info(1).end_bucket_nanos(), bucketStartTimeNs + 2 * bucketSizeNs);
+    EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs);
+    EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), bucketStartTimeNs + 2 * bucketSizeNs);
 
     data = countMetrics.data(2);
     ValidateAttributionUidAndTagDimension(
@@ -183,8 +187,8 @@
             "GMSCoreModule3");
     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 + 3 * bucketSizeNs);
-    EXPECT_EQ(data.bucket_info(0).end_bucket_nanos(), bucketStartTimeNs + 4 * bucketSizeNs);
+    EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs + 3 * bucketSizeNs);
+    EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + 4 * bucketSizeNs);
 
     data = countMetrics.data(3);
     ValidateAttributionUidAndTagDimension(
@@ -192,8 +196,8 @@
             "GMSCoreModule2");
     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 + 2 * bucketSizeNs);
-    EXPECT_EQ(data.bucket_info(0).end_bucket_nanos(), bucketStartTimeNs + 3 * bucketSizeNs);
+    EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs + 2 * bucketSizeNs);
+    EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + 3 * bucketSizeNs);
 }
 
 #else
@@ -202,4 +206,4 @@
 
 }  // namespace statsd
 }  // namespace os
-}  // namespace android
\ No newline at end of file
+}  // namespace android
diff --git a/cmds/statsd/tests/e2e/DimensionInCondition_e2e_test.cpp b/cmds/statsd/tests/e2e/DimensionInCondition_e2e_test.cpp
index b5d48ef..4dffd13 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,11 +57,11 @@
     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);
+    metric->set_bucket(FIVE_MINUTES);
     return config;
 }
 
@@ -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,8 +142,8 @@
     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).end_bucket_nanos(), bucketStartTimeNs + bucketSizeNs);
+    EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
+    EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_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);
     EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1);
@@ -158,44 +153,47 @@
     data = countMetrics.data(1);
     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).end_bucket_nanos(), bucketStartTimeNs + bucketSizeNs);
+    EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
+    EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_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);
     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);
     EXPECT_EQ(data.bucket_info(0).count(), 3);
-    EXPECT_EQ(data.bucket_info(0).start_bucket_nanos(), bucketStartTimeNs);
-    EXPECT_EQ(data.bucket_info(0).end_bucket_nanos(), bucketStartTimeNs + bucketSizeNs);
+    EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
+    EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_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);
     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);
     EXPECT_EQ(data.bucket_info(0).count(), 2);
-    EXPECT_EQ(data.bucket_info(0).start_bucket_nanos(), bucketStartTimeNs);
-    EXPECT_EQ(data.bucket_info(0).end_bucket_nanos(), bucketStartTimeNs + bucketSizeNs);
+    EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
+    EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs);
     EXPECT_EQ(data.bucket_info(1).count(), 1);
-    EXPECT_EQ(data.bucket_info(1).start_bucket_nanos(), bucketStartTimeNs + bucketSizeNs);
-    EXPECT_EQ(data.bucket_info(1).end_bucket_nanos(), bucketStartTimeNs + 2 * bucketSizeNs);
+    EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs);
+    EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), bucketStartTimeNs + 2 * 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);
     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);
     EXPECT_EQ(data.bucket_info(0).count(), 2);
-    EXPECT_EQ(data.bucket_info(0).start_bucket_nanos(), bucketStartTimeNs + bucketSizeNs);
-    EXPECT_EQ(data.bucket_info(0).end_bucket_nanos(), bucketStartTimeNs + 2 * bucketSizeNs);
+    EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs);
+    EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + 2 * 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);
     EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1);
@@ -205,24 +203,26 @@
     data = countMetrics.data(5);
     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).end_bucket_nanos(), bucketStartTimeNs + bucketSizeNs);
+    EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
+    EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_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);
     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);
     EXPECT_EQ(data.bucket_info(0).count(), 1);
-    EXPECT_EQ(data.bucket_info(0).start_bucket_nanos(), bucketStartTimeNs);
-    EXPECT_EQ(data.bucket_info(0).end_bucket_nanos(), bucketStartTimeNs + bucketSizeNs);
+    EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
+    EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_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);
     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;
@@ -252,12 +252,12 @@
     addPredicateToPredicateCombination(isSyncingPredicate, combinationPredicate);
 
     auto metric = config.add_count_metric();
-    metric->set_bucket(ONE_MINUTE);
+    metric->set_bucket(FIVE_MINUTES);
     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);
@@ -355,20 +358,20 @@
     EXPECT_FALSE(data.dimensions_in_condition().has_field());
     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).end_bucket_nanos(), bucketStartTimeNs + bucketSizeNs);
+    EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
+    EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs);
 
     data = countMetrics.data(1);
     EXPECT_EQ(data.dimensions_in_what().field(), android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED);
     EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1);
     EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1);
     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);
-    EXPECT_EQ(data.bucket_info(0).end_bucket_nanos(), bucketStartTimeNs + bucketSizeNs);
+    EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
+    EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs);
 
     data = countMetrics.data(2);
     EXPECT_EQ(data.dimensions_in_what().field(), android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED);
@@ -378,23 +381,23 @@
     EXPECT_FALSE(data.dimensions_in_condition().has_field());
     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);
-    EXPECT_EQ(data.bucket_info(0).end_bucket_nanos(), bucketStartTimeNs + bucketSizeNs);
+    EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
+    EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs);
 
     data = countMetrics.data(3);
     EXPECT_EQ(data.dimensions_in_what().field(), android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED);
     EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1);
     EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1);
     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);
-    EXPECT_EQ(data.bucket_info(0).end_bucket_nanos(), bucketStartTimeNs + bucketSizeNs);
+    EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
+    EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs);
     EXPECT_EQ(data.bucket_info(1).count(), 1);
-    EXPECT_EQ(data.bucket_info(1).start_bucket_nanos(), bucketStartTimeNs + bucketSizeNs);
-    EXPECT_EQ(data.bucket_info(1).end_bucket_nanos(), bucketStartTimeNs + 2 * bucketSizeNs);
+    EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs);
+    EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), bucketStartTimeNs + 2 * bucketSizeNs);
 
     data = countMetrics.data(4);
     EXPECT_EQ(data.dimensions_in_what().field(), android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED);
@@ -404,8 +407,8 @@
     EXPECT_FALSE(data.dimensions_in_condition().has_field());
     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 + bucketSizeNs);
-    EXPECT_EQ(data.bucket_info(0).end_bucket_nanos(), bucketStartTimeNs + 2 * bucketSizeNs);
+    EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs);
+    EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + 2 * bucketSizeNs);
 }
 
 namespace {
@@ -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;
@@ -438,7 +441,7 @@
     addPredicateToPredicateCombination(isSyncingPredicate, combinationPredicate);
 
     auto metric = config.add_duration_metric();
-    metric->set_bucket(ONE_MINUTE);
+    metric->set_bucket(FIVE_MINUTES);
     metric->set_id(StringToId("BatterySaverModeDurationMetric"));
     metric->set_what(inBatterySaverModePredicate.id());
     metric->set_condition(combinationPredicate->id());
@@ -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);
@@ -526,35 +531,35 @@
         EXPECT_FALSE(data.dimensions_in_condition().has_field());
         EXPECT_EQ(data.bucket_info_size(), 2);
         EXPECT_EQ(data.bucket_info(0).duration_nanos(), 9);
-        EXPECT_EQ(data.bucket_info(0).start_bucket_nanos(), bucketStartTimeNs);
-        EXPECT_EQ(data.bucket_info(0).end_bucket_nanos(), bucketStartTimeNs + bucketSizeNs);
+        EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
+        EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs);
         EXPECT_EQ(data.bucket_info(1).duration_nanos(), 30);
-        EXPECT_EQ(data.bucket_info(1).start_bucket_nanos(), bucketStartTimeNs + bucketSizeNs);
-        EXPECT_EQ(data.bucket_info(1).end_bucket_nanos(), bucketStartTimeNs + 2 * bucketSizeNs);
+        EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs);
+        EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), bucketStartTimeNs + 2 * bucketSizeNs);
 
         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);
-        EXPECT_EQ(data.bucket_info(0).end_bucket_nanos(), bucketStartTimeNs + bucketSizeNs);
+        EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
+        EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs);
         EXPECT_EQ(data.bucket_info(1).duration_nanos(), 300);
-        EXPECT_EQ(data.bucket_info(1).start_bucket_nanos(), bucketStartTimeNs + bucketSizeNs);
-        EXPECT_EQ(data.bucket_info(1).end_bucket_nanos(), bucketStartTimeNs + 2 * bucketSizeNs);
+        EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs);
+        EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), bucketStartTimeNs + 2 * bucketSizeNs);
 
         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);
-        EXPECT_EQ(data.bucket_info(0).end_bucket_nanos(), bucketStartTimeNs + bucketSizeNs);
+        EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
+        EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs);
         EXPECT_EQ(data.bucket_info(1).duration_nanos(), 700);
-        EXPECT_EQ(data.bucket_info(1).start_bucket_nanos(), bucketStartTimeNs + bucketSizeNs);
-        EXPECT_EQ(data.bucket_info(1).end_bucket_nanos(), bucketStartTimeNs + 2 * bucketSizeNs);
+        EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs);
+        EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), bucketStartTimeNs + 2 * bucketSizeNs);
     }
 }
 
@@ -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;
@@ -590,12 +595,12 @@
     addPredicateToPredicateCombination(isSyncingPredicate, combinationPredicate);
 
     auto metric = config.add_duration_metric();
-    metric->set_bucket(ONE_MINUTE);
+    metric->set_bucket(FIVE_MINUTES);
     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);
@@ -685,34 +693,34 @@
         EXPECT_FALSE(data.dimensions_in_condition().has_field());
         EXPECT_EQ(data.bucket_info_size(), 1);
         EXPECT_EQ(data.bucket_info(0).duration_nanos(), 9);
-        EXPECT_EQ(data.bucket_info(0).start_bucket_nanos(), bucketStartTimeNs);
-        EXPECT_EQ(data.bucket_info(0).end_bucket_nanos(), bucketStartTimeNs + bucketSizeNs);
+        EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
+        EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs);
 
         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);
-        EXPECT_EQ(data.bucket_info(0).end_bucket_nanos(), bucketStartTimeNs + bucketSizeNs);
+        EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
+        EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs);
         EXPECT_EQ(data.bucket_info(1).duration_nanos(), 100);
-        EXPECT_EQ(data.bucket_info(1).start_bucket_nanos(), bucketStartTimeNs + bucketSizeNs);
-        EXPECT_EQ(data.bucket_info(1).end_bucket_nanos(), bucketStartTimeNs + 2 * bucketSizeNs);
+        EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs);
+        EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), bucketStartTimeNs + 2 * bucketSizeNs);
 
         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);
-        EXPECT_EQ(data.bucket_info(0).end_bucket_nanos(), bucketStartTimeNs + bucketSizeNs);
+        EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
+        EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs);
         EXPECT_EQ(data.bucket_info(1).duration_nanos(), 700);
-        EXPECT_EQ(data.bucket_info(1).start_bucket_nanos(), bucketStartTimeNs + bucketSizeNs);
-        EXPECT_EQ(data.bucket_info(1).end_bucket_nanos(), bucketStartTimeNs + 2 * bucketSizeNs);
+        EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs);
+        EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), bucketStartTimeNs + 2 * bucketSizeNs);
     }
 }
 
@@ -722,4 +730,4 @@
 
 }  // namespace statsd
 }  // namespace os
-}  // namespace android
\ No newline at end of file
+}  // namespace android
diff --git a/cmds/statsd/tests/e2e/GaugeMetric_e2e_test.cpp b/cmds/statsd/tests/e2e/GaugeMetric_e2e_test.cpp
index a80fdc5..3843e0a 100644
--- a/cmds/statsd/tests/e2e/GaugeMetric_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/GaugeMetric_e2e_test.cpp
@@ -53,7 +53,7 @@
     fieldMatcher->add_child()->set_field(7);  // activity_start_msec(int64)
     *gaugeMetric->mutable_dimensions_in_what() =
         CreateDimensions(android::util::APP_START_CHANGED, {1 /* uid field */ });
-    gaugeMetric->set_bucket(ONE_MINUTE);
+    gaugeMetric->set_bucket(FIVE_MINUTES);
 
     auto links = gaugeMetric->add_links();
     links->set_condition(isInBackgroundPredicate.id());
@@ -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;
@@ -158,21 +161,21 @@
     EXPECT_EQ(data.bucket_info(0).end_bucket_nanos(), bucketStartTimeNs + bucketSizeNs);
     EXPECT_EQ(data.bucket_info(0).atom(0).app_start_changed().type(), AppStartChanged::HOT);
     EXPECT_EQ(data.bucket_info(0).atom(0).app_start_changed().activity_name(), "activity_name2");
-    EXPECT_EQ(data.bucket_info(0).atom(0).app_start_changed().activity_start_msec(), 102L);
+    EXPECT_EQ(data.bucket_info(0).atom(0).app_start_changed().activity_start_millis(), 102L);
 
     EXPECT_EQ(data.bucket_info(1).atom_size(), 1);
     EXPECT_EQ(data.bucket_info(1).start_bucket_nanos(), bucketStartTimeNs + bucketSizeNs);
     EXPECT_EQ(data.bucket_info(1).end_bucket_nanos(), bucketStartTimeNs + 2 * bucketSizeNs);
     EXPECT_EQ(data.bucket_info(1).atom(0).app_start_changed().type(), AppStartChanged::WARM);
     EXPECT_EQ(data.bucket_info(1).atom(0).app_start_changed().activity_name(), "activity_name4");
-    EXPECT_EQ(data.bucket_info(1).atom(0).app_start_changed().activity_start_msec(), 104L);
+    EXPECT_EQ(data.bucket_info(1).atom(0).app_start_changed().activity_start_millis(), 104L);
 
     EXPECT_EQ(data.bucket_info(2).atom_size(), 1);
     EXPECT_EQ(data.bucket_info(2).start_bucket_nanos(), bucketStartTimeNs + 2 * bucketSizeNs);
     EXPECT_EQ(data.bucket_info(2).end_bucket_nanos(), bucketStartTimeNs + 3 * bucketSizeNs);
     EXPECT_EQ(data.bucket_info(2).atom(0).app_start_changed().type(), AppStartChanged::COLD);
     EXPECT_EQ(data.bucket_info(2).atom(0).app_start_changed().activity_name(), "activity_name5");
-    EXPECT_EQ(data.bucket_info(2).atom(0).app_start_changed().activity_start_msec(), 105L);
+    EXPECT_EQ(data.bucket_info(2).atom(0).app_start_changed().activity_start_millis(), 105L);
 
     data = gaugeMetrics.data(1);
 
@@ -186,7 +189,7 @@
     EXPECT_EQ(data.bucket_info(0).end_bucket_nanos(), bucketStartTimeNs + 3 * bucketSizeNs);
     EXPECT_EQ(data.bucket_info(0).atom(0).app_start_changed().type(), AppStartChanged::COLD);
     EXPECT_EQ(data.bucket_info(0).atom(0).app_start_changed().activity_name(), "activity_name7");
-    EXPECT_EQ(data.bucket_info(0).atom(0).app_start_changed().activity_start_msec(), 201L);
+    EXPECT_EQ(data.bucket_info(0).atom(0).app_start_changed().activity_start_millis(), 201L);
 }
 
 #else
@@ -195,4 +198,4 @@
 
 }  // namespace statsd
 }  // namespace os
-}  // namespace android
\ No newline at end of file
+}  // namespace android
diff --git a/cmds/statsd/tests/e2e/MetricConditionLink_e2e_test.cpp b/cmds/statsd/tests/e2e/MetricConditionLink_e2e_test.cpp
index 233031c..1b51780 100644
--- a/cmds/statsd/tests/e2e/MetricConditionLink_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/MetricConditionLink_e2e_test.cpp
@@ -71,7 +71,7 @@
     // The metric is dimensioning by uid only.
     *countMetric->mutable_dimensions_in_what() =
         CreateDimensions(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, {1});
-    countMetric->set_bucket(ONE_MINUTE);
+    countMetric->set_bucket(FIVE_MINUTES);
 
     // Links between crash atom and condition of app is in syncing.
     auto links = countMetric->add_links();
@@ -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);
@@ -233,4 +337,4 @@
 
 }  // namespace statsd
 }  // namespace os
-}  // namespace android
\ No newline at end of file
+}  // namespace android
diff --git a/cmds/statsd/tests/e2e/WakelockDuration_e2e_test.cpp b/cmds/statsd/tests/e2e/WakelockDuration_e2e_test.cpp
index 1186a16..efdab98 100644
--- a/cmds/statsd/tests/e2e/WakelockDuration_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/WakelockDuration_e2e_test.cpp
@@ -40,9 +40,11 @@
 
     auto holdingWakelockPredicate = CreateHoldingWakelockPredicate();
     // The predicate is dimensioning by any attribution node and both by uid and tag.
-    *holdingWakelockPredicate.mutable_simple_predicate()->mutable_dimensions() =
-        CreateAttributionUidAndTagDimensions(
+    FieldMatcher dimensions = CreateAttributionUidAndTagDimensions(
             android::util::WAKELOCK_STATE_CHANGED, {Position::FIRST, Position::LAST});
+    // Also slice by the wakelock tag
+    dimensions.add_child()->set_field(3);  // The wakelock tag is set in field 3 of the wakelock.
+    *holdingWakelockPredicate.mutable_simple_predicate()->mutable_dimensions() = dimensions;
     *config.add_predicate() = holdingWakelockPredicate;
 
     auto durationMetric = config.add_duration_metric();
@@ -54,135 +56,269 @@
     *durationMetric->mutable_dimensions_in_what() =
         CreateAttributionUidDimensions(
             android::util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
-    durationMetric->set_bucket(ONE_MINUTE);
+    durationMetric->set_bucket(FIVE_MINUTES);
     return config;
 }
 
+std::vector<AttributionNode> attributions1 = {CreateAttribution(111, "App1"),
+                                              CreateAttribution(222, "GMSCoreModule1"),
+                                              CreateAttribution(222, "GMSCoreModule2")};
+
+std::vector<AttributionNode> attributions2 = {CreateAttribution(111, "App2"),
+                                              CreateAttribution(222, "GMSCoreModule1"),
+                                              CreateAttribution(222, "GMSCoreModule2")};
+
+/*
+Events:
+Screen off is met from (200ns,1 min+500ns].
+Acquire event for wl1 from 2ns to 1min+2ns
+Acquire event for wl2 from 1min-10ns to 2min-15ns
+*/
+void FeedEvents(StatsdConfig config, sp<StatsLogProcessor> processor) {
+    uint64_t bucketStartTimeNs = 10000000000;
+    uint64_t bucketSizeNs =
+            TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
+
+    auto screenTurnedOnEvent = CreateScreenStateChangedEvent(
+            android::view::DisplayStateEnum::DISPLAY_STATE_ON, bucketStartTimeNs + 1);
+    auto screenTurnedOffEvent = CreateScreenStateChangedEvent(
+            android::view::DisplayStateEnum::DISPLAY_STATE_OFF, bucketStartTimeNs + 200);
+    auto screenTurnedOnEvent2 =
+            CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
+                                          bucketStartTimeNs + bucketSizeNs + 500);
+
+    auto acquireEvent1 = CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + 2);
+    auto releaseEvent1 =
+            CreateReleaseWakelockEvent(attributions1, "wl1", bucketStartTimeNs + bucketSizeNs + 2);
+    auto acquireEvent2 =
+            CreateAcquireWakelockEvent(attributions2, "wl2", bucketStartTimeNs + bucketSizeNs - 10);
+    auto releaseEvent2 = CreateReleaseWakelockEvent(attributions2, "wl2",
+                                                    bucketStartTimeNs + 2 * bucketSizeNs - 15);
+
+    std::vector<std::unique_ptr<LogEvent>> events;
+
+    events.push_back(std::move(screenTurnedOnEvent));
+    events.push_back(std::move(screenTurnedOffEvent));
+    events.push_back(std::move(screenTurnedOnEvent2));
+    events.push_back(std::move(acquireEvent1));
+    events.push_back(std::move(acquireEvent2));
+    events.push_back(std::move(releaseEvent1));
+    events.push_back(std::move(releaseEvent2));
+
+    sortLogEventsByTimestamp(&events);
+
+    for (const auto& event : events) {
+        processor->OnLogEvent(event.get());
+    }
+}
+
 }  // namespace
 
-TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensions) {
+TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForSumDuration1) {
     ConfigKey cfgKey;
-    for (auto aggregationType : { DurationMetric::SUM, DurationMetric::MAX_SPARSE }) {
-        auto config = CreateStatsdConfig(aggregationType);
-        uint64_t bucketStartTimeNs = 10000000000;
-        uint64_t bucketSizeNs =
+    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()));
 
-        auto processor = CreateStatsLogProcessor(bucketStartTimeNs / NS_PER_SEC, config, cfgKey);
-        EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
-        EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
+    EXPECT_EQ(reports.reports_size(), 1);
+    EXPECT_EQ(reports.reports(0).metrics_size(), 1);
+    // Only 1 dimension output. The tag dimension in the predicate has been aggregated.
+    EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data_size(), 1);
 
-        auto screenTurnedOnEvent =
-            CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
-                                          bucketStartTimeNs + 1);
-        auto screenTurnedOffEvent =
+    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);
+    // Validate bucket info.
+    EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data(0).bucket_info_size(), 1);
+    data = reports.reports(0).metrics(0).duration_metrics().data(0);
+    // 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);
+}
+
+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);
+    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);
+    // Two output buckets.
+    // The wakelock holding interval in the 1st bucket 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(),
+              bucketStartTimeNs + bucketSizeNs - (bucketStartTimeNs + 200));
+    // 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(
             CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
-                                          bucketStartTimeNs + 200);
-        auto screenTurnedOnEvent2 =
-            CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
-                                          bucketStartTimeNs + bucketSizeNs + 500);
-
-        std::vector<AttributionNode> attributions1 =
-            {CreateAttribution(111, "App1"), CreateAttribution(222, "GMSCoreModule1"),
-             CreateAttribution(222, "GMSCoreModule2")};
-
-        std::vector<AttributionNode> attributions2 =
-            {CreateAttribution(111, "App2"), CreateAttribution(222, "GMSCoreModule1"),
-             CreateAttribution(222, "GMSCoreModule2")};
-
-        auto acquireEvent1 = CreateAcquireWakelockEvent(
-            attributions1, "wl1", bucketStartTimeNs + 2);
-        auto acquireEvent2 = CreateAcquireWakelockEvent(
-            attributions2, "wl2", bucketStartTimeNs + bucketSizeNs - 10);
-
-        auto releaseEvent1 = CreateReleaseWakelockEvent(
-            attributions1, "wl1", bucketStartTimeNs + bucketSizeNs + 2);
-        auto releaseEvent2 = CreateReleaseWakelockEvent(
-            attributions2, "wl2", bucketStartTimeNs + 2 * bucketSizeNs - 15);
-
-
-        std::vector<std::unique_ptr<LogEvent>> events;
-
-        events.push_back(std::move(screenTurnedOnEvent));
-        events.push_back(std::move(screenTurnedOffEvent));
-        events.push_back(std::move(screenTurnedOnEvent2));
-        events.push_back(std::move(acquireEvent1));
-        events.push_back(std::move(acquireEvent2));
-        events.push_back(std::move(releaseEvent1));
-        events.push_back(std::move(releaseEvent2));
-
-        sortLogEventsByTimestamp(&events);
-
-        for (const auto& event : events) {
-            processor->OnLogEvent(event.get());
-        }
-
-        ConfigMetricsReportList reports;
-        processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs - 1, &reports);
-        EXPECT_EQ(reports.reports_size(), 1);
-        EXPECT_EQ(reports.reports(0).metrics_size(), 1);
-        // Only 1 dimension output. The tag dimension in the predicate has been aggregated.
-        EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data_size(), 1);
-
-        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);
-        // Validate bucket info.
-        EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data(0).bucket_info_size(), 1);
-        data = reports.reports(0).metrics(0).duration_metrics().data(0);
-        // 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);
-        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);
-        // Validate dimension value.
-        ValidateAttributionUidDimension(
-            data.dimensions_in_what(), android::util::WAKELOCK_STATE_CHANGED, 111);
-        // Two output buckets.
-        // The wakelock holding interval in the 1st bucket 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(),
-            bucketStartTimeNs + bucketSizeNs - (bucketStartTimeNs + 200));
-        // 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);
-
-        events.clear();
-        events.push_back(CreateScreenStateChangedEvent(
-            android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
-            bucketStartTimeNs + 2 * bucketSizeNs + 90));
-        events.push_back(CreateAcquireWakelockEvent(
-            attributions1, "wl3", bucketStartTimeNs + 2 * bucketSizeNs + 100));
-        events.push_back(CreateReleaseWakelockEvent(
-            attributions1, "wl3", bucketStartTimeNs + 5 * bucketSizeNs + 100));
-        sortLogEventsByTimestamp(&events);
-        for (const auto& event : events) {
-            processor->OnLogEvent(event.get());
-        }
-        reports.Clear();
-        processor->onDumpReport(cfgKey, bucketStartTimeNs + 6 * bucketSizeNs + 1, &reports);
-        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);
-        ValidateAttributionUidDimension(
-            data.dimensions_in_what(), android::util::WAKELOCK_STATE_CHANGED, 111);
-        // The last wakelock holding spans 4 buckets.
-        EXPECT_EQ((unsigned long long)data.bucket_info(2).duration_nanos(), bucketSizeNs - 100);
-        EXPECT_EQ((unsigned long long)data.bucket_info(3).duration_nanos(), bucketSizeNs);
-        EXPECT_EQ((unsigned long long)data.bucket_info(4).duration_nanos(), bucketSizeNs);
-        EXPECT_EQ((unsigned long long)data.bucket_info(5).duration_nanos(), 100UL);
+                                          bucketStartTimeNs + 2 * bucketSizeNs + 90));
+    events.push_back(CreateAcquireWakelockEvent(attributions1, "wl3",
+                                                bucketStartTimeNs + 2 * bucketSizeNs + 100));
+    events.push_back(CreateReleaseWakelockEvent(attributions1, "wl3",
+                                                bucketStartTimeNs + 5 * bucketSizeNs + 100));
+    sortLogEventsByTimestamp(&events);
+    for (const auto& event : events) {
+        processor->OnLogEvent(event.get());
     }
+
+    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);
+    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.
+    EXPECT_EQ((unsigned long long)data.bucket_info(2).duration_nanos(), bucketSizeNs - 100);
+    EXPECT_EQ((unsigned long long)data.bucket_info(3).duration_nanos(), bucketSizeNs);
+    EXPECT_EQ((unsigned long long)data.bucket_info(4).duration_nanos(), bucketSizeNs);
+    EXPECT_EQ((unsigned long long)data.bucket_info(5).duration_nanos(), 100UL);
+}
+
+TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForMaxDuration1) {
+    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);
+
+    // 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);
+    // Dump the report after the end of 2nd bucket. One dimension with one bucket.
+    EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data(0).bucket_info_size(), 1);
+    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);
+    // 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(
+            CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
+                                          bucketStartTimeNs + 2 * bucketSizeNs + 90));
+    events.push_back(CreateAcquireWakelockEvent(attributions1, "wl3",
+                                                bucketStartTimeNs + 2 * bucketSizeNs + 100));
+    events.push_back(CreateReleaseWakelockEvent(attributions1, "wl3",
+                                                bucketStartTimeNs + 5 * bucketSizeNs + 100));
+    sortLogEventsByTimestamp(&events);
+    for (const auto& event : events) {
+        processor->OnLogEvent(event.get());
+    }
+
+    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);
+    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.
+    EXPECT_EQ((unsigned long long)data.bucket_info(1).duration_nanos(), 3 * bucketSizeNs);
+    EXPECT_EQ((unsigned long long)data.bucket_info(1).start_bucket_elapsed_nanos(),
+              bucketStartTimeNs + 5 * bucketSizeNs);
+    EXPECT_EQ((unsigned long long)data.bucket_info(1).end_bucket_elapsed_nanos(),
+              bucketStartTimeNs + 6 * bucketSizeNs);
 }
 
 #else
@@ -191,4 +327,4 @@
 
 }  // namespace statsd
 }  // namespace os
-}  // namespace android
\ No newline at end of file
+}  // namespace android
diff --git a/cmds/statsd/tests/external/puller_util_test.cpp b/cmds/statsd/tests/external/puller_util_test.cpp
new file mode 100644
index 0000000..7d9c8a8
--- /dev/null
+++ b/cmds/statsd/tests/external/puller_util_test.cpp
@@ -0,0 +1,269 @@
+// 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 "external/puller_util.h"
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <stdio.h>
+#include <vector>
+#include "../metrics/metrics_test_helper.h"
+
+#ifdef __ANDROID__
+
+namespace android {
+namespace os {
+namespace statsd {
+
+using namespace testing;
+using std::make_shared;
+using std::shared_ptr;
+using std::vector;
+using testing::Contains;
+/*
+ * Test merge isolated and host uid
+ */
+
+int uidAtomTagId = android::util::CPU_TIME_PER_UID_FREQ;
+int nonUidAtomTagId = android::util::SYSTEM_UPTIME;
+int timestamp = 1234;
+int isolatedUid = 30;
+int isolatedAdditiveData = 31;
+int isolatedNonAdditiveData = 32;
+int hostUid = 20;
+int hostAdditiveData = 21;
+int hostNonAdditiveData = 22;
+
+void extractIntoVector(vector<shared_ptr<LogEvent>> events,
+                      vector<vector<int>>& ret) {
+  ret.clear();
+  status_t err;
+  for (const auto& event : events) {
+    vector<int> vec;
+    vec.push_back(event->GetInt(1, &err));
+    vec.push_back(event->GetInt(2, &err));
+    vec.push_back(event->GetInt(3, &err));
+    ret.push_back(vec);
+  }
+}
+
+TEST(puller_util, MergeNoDimension) {
+  vector<shared_ptr<LogEvent>> inputData;
+  shared_ptr<LogEvent> event = make_shared<LogEvent>(uidAtomTagId, timestamp);
+  // 30->22->31
+  event->write(isolatedUid);
+  event->write(hostNonAdditiveData);
+  event->write(isolatedAdditiveData);
+  event->init();
+  inputData.push_back(event);
+
+  // 20->22->21
+  event = make_shared<LogEvent>(uidAtomTagId, timestamp);
+  event->write(hostUid);
+  event->write(hostNonAdditiveData);
+  event->write(hostAdditiveData);
+  event->init();
+  inputData.push_back(event);
+
+  sp<MockUidMap> uidMap = new NaggyMock<MockUidMap>();
+  EXPECT_CALL(*uidMap, getHostUidOrSelf(isolatedUid))
+      .WillRepeatedly(Return(hostUid));
+  EXPECT_CALL(*uidMap, getHostUidOrSelf(Ne(isolatedUid)))
+      .WillRepeatedly(ReturnArg<0>());
+  mergeIsolatedUidsToHostUid(inputData, uidMap, uidAtomTagId);
+
+  vector<vector<int>> actual;
+  extractIntoVector(inputData, actual);
+  vector<int> expectedV1 = {20, 22, 52};
+  EXPECT_EQ(1, (int)actual.size());
+  EXPECT_THAT(actual, Contains(expectedV1));
+}
+
+TEST(puller_util, MergeWithDimension) {
+  vector<shared_ptr<LogEvent>> inputData;
+  shared_ptr<LogEvent> event = make_shared<LogEvent>(uidAtomTagId, timestamp);
+  // 30->32->31
+  event->write(isolatedUid);
+  event->write(isolatedNonAdditiveData);
+  event->write(isolatedAdditiveData);
+  event->init();
+  inputData.push_back(event);
+
+  // 20->32->21
+  event = make_shared<LogEvent>(uidAtomTagId, timestamp);
+  event->write(hostUid);
+  event->write(isolatedNonAdditiveData);
+  event->write(hostAdditiveData);
+  event->init();
+  inputData.push_back(event);
+
+  // 20->22->21
+  event = make_shared<LogEvent>(uidAtomTagId, timestamp);
+  event->write(hostUid);
+  event->write(hostNonAdditiveData);
+  event->write(hostAdditiveData);
+  event->init();
+  inputData.push_back(event);
+
+  sp<MockUidMap> uidMap = new NaggyMock<MockUidMap>();
+  EXPECT_CALL(*uidMap, getHostUidOrSelf(isolatedUid))
+      .WillRepeatedly(Return(hostUid));
+  EXPECT_CALL(*uidMap, getHostUidOrSelf(Ne(isolatedUid)))
+      .WillRepeatedly(ReturnArg<0>());
+  mergeIsolatedUidsToHostUid(inputData, uidMap, uidAtomTagId);
+
+  vector<vector<int>> actual;
+  extractIntoVector(inputData, actual);
+  vector<int> expectedV1 = {20, 22, 21};
+  vector<int> expectedV2 = {20, 32, 52};
+  EXPECT_EQ(2, (int)actual.size());
+  EXPECT_THAT(actual, Contains(expectedV1));
+  EXPECT_THAT(actual, Contains(expectedV2));
+}
+
+TEST(puller_util, NoMergeHostUidOnly) {
+  vector<shared_ptr<LogEvent>> inputData;
+  shared_ptr<LogEvent> event = make_shared<LogEvent>(uidAtomTagId, timestamp);
+  // 20->32->31
+  event->write(hostUid);
+  event->write(isolatedNonAdditiveData);
+  event->write(isolatedAdditiveData);
+  event->init();
+  inputData.push_back(event);
+
+  // 20->22->21
+  event = make_shared<LogEvent>(uidAtomTagId, timestamp);
+  event->write(hostUid);
+  event->write(hostNonAdditiveData);
+  event->write(hostAdditiveData);
+  event->init();
+  inputData.push_back(event);
+
+  sp<MockUidMap> uidMap = new NaggyMock<MockUidMap>();
+  EXPECT_CALL(*uidMap, getHostUidOrSelf(isolatedUid))
+      .WillRepeatedly(Return(hostUid));
+  EXPECT_CALL(*uidMap, getHostUidOrSelf(Ne(isolatedUid)))
+      .WillRepeatedly(ReturnArg<0>());
+  mergeIsolatedUidsToHostUid(inputData, uidMap, uidAtomTagId);
+
+  // 20->32->31
+  // 20->22->21
+  vector<vector<int>> actual;
+  extractIntoVector(inputData, actual);
+  vector<int> expectedV1 = {20, 32, 31};
+  vector<int> expectedV2 = {20, 22, 21};
+  EXPECT_EQ(2, (int)actual.size());
+  EXPECT_THAT(actual, Contains(expectedV1));
+  EXPECT_THAT(actual, Contains(expectedV2));
+}
+
+TEST(puller_util, IsolatedUidOnly) {
+  vector<shared_ptr<LogEvent>> inputData;
+  shared_ptr<LogEvent> event = make_shared<LogEvent>(uidAtomTagId, timestamp);
+  // 30->32->31
+  event->write(hostUid);
+  event->write(isolatedNonAdditiveData);
+  event->write(isolatedAdditiveData);
+  event->init();
+  inputData.push_back(event);
+
+  // 30->22->21
+  event = make_shared<LogEvent>(uidAtomTagId, timestamp);
+  event->write(hostUid);
+  event->write(hostNonAdditiveData);
+  event->write(hostAdditiveData);
+  event->init();
+  inputData.push_back(event);
+
+  sp<MockUidMap> uidMap = new NaggyMock<MockUidMap>();
+  EXPECT_CALL(*uidMap, getHostUidOrSelf(isolatedUid))
+      .WillRepeatedly(Return(hostUid));
+  EXPECT_CALL(*uidMap, getHostUidOrSelf(Ne(isolatedUid)))
+      .WillRepeatedly(ReturnArg<0>());
+  mergeIsolatedUidsToHostUid(inputData, uidMap, uidAtomTagId);
+
+  // 20->32->31
+  // 20->22->21
+  vector<vector<int>> actual;
+  extractIntoVector(inputData, actual);
+  vector<int> expectedV1 = {20, 32, 31};
+  vector<int> expectedV2 = {20, 22, 21};
+  EXPECT_EQ(2, (int)actual.size());
+  EXPECT_THAT(actual, Contains(expectedV1));
+  EXPECT_THAT(actual, Contains(expectedV2));
+}
+
+TEST(puller_util, MultipleIsolatedUidToOneHostUid) {
+  vector<shared_ptr<LogEvent>> inputData;
+  shared_ptr<LogEvent> event = make_shared<LogEvent>(uidAtomTagId, timestamp);
+  // 30->32->31
+  event->write(isolatedUid);
+  event->write(isolatedNonAdditiveData);
+  event->write(isolatedAdditiveData);
+  event->init();
+  inputData.push_back(event);
+
+  // 31->32->21
+  event = make_shared<LogEvent>(uidAtomTagId, timestamp);
+  event->write(isolatedUid + 1);
+  event->write(isolatedNonAdditiveData);
+  event->write(hostAdditiveData);
+  event->init();
+  inputData.push_back(event);
+
+  // 20->32->21
+  event = make_shared<LogEvent>(uidAtomTagId, timestamp);
+  event->write(hostUid);
+  event->write(isolatedNonAdditiveData);
+  event->write(hostAdditiveData);
+  event->init();
+  inputData.push_back(event);
+
+  sp<MockUidMap> uidMap = new NaggyMock<MockUidMap>();
+  EXPECT_CALL(*uidMap, getHostUidOrSelf(_)).WillRepeatedly(Return(hostUid));
+  mergeIsolatedUidsToHostUid(inputData, uidMap, uidAtomTagId);
+
+  vector<vector<int>> actual;
+  extractIntoVector(inputData, actual);
+  vector<int> expectedV1 = {20, 32, 73};
+  EXPECT_EQ(1, (int)actual.size());
+  EXPECT_THAT(actual, Contains(expectedV1));
+}
+
+TEST(puller_util, NoNeedToMerge) {
+  vector<shared_ptr<LogEvent>> inputData;
+  shared_ptr<LogEvent> event =
+      make_shared<LogEvent>(nonUidAtomTagId, timestamp);
+  // 32
+  event->write(isolatedNonAdditiveData);
+  event->init();
+  inputData.push_back(event);
+
+  event = make_shared<LogEvent>(nonUidAtomTagId, timestamp);
+  // 22
+  event->write(hostNonAdditiveData);
+  event->init();
+  inputData.push_back(event);
+
+  sp<MockUidMap> uidMap = new NaggyMock<MockUidMap>();
+  mergeIsolatedUidsToHostUid(inputData, uidMap, nonUidAtomTagId);
+
+  EXPECT_EQ(2, (int)inputData.size());
+}
+
+}  // namespace statsd
+}  // namespace os
+}  // namespace android
+#else
+GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif
diff --git a/cmds/statsd/tests/guardrail/StatsdStats_test.cpp b/cmds/statsd/tests/guardrail/StatsdStats_test.cpp
index a134300..bd11443 100644
--- a/cmds/statsd/tests/guardrail/StatsdStats_test.cpp
+++ b/cmds/statsd/tests/guardrail/StatsdStats_test.cpp
@@ -225,7 +225,7 @@
     bool dropboxAtomGood = false;
 
     for (const auto& atomStats : report.atom_stats()) {
-        if (atomStats.tag() == android::util::SENSOR_STATE_CHANGED && atomStats.count() == 2) {
+        if (atomStats.tag() == android::util::SENSOR_STATE_CHANGED && atomStats.count() == 3) {
             sensorAtomGood = true;
         }
         if (atomStats.tag() == android::util::DROPBOX_ERROR_CHANGED && atomStats.count() == 1) {
diff --git a/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp b/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp
index 50b3532..20ddbe9 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"
@@ -49,12 +48,15 @@
     metric.set_bucket(ONE_MINUTE);
 
     LogEvent event1(tagId, bucketStartTimeNs + 1);
+    event1.init();
     LogEvent event2(tagId, bucketStartTimeNs + 2);
+    event2.init();
 
     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
 
     CountMetricProducer countProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
                                       bucketStartTimeNs);
+    countProducer.setBucketSize(60 * NS_PER_SEC);
 
     // 2 events in bucket 1.
     countProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
@@ -77,6 +79,8 @@
 
     // 1 matched event happens in bucket 2.
     LogEvent event3(tagId, bucketStartTimeNs + bucketSizeNs + 2);
+    event3.init();
+
     countProducer.onMatchedLogEvent(1 /*log matcher index*/, event3);
     countProducer.flushIfNeededLocked(bucketStartTimeNs + 2 * bucketSizeNs + 1);
     EXPECT_EQ(1UL, countProducer.mPastBuckets.size());
@@ -107,11 +111,15 @@
     metric.set_condition(StringToId("SCREEN_ON"));
 
     LogEvent event1(1, bucketStartTimeNs + 1);
+    event1.init();
+
     LogEvent event2(1, bucketStartTimeNs + 10);
+    event2.init();
 
     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
 
     CountMetricProducer countProducer(kConfigKey, metric, 1, wizard, bucketStartTimeNs);
+    countProducer.setBucketSize(60 * NS_PER_SEC);
 
     countProducer.onConditionChanged(true, bucketStartTimeNs);
     countProducer.onMatchedLogEvent(1 /*matcher index*/, event1);
@@ -173,6 +181,7 @@
 
     CountMetricProducer countProducer(kConfigKey, metric, 1 /*condition tracker index*/, wizard,
                                       bucketStartTimeNs);
+    countProducer.setBucketSize(60 * NS_PER_SEC);
 
     countProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
     countProducer.flushIfNeededLocked(bucketStartTimeNs + 1);
@@ -191,6 +200,120 @@
     EXPECT_EQ(1LL, bucketInfo.mCount);
 }
 
+TEST(CountMetricProducerTest, TestEventWithAppUpgrade) {
+    uint64_t bucketStartTimeNs = 10000000000;
+    uint64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
+    uint64_t eventUpgradeTimeNs = bucketStartTimeNs + 15 * NS_PER_SEC;
+
+    int tagId = 1;
+    int conditionTagId = 2;
+
+    CountMetric metric;
+    metric.set_id(1);
+    metric.set_bucket(ONE_MINUTE);
+    Alert alert;
+    alert.set_num_buckets(3);
+    alert.set_trigger_if_sum_gt(2);
+    LogEvent event1(tagId, bucketStartTimeNs + 1);
+    event1.write("111");  // uid
+    event1.init();
+    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+    CountMetricProducer countProducer(kConfigKey, metric, -1 /* no condition */, wizard,
+                                      bucketStartTimeNs);
+    countProducer.setBucketSize(60 * NS_PER_SEC);
+
+    sp<AnomalyTracker> anomalyTracker = countProducer.addAnomalyTracker(alert);
+    EXPECT_TRUE(anomalyTracker != nullptr);
+
+    // Bucket is flushed yet.
+    countProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
+    EXPECT_EQ(0UL, countProducer.mPastBuckets.size());
+    EXPECT_EQ(0, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
+
+    // App upgrade forces bucket flush.
+    // Check that there's a past bucket and the bucket end is not adjusted.
+    countProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
+    EXPECT_EQ(1UL, countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+    EXPECT_EQ((long long)bucketStartTimeNs,
+              countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mBucketStartNs);
+    EXPECT_EQ((long long)eventUpgradeTimeNs,
+              countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mBucketEndNs);
+    EXPECT_EQ(eventUpgradeTimeNs, countProducer.mCurrentBucketStartTimeNs);
+    // Anomaly tracker only contains full buckets.
+    EXPECT_EQ(0, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
+
+    uint64_t lastEndTimeNs = countProducer.getCurrentBucketEndTimeNs();
+    // Next event occurs in same bucket as partial bucket created.
+    LogEvent event2(tagId, bucketStartTimeNs + 59 * NS_PER_SEC + 10);
+    event2.write("222");  // uid
+    event2.init();
+    countProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
+    EXPECT_EQ(1UL, countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+    EXPECT_EQ(eventUpgradeTimeNs, countProducer.mCurrentBucketStartTimeNs);
+    EXPECT_EQ(0, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
+
+    // Third event in following bucket.
+    LogEvent event3(tagId, bucketStartTimeNs + 62 * NS_PER_SEC + 10);
+    event3.write("333");  // uid
+    event3.init();
+    countProducer.onMatchedLogEvent(1 /*log matcher index*/, event3);
+    EXPECT_EQ(2UL, countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+    EXPECT_EQ(lastEndTimeNs, countProducer.mCurrentBucketStartTimeNs);
+    EXPECT_EQ(2, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
+}
+
+TEST(CountMetricProducerTest, TestEventWithAppUpgradeInNextBucket) {
+    uint64_t bucketStartTimeNs = 10000000000;
+    uint64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
+    uint64_t eventUpgradeTimeNs = bucketStartTimeNs + 65 * NS_PER_SEC;
+
+    int tagId = 1;
+    int conditionTagId = 2;
+
+    CountMetric metric;
+    metric.set_id(1);
+    metric.set_bucket(ONE_MINUTE);
+    LogEvent event1(tagId, bucketStartTimeNs + 1);
+    event1.write("111");  // uid
+    event1.init();
+    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+    CountMetricProducer countProducer(kConfigKey, metric, -1 /* no condition */, wizard,
+                                      bucketStartTimeNs);
+    countProducer.setBucketSize(60 * NS_PER_SEC);
+
+    // Bucket is flushed yet.
+    countProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
+    EXPECT_EQ(0UL, countProducer.mPastBuckets.size());
+
+    // App upgrade forces bucket flush.
+    // Check that there's a past bucket and the bucket end is not adjusted.
+    countProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
+    EXPECT_EQ(1UL, countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+    EXPECT_EQ((int64_t)bucketStartTimeNs,
+              countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mBucketStartNs);
+    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs,
+              (uint64_t)countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mBucketEndNs);
+    EXPECT_EQ(eventUpgradeTimeNs, countProducer.mCurrentBucketStartTimeNs);
+
+    // Next event occurs in same bucket as partial bucket created.
+    LogEvent event2(tagId, bucketStartTimeNs + 70 * NS_PER_SEC + 10);
+    event2.write("222");  // uid
+    event2.init();
+    countProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
+    EXPECT_EQ(1UL, countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+
+    // Third event in following bucket.
+    LogEvent event3(tagId, bucketStartTimeNs + 121 * NS_PER_SEC + 10);
+    event3.write("333");  // uid
+    event3.init();
+    countProducer.onMatchedLogEvent(1 /*log matcher index*/, event3);
+    EXPECT_EQ(2UL, countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+    EXPECT_EQ((int64_t)eventUpgradeTimeNs,
+              countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][1].mBucketStartNs);
+    EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
+              (uint64_t)countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][1].mBucketEndNs);
+}
+
 TEST(CountMetricProducerTest, TestAnomalyDetectionUnSliced) {
     Alert alert;
     alert.set_id(11);
@@ -212,16 +335,25 @@
     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
     CountMetricProducer countProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
                                       bucketStartTimeNs);
+    countProducer.setBucketSize(60 * NS_PER_SEC);
+
     sp<AnomalyTracker> anomalyTracker = countProducer.addAnomalyTracker(alert);
 
     int tagId = 1;
     LogEvent event1(tagId, bucketStartTimeNs + 1);
+    event1.init();
     LogEvent event2(tagId, bucketStartTimeNs + 2);
+    event2.init();
     LogEvent event3(tagId, bucketStartTimeNs + 2 * bucketSizeNs + 1);
+    event3.init();
     LogEvent event4(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 1);
+    event4.init();
     LogEvent event5(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 2);
+    event5.init();
     LogEvent event6(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 3);
+    event6.init();
     LogEvent event7(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 2 * NS_PER_SEC);
+    event7.init();
 
     // Two events in bucket #0.
     countProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
@@ -245,13 +377,13 @@
     EXPECT_EQ(3L, countProducer.mCurrentSlicedCounter->begin()->second);
     // Anomaly at event 6 is within refractory period. The alarm is at event 5 timestamp not event 6
     EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
-            event5.GetTimestampNs() / NS_PER_SEC + refPeriodSec);
+            event5.GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec);
 
     countProducer.onMatchedLogEvent(1 /*log matcher index*/, event7);
     EXPECT_EQ(1UL, countProducer.mCurrentSlicedCounter->size());
     EXPECT_EQ(4L, countProducer.mCurrentSlicedCounter->begin()->second);
     EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
-            event7.GetTimestampNs() / NS_PER_SEC + refPeriodSec);
+            event7.GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec);
 }
 
 }  // namespace statsd
diff --git a/cmds/statsd/tests/metrics/DurationMetricProducer_test.cpp b/cmds/statsd/tests/metrics/DurationMetricProducer_test.cpp
index c9fe252..7969596 100644
--- a/cmds/statsd/tests/metrics/DurationMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/DurationMetricProducer_test.cpp
@@ -51,12 +51,15 @@
 
     int tagId = 1;
     LogEvent event1(tagId, bucketStartTimeNs + 1);
+    event1.init();
     LogEvent event2(tagId, bucketStartTimeNs + bucketSizeNs + 2);
+    event2.init();
 
     FieldMatcher dimensions;
     DurationMetricProducer durationProducer(
             kConfigKey, metric, -1 /*no condition*/, 1 /* start index */, 2 /* stop index */,
             3 /* stop_all index */, false /*nesting*/, wizard, dimensions, bucketStartTimeNs);
+    durationProducer.setBucketSize(60 * NS_PER_SEC);
 
     durationProducer.onMatchedLogEvent(1 /* start index*/, event1);
     durationProducer.onMatchedLogEvent(2 /* stop index*/, event2);
@@ -86,14 +89,20 @@
 
     int tagId = 1;
     LogEvent event1(tagId, bucketStartTimeNs + 1);
+    event1.init();
     LogEvent event2(tagId, bucketStartTimeNs + 2);
+    event2.init();
     LogEvent event3(tagId, bucketStartTimeNs + bucketSizeNs + 1);
+    event3.init();
     LogEvent event4(tagId, bucketStartTimeNs + bucketSizeNs + 3);
+    event4.init();
 
     FieldMatcher dimensions;
     DurationMetricProducer durationProducer(
             kConfigKey, metric, 0 /* condition index */, 1 /* start index */, 2 /* stop index */,
             3 /* stop_all index */, false /*nesting*/, wizard, dimensions, bucketStartTimeNs);
+    durationProducer.setBucketSize(60 * NS_PER_SEC);
+
     EXPECT_FALSE(durationProducer.mCondition);
     EXPECT_FALSE(durationProducer.isConditionSliced());
 
@@ -116,6 +125,257 @@
     EXPECT_EQ(1ULL, buckets2[0].mDuration);
 }
 
+TEST(DurationMetricTrackerTest, TestSumDurationWithUpgrade) {
+    /**
+     * The duration starts from the first bucket, through the two partial buckets (10-70sec),
+     * another bucket, and ends at the beginning of the next full bucket.
+     * Expected buckets:
+     *  - [10,25]: 14 secs
+     *  - [25,70]: All 45 secs
+     *  - [70,130]: All 60 secs
+     *  - [130, 210]: Only 5 secs (event ended at 135sec)
+     */
+    uint64_t bucketStartTimeNs = 10000000000;
+    uint64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
+    uint64_t eventUpgradeTimeNs = bucketStartTimeNs + 15 * NS_PER_SEC;
+    uint64_t startTimeNs = bucketStartTimeNs + 1 * NS_PER_SEC;
+    uint64_t endTimeNs = startTimeNs + 125 * NS_PER_SEC;
+
+    int tagId = 1;
+
+    DurationMetric metric;
+    metric.set_id(1);
+    metric.set_bucket(ONE_MINUTE);
+    metric.set_aggregation_type(DurationMetric_AggregationType_SUM);
+    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+    FieldMatcher dimensions;
+    DurationMetricProducer durationProducer(
+            kConfigKey, metric, -1 /* no condition */, 1 /* start index */, 2 /* stop index */,
+            3 /* stop_all index */, false /*nesting*/, wizard, dimensions, bucketStartTimeNs);
+    durationProducer.setBucketSize(60 * NS_PER_SEC);
+
+    LogEvent start_event(tagId, startTimeNs);
+    start_event.init();
+    durationProducer.onMatchedLogEvent(1 /* start index*/, start_event);
+    EXPECT_EQ(0UL, durationProducer.mPastBuckets.size());
+    EXPECT_EQ(bucketStartTimeNs, durationProducer.mCurrentBucketStartTimeNs);
+
+    durationProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
+    EXPECT_EQ(1UL, durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+    std::vector<DurationBucket> buckets =
+            durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
+    EXPECT_EQ(bucketStartTimeNs, buckets[0].mBucketStartNs);
+    EXPECT_EQ(eventUpgradeTimeNs, buckets[0].mBucketEndNs);
+    EXPECT_EQ(eventUpgradeTimeNs - startTimeNs, buckets[0].mDuration);
+    EXPECT_EQ(eventUpgradeTimeNs, durationProducer.mCurrentBucketStartTimeNs);
+
+    // We skip ahead one bucket, so we fill in the first two partial buckets and one full bucket.
+    LogEvent end_event(tagId, endTimeNs);
+    end_event.init();
+    durationProducer.onMatchedLogEvent(2 /* stop index*/, end_event);
+    buckets = durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
+    EXPECT_EQ(3UL, buckets.size());
+    EXPECT_EQ(eventUpgradeTimeNs, buckets[1].mBucketStartNs);
+    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets[1].mBucketEndNs);
+    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs - eventUpgradeTimeNs, buckets[1].mDuration);
+    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets[2].mBucketStartNs);
+    EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, buckets[2].mBucketEndNs);
+    EXPECT_EQ(bucketSizeNs, buckets[2].mDuration);
+}
+
+TEST(DurationMetricTrackerTest, TestSumDurationWithUpgradeInFollowingBucket) {
+    /**
+     * Expected buckets (start at 11s, upgrade at 75s, end at 135s):
+     *  - [10,70]: 59 secs
+     *  - [70,75]: 5 sec
+     *  - [75,130]: 55 secs
+     */
+    uint64_t bucketStartTimeNs = 10000000000;
+    uint64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
+    uint64_t eventUpgradeTimeNs = bucketStartTimeNs + 65 * NS_PER_SEC;
+    uint64_t startTimeNs = bucketStartTimeNs + 1 * NS_PER_SEC;
+    uint64_t endTimeNs = startTimeNs + 125 * NS_PER_SEC;
+
+    int tagId = 1;
+
+    DurationMetric metric;
+    metric.set_id(1);
+    metric.set_bucket(ONE_MINUTE);
+    metric.set_aggregation_type(DurationMetric_AggregationType_SUM);
+    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+    FieldMatcher dimensions;
+    DurationMetricProducer durationProducer(
+            kConfigKey, metric, -1 /* no condition */, 1 /* start index */, 2 /* stop index */,
+            3 /* stop_all index */, false /*nesting*/, wizard, dimensions, bucketStartTimeNs);
+    durationProducer.setBucketSize(60 * NS_PER_SEC);
+
+    LogEvent start_event(tagId, startTimeNs);
+    start_event.init();
+    durationProducer.onMatchedLogEvent(1 /* start index*/, start_event);
+    EXPECT_EQ(0UL, durationProducer.mPastBuckets.size());
+    EXPECT_EQ(bucketStartTimeNs, durationProducer.mCurrentBucketStartTimeNs);
+
+    durationProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
+    EXPECT_EQ(2UL, durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+    std::vector<DurationBucket> buckets =
+            durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
+    EXPECT_EQ(bucketStartTimeNs, buckets[0].mBucketStartNs);
+    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets[0].mBucketEndNs);
+    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs - startTimeNs, buckets[0].mDuration);
+    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets[1].mBucketStartNs);
+    EXPECT_EQ(eventUpgradeTimeNs, buckets[1].mBucketEndNs);
+    EXPECT_EQ(eventUpgradeTimeNs - (bucketStartTimeNs + bucketSizeNs), buckets[1].mDuration);
+    EXPECT_EQ(eventUpgradeTimeNs, durationProducer.mCurrentBucketStartTimeNs);
+
+    // We skip ahead one bucket, so we fill in the first two partial buckets and one full bucket.
+    LogEvent end_event(tagId, endTimeNs);
+    end_event.init();
+    durationProducer.onMatchedLogEvent(2 /* stop index*/, end_event);
+    buckets = durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
+    EXPECT_EQ(3UL, buckets.size());
+    EXPECT_EQ(eventUpgradeTimeNs, buckets[2].mBucketStartNs);
+    EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, buckets[2].mBucketEndNs);
+    EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs - eventUpgradeTimeNs, buckets[2].mDuration);
+}
+
+TEST(DurationMetricTrackerTest, TestSumDurationAnomalyWithUpgrade) {
+    uint64_t bucketStartTimeNs = 10000000000;
+    uint64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
+    uint64_t eventUpgradeTimeNs = bucketStartTimeNs + 15 * NS_PER_SEC;
+    uint64_t startTimeNs = bucketStartTimeNs + 1;
+    uint64_t endTimeNs = startTimeNs + 65 * NS_PER_SEC;
+
+    int tagId = 1;
+
+    // Setup metric with alert.
+    DurationMetric metric;
+    metric.set_id(1);
+    metric.set_bucket(ONE_MINUTE);
+    metric.set_aggregation_type(DurationMetric_AggregationType_SUM);
+    Alert alert;
+    alert.set_num_buckets(3);
+    alert.set_trigger_if_sum_gt(2);
+
+    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+    FieldMatcher dimensions;
+    DurationMetricProducer durationProducer(
+            kConfigKey, metric, -1 /* no condition */, 1 /* start index */, 2 /* stop index */,
+            3 /* stop_all index */, false /*nesting*/, wizard, dimensions, bucketStartTimeNs);
+    durationProducer.setBucketSize(60 * NS_PER_SEC);
+
+    sp<AnomalyTracker> anomalyTracker = durationProducer.addAnomalyTracker(alert);
+    EXPECT_TRUE(anomalyTracker != nullptr);
+
+    LogEvent start_event(tagId, startTimeNs);
+    start_event.init();
+    durationProducer.onMatchedLogEvent(1 /* start index*/, start_event);
+    durationProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
+    // We skip ahead one bucket, so we fill in the first two partial buckets and one full bucket.
+    LogEvent end_event(tagId, endTimeNs);
+    end_event.init();
+    durationProducer.onMatchedLogEvent(2 /* stop index*/, end_event);
+
+    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs - startTimeNs,
+              (uint64_t)anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
+}
+
+TEST(DurationMetricTrackerTest, TestMaxDurationWithUpgrade) {
+    uint64_t bucketStartTimeNs = 10000000000;
+    uint64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
+    uint64_t eventUpgradeTimeNs = bucketStartTimeNs + 15 * NS_PER_SEC;
+    uint64_t startTimeNs = bucketStartTimeNs + 1;
+    uint64_t endTimeNs = startTimeNs + 125 * NS_PER_SEC;
+
+    int tagId = 1;
+
+    DurationMetric metric;
+    metric.set_id(1);
+    metric.set_bucket(ONE_MINUTE);
+    metric.set_aggregation_type(DurationMetric_AggregationType_MAX_SPARSE);
+    LogEvent event1(tagId, startTimeNs);
+    event1.write("111");  // uid
+    event1.init();
+    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+    FieldMatcher dimensions;
+    DurationMetricProducer durationProducer(
+            kConfigKey, metric, -1 /* no condition */, 1 /* start index */, 2 /* stop index */,
+            3 /* stop_all index */, false /*nesting*/, wizard, dimensions, bucketStartTimeNs);
+    durationProducer.setBucketSize(60 * NS_PER_SEC);
+
+    LogEvent start_event(tagId, startTimeNs);
+    start_event.init();
+    durationProducer.onMatchedLogEvent(1 /* start index*/, start_event);
+    EXPECT_EQ(0UL, durationProducer.mPastBuckets.size());
+    EXPECT_EQ(bucketStartTimeNs, durationProducer.mCurrentBucketStartTimeNs);
+
+    durationProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
+    EXPECT_EQ(0UL, durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+    EXPECT_EQ(eventUpgradeTimeNs, durationProducer.mCurrentBucketStartTimeNs);
+
+    // We skip ahead one bucket, so we fill in the first two partial buckets and one full bucket.
+    LogEvent end_event(tagId, endTimeNs);
+    end_event.init();
+    durationProducer.onMatchedLogEvent(2 /* stop index*/, end_event);
+    EXPECT_EQ(0UL, durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+
+    durationProducer.flushIfNeededLocked(bucketStartTimeNs + 3 * bucketSizeNs + 1);
+    std::vector<DurationBucket> buckets =
+            durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
+    EXPECT_EQ(1UL, buckets.size());
+    EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, buckets[0].mBucketStartNs);
+    EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs, buckets[0].mBucketEndNs);
+    EXPECT_EQ(endTimeNs - startTimeNs, buckets[0].mDuration);
+}
+
+TEST(DurationMetricTrackerTest, TestMaxDurationWithUpgradeInNextBucket) {
+    uint64_t bucketStartTimeNs = 10000000000;
+    uint64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
+    uint64_t eventUpgradeTimeNs = bucketStartTimeNs + 65 * NS_PER_SEC;
+    uint64_t startTimeNs = bucketStartTimeNs + 1;
+    uint64_t endTimeNs = startTimeNs + 115 * NS_PER_SEC;
+
+    int tagId = 1;
+
+    DurationMetric metric;
+    metric.set_id(1);
+    metric.set_bucket(ONE_MINUTE);
+    metric.set_aggregation_type(DurationMetric_AggregationType_MAX_SPARSE);
+    LogEvent event1(tagId, startTimeNs);
+    event1.write("111");  // uid
+    event1.init();
+    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+    FieldMatcher dimensions;
+    DurationMetricProducer durationProducer(
+            kConfigKey, metric, -1 /* no condition */, 1 /* start index */, 2 /* stop index */,
+            3 /* stop_all index */, false /*nesting*/, wizard, dimensions, bucketStartTimeNs);
+    durationProducer.setBucketSize(60 * NS_PER_SEC);
+
+    LogEvent start_event(tagId, startTimeNs);
+    start_event.init();
+    durationProducer.onMatchedLogEvent(1 /* start index*/, start_event);
+    EXPECT_EQ(0UL, durationProducer.mPastBuckets.size());
+    EXPECT_EQ(bucketStartTimeNs, durationProducer.mCurrentBucketStartTimeNs);
+
+    durationProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
+    EXPECT_EQ(0UL, durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+    EXPECT_EQ(eventUpgradeTimeNs, durationProducer.mCurrentBucketStartTimeNs);
+
+    // Stop occurs in the same partial bucket as created for the app upgrade.
+    LogEvent end_event(tagId, endTimeNs);
+    end_event.init();
+    durationProducer.onMatchedLogEvent(2 /* stop index*/, end_event);
+    EXPECT_EQ(0UL, durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+    EXPECT_EQ(eventUpgradeTimeNs, durationProducer.mCurrentBucketStartTimeNs);
+
+    durationProducer.flushIfNeededLocked(bucketStartTimeNs + 2 * bucketSizeNs + 1);
+    std::vector<DurationBucket> buckets =
+            durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
+    EXPECT_EQ(1UL, buckets.size());
+    EXPECT_EQ(eventUpgradeTimeNs, buckets[0].mBucketStartNs);
+    EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, buckets[0].mBucketEndNs);
+    EXPECT_EQ(endTimeNs - startTimeNs, buckets[0].mDuration);
+}
+
 }  // namespace statsd
 }  // namespace os
 }  // namespace android
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 58be5b0..0eb8ce2 100644
--- a/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp
@@ -44,6 +44,7 @@
 const int64_t bucket2StartTimeNs = bucketStartTimeNs + bucketSizeNs;
 const int64_t bucket3StartTimeNs = bucketStartTimeNs + 2 * bucketSizeNs;
 const int64_t bucket4StartTimeNs = bucketStartTimeNs + 3 * bucketSizeNs;
+const uint64_t eventUpgradeTimeNs = bucketStartTimeNs + 15 * NS_PER_SEC;
 
 TEST(GaugeMetricProducerTest, TestNoCondition) {
     GaugeMetric metric;
@@ -66,6 +67,7 @@
 
     GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
                                       tagId, bucketStartTimeNs, pullerManager);
+    gaugeProducer.setBucketSize(60 * NS_PER_SEC);
 
     vector<shared_ptr<LogEvent>> allData;
     allData.clear();
@@ -79,9 +81,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();
@@ -95,16 +98,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);
@@ -113,12 +120,153 @@
     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);
 }
 
+TEST(GaugeMetricProducerTest, TestPushedEventsWithUpgrade) {
+    GaugeMetric metric;
+    metric.set_id(metricId);
+    metric.set_bucket(ONE_MINUTE);
+    metric.mutable_gauge_fields_filter()->set_include_all(true);
+
+    Alert alert;
+    alert.set_id(101);
+    alert.set_metric_id(metricId);
+    alert.set_trigger_if_sum_gt(25);
+    alert.set_num_buckets(100);
+    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+    shared_ptr<MockStatsPullerManager> pullerManager =
+            make_shared<StrictMock<MockStatsPullerManager>>();
+    GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
+                                      -1 /* -1 means no pulling */, bucketStartTimeNs,
+                                      pullerManager);
+    gaugeProducer.setBucketSize(60 * NS_PER_SEC);
+    sp<AnomalyTracker> anomalyTracker = gaugeProducer.addAnomalyTracker(alert);
+    EXPECT_TRUE(anomalyTracker != nullptr);
+
+    shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
+    event1->write(1);
+    event1->write(10);
+    event1->init();
+    gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
+    EXPECT_EQ(1UL, (*gaugeProducer.mCurrentSlicedBucket).count(DEFAULT_METRIC_DIMENSION_KEY));
+
+    gaugeProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
+    EXPECT_EQ(0UL, (*gaugeProducer.mCurrentSlicedBucket).count(DEFAULT_METRIC_DIMENSION_KEY));
+    EXPECT_EQ(1UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+    EXPECT_EQ(0UL, gaugeProducer.mCurrentBucketNum);
+    EXPECT_EQ(eventUpgradeTimeNs, gaugeProducer.mCurrentBucketStartTimeNs);
+    // Partial buckets are not sent to anomaly tracker.
+    EXPECT_EQ(0, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
+
+    // Create an event in the same partial bucket.
+    shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 59 * NS_PER_SEC);
+    event2->write(1);
+    event2->write(10);
+    event2->init();
+    gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
+    EXPECT_EQ(0UL, gaugeProducer.mCurrentBucketNum);
+    EXPECT_EQ(1UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+    EXPECT_EQ((uint64_t)eventUpgradeTimeNs, gaugeProducer.mCurrentBucketStartTimeNs);
+    // Partial buckets are not sent to anomaly tracker.
+    EXPECT_EQ(0, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
+
+    // Next event should trigger creation of new bucket and send previous full bucket to anomaly
+    // tracker.
+    shared_ptr<LogEvent> event3 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 65 * NS_PER_SEC);
+    event3->write(1);
+    event3->write(10);
+    event3->init();
+    gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, *event3);
+    EXPECT_EQ(1UL, gaugeProducer.mCurrentBucketNum);
+    EXPECT_EQ(2UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+    EXPECT_EQ((uint64_t)bucketStartTimeNs + bucketSizeNs, gaugeProducer.mCurrentBucketStartTimeNs);
+    EXPECT_EQ(1, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
+
+    // Next event should trigger creation of new bucket.
+    shared_ptr<LogEvent> event4 =
+            make_shared<LogEvent>(tagId, bucketStartTimeNs + 125 * NS_PER_SEC);
+    event4->write(1);
+    event4->write(10);
+    event4->init();
+    gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, *event4);
+    EXPECT_EQ(2UL, gaugeProducer.mCurrentBucketNum);
+    EXPECT_EQ(3UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+    EXPECT_EQ(2, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
+}
+
+TEST(GaugeMetricProducerTest, TestPulledWithUpgrade) {
+    GaugeMetric metric;
+    metric.set_id(metricId);
+    metric.set_bucket(ONE_MINUTE);
+    auto gaugeFieldMatcher = metric.mutable_gauge_fields_filter()->mutable_fields();
+    gaugeFieldMatcher->set_field(tagId);
+    gaugeFieldMatcher->add_child()->set_field(2);
+
+    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+
+    shared_ptr<MockStatsPullerManager> pullerManager =
+            make_shared<StrictMock<MockStatsPullerManager>>();
+    EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _)).WillOnce(Return());
+    EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
+    EXPECT_CALL(*pullerManager, Pull(tagId, _))
+            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+                data->clear();
+                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, eventUpgradeTimeNs);
+                event->write("some value");
+                event->write(2);
+                event->init();
+                data->push_back(event);
+                return true;
+            }));
+
+    GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
+                                      tagId, bucketStartTimeNs, pullerManager);
+    gaugeProducer.setBucketSize(60 * NS_PER_SEC);
+
+    vector<shared_ptr<LogEvent>> allData;
+    shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
+    event->write("some value");
+    event->write(1);
+    event->init();
+    allData.push_back(event);
+    gaugeProducer.onDataPulled(allData);
+    EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
+    EXPECT_EQ(1, gaugeProducer.mCurrentSlicedBucket->begin()
+                         ->second.front()
+                         .mFields->begin()
+                         ->mValue.int_value);
+
+    gaugeProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
+    EXPECT_EQ(1UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+    EXPECT_EQ(0UL, gaugeProducer.mCurrentBucketNum);
+    EXPECT_EQ((uint64_t)eventUpgradeTimeNs, gaugeProducer.mCurrentBucketStartTimeNs);
+    EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
+    EXPECT_EQ(2, gaugeProducer.mCurrentSlicedBucket->begin()
+                         ->second.front()
+                         .mFields->begin()
+                         ->mValue.int_value);
+
+    allData.clear();
+    event = make_shared<LogEvent>(tagId, bucketStartTimeNs + bucketSizeNs + 1);
+    event->write("some value");
+    event->write(3);
+    event->init();
+    allData.push_back(event);
+    gaugeProducer.onDataPulled(allData);
+    EXPECT_EQ(2UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+    EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
+    EXPECT_EQ(3, gaugeProducer.mCurrentSlicedBucket->begin()
+                         ->second.front()
+                         .mFields->begin()
+                         ->mValue.int_value);
+}
+
 TEST(GaugeMetricProducerTest, TestWithCondition) {
     GaugeMetric metric;
     metric.set_id(metricId);
@@ -147,12 +295,14 @@
 
     GaugeMetricProducer gaugeProducer(kConfigKey, metric, 1, wizard, tagId,
                                       bucketStartTimeNs, pullerManager);
+    gaugeProducer.setBucketSize(60 * NS_PER_SEC);
 
     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;
@@ -165,19 +315,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);
 }
 
@@ -197,6 +354,7 @@
     gaugeFieldMatcher->add_child()->set_field(2);
     GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
                                       tagId, bucketStartTimeNs, pullerManager);
+    gaugeProducer.setBucketSize(60 * NS_PER_SEC);
 
     Alert alert;
     alert.set_id(101);
@@ -215,9 +373,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 =
@@ -228,11 +387,12 @@
 
     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);
+            event2->GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec);
 
     std::shared_ptr<LogEvent> event3 =
             std::make_shared<LogEvent>(tagId, bucketStartTimeNs + 2 * bucketSizeNs + 10);
@@ -242,11 +402,12 @@
 
     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);
+            event2->GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec);
 
     // The event4 does not have the gauge field. Thus the current bucket value is 0.
     std::shared_ptr<LogEvent> event4 =
diff --git a/cmds/statsd/tests/metrics/MaxDurationTracker_test.cpp b/cmds/statsd/tests/metrics/MaxDurationTracker_test.cpp
index 203f028..3397f14 100644
--- a/cmds/statsd/tests/metrics/MaxDurationTracker_test.cpp
+++ b/cmds/statsd/tests/metrics/MaxDurationTracker_test.cpp
@@ -41,6 +41,11 @@
 
 const int TagId = 1;
 
+const HashableDimensionKey eventKey = getMockedDimensionKey(TagId, 0, "1");
+const std::vector<HashableDimensionKey> conditionKey = {getMockedDimensionKey(TagId, 4, "1")};
+const HashableDimensionKey key1 = getMockedDimensionKey(TagId, 1, "1");
+const HashableDimensionKey key2 = getMockedDimensionKey(TagId, 1, "2");
+const uint64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL;
 
 TEST(MaxDurationTrackerTest, TestSimpleMaxDuration) {
     const MetricDimensionKey eventKey = getMockedMetricDimensionKey(TagId, 0, "1");
@@ -48,17 +53,20 @@
     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;
 
     uint64_t bucketStartTimeNs = 10000000000;
-    uint64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL;
+    uint64_t bucketEndTimeNs = bucketStartTimeNs + bucketSizeNs;
+    uint64_t bucketNum = 0;
 
     int64_t metricId = 1;
     MaxDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, -1, dimensionInCondition,
-                               false, bucketStartTimeNs, bucketSizeNs, false, {});
+                               false, bucketStartTimeNs, bucketNum, bucketStartTimeNs, bucketSizeNs,
+                               false, {});
 
     tracker.noteStart(key1, true, bucketStartTimeNs, ConditionKey());
     // Event starts again. This would not change anything as it already starts.
@@ -82,17 +90,20 @@
     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;
 
-    uint64_t bucketStartTimeNs = 10000000000;
     uint64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL;
+    uint64_t bucketStartTimeNs = 10000000000;
+    uint64_t bucketEndTimeNs = bucketStartTimeNs + bucketSizeNs;
+    uint64_t bucketNum = 0;
 
     int64_t metricId = 1;
     MaxDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, -1, dimensionInCondition,
-                               false, bucketStartTimeNs, bucketSizeNs, false, {});
+                               false, bucketStartTimeNs, bucketNum, bucketStartTimeNs, bucketSizeNs,
+                               false, {});
 
     tracker.noteStart(key1, true, bucketStartTimeNs + 1, ConditionKey());
 
@@ -101,15 +112,14 @@
     tracker.flushIfNeeded(bucketStartTimeNs + bucketSizeNs + 40, &buckets);
     tracker.noteStopAll(bucketStartTimeNs + bucketSizeNs + 40);
     EXPECT_TRUE(tracker.mInfos.empty());
-
-    EXPECT_TRUE(buckets.find(eventKey) != buckets.end());
-    EXPECT_EQ(1u, buckets[eventKey].size());
-    EXPECT_EQ(bucketSizeNs - 1, buckets[eventKey][0].mDuration);
+    EXPECT_TRUE(buckets.find(eventKey) == buckets.end());
 
     tracker.flushIfNeeded(bucketStartTimeNs + 3 * bucketSizeNs + 40, &buckets);
-    EXPECT_EQ(2u, buckets[eventKey].size());
-    EXPECT_EQ(bucketSizeNs - 1, buckets[eventKey][0].mDuration);
-    EXPECT_EQ(40ULL, buckets[eventKey][1].mDuration);
+    EXPECT_TRUE(buckets.find(eventKey) != buckets.end());
+    EXPECT_EQ(1u, buckets[eventKey].size());
+    EXPECT_EQ(bucketSizeNs + 40 - 1, buckets[eventKey][0].mDuration);
+    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets[eventKey][0].mBucketStartNs);
+    EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, buckets[eventKey][0].mBucketEndNs);
 }
 
 TEST(MaxDurationTrackerTest, TestCrossBucketBoundary) {
@@ -117,17 +127,20 @@
     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;
 
-    uint64_t bucketStartTimeNs = 10000000000;
     uint64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL;
+    uint64_t bucketStartTimeNs = 10000000000;
+    uint64_t bucketEndTimeNs = bucketStartTimeNs + bucketSizeNs;
+    uint64_t bucketNum = 0;
 
     int64_t metricId = 1;
     MaxDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, -1, dimensionInCondition,
-                               false, bucketStartTimeNs, bucketSizeNs, false, {});
+                               false, bucketStartTimeNs, bucketNum, bucketStartTimeNs, bucketSizeNs,
+                               false, {});
 
     // The event starts.
     tracker.noteStart(DEFAULT_DIMENSION_KEY, true, bucketStartTimeNs + 1, ConditionKey());
@@ -137,14 +150,18 @@
                       ConditionKey());
 
     // The event stops at early 4th bucket.
+    // Notestop is called from DurationMetricProducer's onMatchedLogEvent, which calls
+    // flushIfneeded.
     tracker.flushIfNeeded(bucketStartTimeNs + (3 * bucketSizeNs) + 20, &buckets);
     tracker.noteStop(DEFAULT_DIMENSION_KEY, bucketStartTimeNs + (3 * bucketSizeNs) + 20,
                      false /*stop all*/);
-    EXPECT_TRUE(buckets.find(eventKey) != buckets.end());
-    EXPECT_EQ(3u, buckets[eventKey].size());
-    EXPECT_EQ((unsigned long long)(bucketSizeNs - 1), buckets[eventKey][0].mDuration);
-    EXPECT_EQ((unsigned long long)bucketSizeNs, buckets[eventKey][1].mDuration);
-    EXPECT_EQ((unsigned long long)bucketSizeNs, buckets[eventKey][2].mDuration);
+    EXPECT_TRUE(buckets.find(eventKey) == buckets.end());
+
+    tracker.flushIfNeeded(bucketStartTimeNs + 4 * bucketSizeNs, &buckets);
+    EXPECT_EQ(1u, buckets[eventKey].size());
+    EXPECT_EQ((3 * bucketSizeNs) + 20 - 1, buckets[eventKey][0].mDuration);
+    EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs, buckets[eventKey][0].mBucketStartNs);
+    EXPECT_EQ(bucketStartTimeNs + 4 * bucketSizeNs, buckets[eventKey][0].mBucketEndNs);
 }
 
 TEST(MaxDurationTrackerTest, TestCrossBucketBoundary_nested) {
@@ -152,17 +169,20 @@
     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;
 
-    uint64_t bucketStartTimeNs = 10000000000;
     uint64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL;
+    uint64_t bucketStartTimeNs = 10000000000;
+    uint64_t bucketEndTimeNs = bucketStartTimeNs + bucketSizeNs;
+    uint64_t bucketNum = 0;
 
     int64_t metricId = 1;
     MaxDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, -1, dimensionInCondition,
-                               true, bucketStartTimeNs, bucketSizeNs, false, {});
+                               true, bucketStartTimeNs, bucketNum, bucketStartTimeNs, bucketSizeNs,
+                               false, {});
 
     // 2 starts
     tracker.noteStart(DEFAULT_DIMENSION_KEY, true, bucketStartTimeNs + 1, ConditionKey());
@@ -171,28 +191,23 @@
     tracker.noteStop(DEFAULT_DIMENSION_KEY, bucketStartTimeNs + 20, false /*stop all*/);
 
     tracker.flushIfNeeded(bucketStartTimeNs + (2 * bucketSizeNs) + 1, &buckets);
-
-    EXPECT_TRUE(buckets.find(eventKey) != buckets.end());
-    EXPECT_EQ(2u, buckets[eventKey].size());
-    EXPECT_EQ(bucketSizeNs - 1, buckets[eventKey][0].mDuration);
-    EXPECT_EQ(bucketSizeNs, buckets[eventKey][1].mDuration);
+    // Because of nesting, still not stopped.
+    EXPECT_TRUE(buckets.find(eventKey) == buckets.end());
 
     // real stop now.
     tracker.noteStop(DEFAULT_DIMENSION_KEY,
                      bucketStartTimeNs + (2 * bucketSizeNs) + 5, false);
     tracker.flushIfNeeded(bucketStartTimeNs + (3 * bucketSizeNs) + 1, &buckets);
 
-    EXPECT_EQ(3u, buckets[eventKey].size());
-    EXPECT_EQ(bucketSizeNs - 1, buckets[eventKey][0].mDuration);
-    EXPECT_EQ(bucketSizeNs, buckets[eventKey][1].mDuration);
-    EXPECT_EQ(5ULL, buckets[eventKey][2].mDuration);
+    EXPECT_EQ(1u, buckets[eventKey].size());
+    EXPECT_EQ(2 * bucketSizeNs + 5 - 1, buckets[eventKey][0].mDuration);
 }
 
 TEST(MaxDurationTrackerTest, TestMaxDurationWithCondition) {
     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;
@@ -204,14 +219,17 @@
 
     unordered_map<MetricDimensionKey, vector<DurationBucket>> buckets;
 
-    uint64_t bucketStartTimeNs = 10000000000;
-    uint64_t eventStartTimeNs = bucketStartTimeNs + 1;
     uint64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL;
+    uint64_t bucketStartTimeNs = 10000000000;
+    uint64_t bucketEndTimeNs = bucketStartTimeNs + bucketSizeNs;
+    uint64_t bucketNum = 0;
+    uint64_t eventStartTimeNs = bucketStartTimeNs + 1;
     int64_t durationTimeNs = 2 * 1000;
 
     int64_t metricId = 1;
     MaxDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, dimensionInCondition,
-                               false, bucketStartTimeNs, bucketSizeNs, true, {});
+                               false, bucketStartTimeNs, bucketNum, bucketStartTimeNs, bucketSizeNs,
+                               true, {});
     EXPECT_TRUE(tracker.mAnomalyTrackers.empty());
 
     tracker.noteStart(key1, true, eventStartTimeNs, conditionKey1);
@@ -226,45 +244,6 @@
     EXPECT_EQ(5ULL, buckets[eventKey][0].mDuration);
 }
 
-TEST(MaxDurationTrackerTest, TestAnomalyDetection) {
-    const MetricDimensionKey eventKey = getMockedMetricDimensionKey(TagId, 0, "1");
-    const HashableDimensionKey key1 = getMockedDimensionKey(TagId, 1, "1");
-    const HashableDimensionKey key2 = getMockedDimensionKey(TagId, 1, "2");
-    FieldMatcher dimensionInCondition;
-    int64_t metricId = 1;
-    Alert alert;
-    alert.set_id(101);
-    alert.set_metric_id(metricId);
-    alert.set_trigger_if_sum_gt(32 * NS_PER_SEC);
-    alert.set_num_buckets(2);
-    const int32_t refPeriodSec = 1;
-    alert.set_refractory_period_secs(refPeriodSec);
-
-    unordered_map<MetricDimensionKey, vector<DurationBucket>> buckets;
-    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
-
-    uint64_t bucketStartTimeNs = 10 * NS_PER_SEC;
-    uint64_t eventStartTimeNs = bucketStartTimeNs + NS_PER_SEC + 1;
-    uint64_t bucketSizeNs = 30 * NS_PER_SEC;
-
-    sp<DurationAnomalyTracker> anomalyTracker = new DurationAnomalyTracker(alert, kConfigKey);
-    MaxDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, -1, dimensionInCondition,
-                               true, bucketStartTimeNs, bucketSizeNs, false, {anomalyTracker});
-
-    tracker.noteStart(key1, true, eventStartTimeNs, ConditionKey());
-    tracker.noteStop(key1, eventStartTimeNs + 10, false);
-    EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(eventKey), 0U);
-    EXPECT_EQ(10LL, tracker.mDuration);
-
-    tracker.noteStart(key2, true, eventStartTimeNs + 20, ConditionKey());
-    tracker.flushIfNeeded(eventStartTimeNs + 2 * bucketSizeNs + 3 * NS_PER_SEC, &buckets);
-    tracker.noteStop(key2, eventStartTimeNs + 2 * bucketSizeNs + 3 * NS_PER_SEC, false);
-    EXPECT_EQ((long long)(4 * NS_PER_SEC + 1LL), tracker.mDuration);
-
-    EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(eventKey),
-              (eventStartTimeNs + 2 * bucketSizeNs) / NS_PER_SEC  + 3 + refPeriodSec);
-}
-
 }  // namespace statsd
 }  // namespace os
 }  // namespace android
diff --git a/cmds/statsd/tests/metrics/OringDurationTracker_test.cpp b/cmds/statsd/tests/metrics/OringDurationTracker_test.cpp
index 80e16a1..cb731c5 100644
--- a/cmds/statsd/tests/metrics/OringDurationTracker_test.cpp
+++ b/cmds/statsd/tests/metrics/OringDurationTracker_test.cpp
@@ -38,6 +38,12 @@
 const ConfigKey kConfigKey(0, 12345);
 const int TagId = 1;
 const int64_t metricId = 123;
+const HashableDimensionKey eventKey = getMockedDimensionKey(TagId, 0, "event");
+
+const std::vector<HashableDimensionKey> kConditionKey1 = {getMockedDimensionKey(TagId, 1, "maps")};
+const HashableDimensionKey kEventKey1 = getMockedDimensionKey(TagId, 2, "maps");
+const HashableDimensionKey kEventKey2 = getMockedDimensionKey(TagId, 3, "maps");
+const uint64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL;
 
 TEST(OringDurationTrackerTest, TestDurationOverlap) {
     const MetricDimensionKey eventKey = getMockedMetricDimensionKey(TagId, 0, "event");
@@ -46,18 +52,20 @@
         {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;
 
-    uint64_t bucketStartTimeNs = 10000000000;
-    uint64_t eventStartTimeNs = bucketStartTimeNs + 1;
     uint64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL;
+    uint64_t bucketStartTimeNs = 10000000000;
+    uint64_t bucketNum = 0;
+    uint64_t eventStartTimeNs = bucketStartTimeNs + 1;
     uint64_t durationTimeNs = 2 * 1000;
 
     OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, dimensionInCondition,
-                                 false, bucketStartTimeNs, bucketSizeNs, false, {});
+                                 false, bucketStartTimeNs, bucketNum, bucketStartTimeNs,
+                                 bucketSizeNs, false, {});
 
     tracker.noteStart(kEventKey1, true, eventStartTimeNs, ConditionKey());
     EXPECT_EQ((long long)eventStartTimeNs, tracker.mLastStartTime);
@@ -79,17 +87,19 @@
         {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;
 
-    uint64_t bucketStartTimeNs = 10000000000;
-    uint64_t eventStartTimeNs = bucketStartTimeNs + 1;
     uint64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL;
+    uint64_t bucketStartTimeNs = 10000000000;
+    uint64_t bucketNum = 0;
+    uint64_t eventStartTimeNs = bucketStartTimeNs + 1;
 
     OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, dimensionInCondition,
-                                 true, bucketStartTimeNs, bucketSizeNs, false, {});
+                                 true, bucketStartTimeNs, bucketNum, bucketStartTimeNs,
+                                 bucketSizeNs, false, {});
 
     tracker.noteStart(kEventKey1, true, eventStartTimeNs, ConditionKey());
     tracker.noteStart(kEventKey1, true, eventStartTimeNs + 10, ConditionKey());  // overlapping wl
@@ -110,17 +120,19 @@
         {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;
 
-    uint64_t bucketStartTimeNs = 10000000000;
-    uint64_t eventStartTimeNs = bucketStartTimeNs + 1;
     uint64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL;
+    uint64_t bucketStartTimeNs = 10000000000;
+    uint64_t bucketNum = 0;
+    uint64_t eventStartTimeNs = bucketStartTimeNs + 1;
 
     OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, dimensionInCondition,
-                                 true, bucketStartTimeNs, bucketSizeNs, false, {});
+                                 true, bucketStartTimeNs, bucketNum, bucketStartTimeNs,
+                                 bucketSizeNs, false, {});
 
     tracker.noteStart(kEventKey1, true, eventStartTimeNs, ConditionKey());
     tracker.noteStart(kEventKey2, true, eventStartTimeNs + 10, ConditionKey());  // overlapping wl
@@ -140,18 +152,20 @@
         {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;
 
-    uint64_t bucketStartTimeNs = 10000000000;
-    uint64_t eventStartTimeNs = bucketStartTimeNs + 1;
     uint64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL;
+    uint64_t bucketStartTimeNs = 10000000000;
+    uint64_t bucketNum = 0;
+    uint64_t eventStartTimeNs = bucketStartTimeNs + 1;
     uint64_t durationTimeNs = 2 * 1000;
 
     OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, dimensionInCondition,
-                                 true, bucketStartTimeNs, bucketSizeNs, false, {});
+                                 true, bucketStartTimeNs, bucketNum, bucketStartTimeNs,
+                                 bucketSizeNs, false, {});
 
     tracker.noteStart(kEventKey1, true, eventStartTimeNs, ConditionKey());
     EXPECT_EQ((long long)eventStartTimeNs, tracker.mLastStartTime);
@@ -179,7 +193,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;
@@ -190,13 +204,15 @@
 
     unordered_map<MetricDimensionKey, vector<DurationBucket>> buckets;
 
-    uint64_t bucketStartTimeNs = 10000000000;
-    uint64_t eventStartTimeNs = bucketStartTimeNs + 1;
     uint64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL;
+    uint64_t bucketStartTimeNs = 10000000000;
+    uint64_t bucketNum = 0;
+    uint64_t eventStartTimeNs = bucketStartTimeNs + 1;
     uint64_t durationTimeNs = 2 * 1000;
 
     OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, dimensionInCondition,
-                                 false, bucketStartTimeNs, bucketSizeNs, true, {});
+                                 false, bucketStartTimeNs, bucketNum, bucketStartTimeNs,
+                                 bucketSizeNs, true, {});
 
     tracker.noteStart(kEventKey1, true, eventStartTimeNs, key1);
 
@@ -217,7 +233,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;
@@ -231,12 +247,14 @@
     unordered_map<MetricDimensionKey, vector<DurationBucket>> buckets;
 
     uint64_t bucketStartTimeNs = 10000000000;
-    uint64_t eventStartTimeNs = bucketStartTimeNs + 1;
     uint64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL;
+    uint64_t bucketNum = 0;
+    uint64_t eventStartTimeNs = bucketStartTimeNs + 1;
     uint64_t durationTimeNs = 2 * 1000;
 
     OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, dimensionInCondition,
-                                 false, bucketStartTimeNs, bucketSizeNs, true, {});
+                                 false, bucketStartTimeNs, bucketNum, bucketStartTimeNs,
+                                 bucketSizeNs, true, {});
 
     tracker.noteStart(kEventKey1, true, eventStartTimeNs, key1);
     // condition to false; record duration 5n
@@ -259,7 +277,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;
@@ -271,11 +289,13 @@
     unordered_map<MetricDimensionKey, vector<DurationBucket>> buckets;
 
     uint64_t bucketStartTimeNs = 10000000000;
-    uint64_t eventStartTimeNs = bucketStartTimeNs + 1;
     uint64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL;
+    uint64_t bucketNum = 0;
+    uint64_t eventStartTimeNs = bucketStartTimeNs + 1;
 
     OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, dimensionInCondition,
-                                 true, bucketStartTimeNs, bucketSizeNs, true, {});
+                                 true, bucketStartTimeNs, bucketNum, bucketStartTimeNs,
+                                 bucketSizeNs, true, {});
 
     tracker.noteStart(kEventKey1, true, eventStartTimeNs, key1);
     tracker.noteStart(kEventKey1, true, eventStartTimeNs + 2, key1);
@@ -299,7 +319,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);
@@ -311,12 +331,13 @@
     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
 
     uint64_t bucketStartTimeNs = 10 * NS_PER_SEC;
+    uint64_t bucketNum = 0;
     uint64_t eventStartTimeNs = bucketStartTimeNs + NS_PER_SEC + 1;
-    uint64_t bucketSizeNs = 30 * NS_PER_SEC;
 
     sp<DurationAnomalyTracker> anomalyTracker = new DurationAnomalyTracker(alert, kConfigKey);
     OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, dimensionInCondition,
-                                 true, bucketStartTimeNs, bucketSizeNs, true, {anomalyTracker});
+                                 true, bucketStartTimeNs, bucketNum, bucketStartTimeNs,
+                                 bucketSizeNs, true, {anomalyTracker});
 
     // Nothing in the past bucket.
     tracker.noteStart(DEFAULT_DIMENSION_KEY, true, eventStartTimeNs, ConditionKey());
@@ -366,7 +387,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);
@@ -379,26 +400,27 @@
     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
 
     uint64_t bucketStartTimeNs = 10 * NS_PER_SEC;
+    uint64_t bucketNum = 0;
     uint64_t eventStartTimeNs = bucketStartTimeNs + NS_PER_SEC + 1;
-    uint64_t bucketSizeNs = 30 * NS_PER_SEC;
 
     sp<DurationAnomalyTracker> anomalyTracker = new DurationAnomalyTracker(alert, kConfigKey);
     OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, dimensionInCondition,
-                                 true /*nesting*/, bucketStartTimeNs, bucketSizeNs, false, {anomalyTracker});
+                                 true /*nesting*/, bucketStartTimeNs, bucketNum, bucketStartTimeNs,
+                                 bucketSizeNs, false, {anomalyTracker});
 
     tracker.noteStart(kEventKey1, true, eventStartTimeNs, ConditionKey());
     tracker.noteStop(kEventKey1, eventStartTimeNs + 10, false);
     EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(eventKey), 0U);
     EXPECT_TRUE(tracker.mStarted.empty());
-    EXPECT_EQ(10LL, tracker.mDuration);
+    EXPECT_EQ(10LL, tracker.mDuration); // 10ns
 
     EXPECT_EQ(0u, tracker.mStarted.size());
 
     tracker.noteStart(kEventKey1, true, eventStartTimeNs + 20, ConditionKey());
     EXPECT_EQ(1u, anomalyTracker->mAlarms.size());
-    EXPECT_EQ((long long)(51ULL * NS_PER_SEC),
+    EXPECT_EQ((long long)(52ULL * NS_PER_SEC),  // (10s + 1s + 1ns + 20ns) - 10ns + 40s, rounded up
               (long long)(anomalyTracker->mAlarms.begin()->second->timestampSec * NS_PER_SEC));
-    // The alarm is set to fire at 51s, and when it does, an anomaly would be declared. However,
+    // The alarm is set to fire at 52s, and when it does, an anomaly would be declared. However,
     // because this is a unit test, the alarm won't actually fire at all. Since the alarm fails
     // to fire in time, the anomaly is instead caught when noteStop is called, at around 71s.
     tracker.flushIfNeeded(eventStartTimeNs + 2 * bucketSizeNs + 25, &buckets);
@@ -415,7 +437,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);
@@ -429,13 +451,12 @@
     ConditionKey conkey;
     conkey[StringToId("APP_BACKGROUND")] = kConditionKey1;
     uint64_t bucketStartTimeNs = 10 * NS_PER_SEC;
-    uint64_t eventStartTimeNs = bucketStartTimeNs + NS_PER_SEC + 1;
     uint64_t bucketSizeNs = 30 * NS_PER_SEC;
 
     sp<DurationAnomalyTracker> anomalyTracker = new DurationAnomalyTracker(alert, kConfigKey);
     OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, dimensionInCondition,
-                                 true /*nesting*/, bucketStartTimeNs, bucketSizeNs, false,
-                                 {anomalyTracker});
+                                 true /*nesting*/, bucketStartTimeNs, 0, bucketStartTimeNs,
+                                 bucketSizeNs, false, {anomalyTracker});
 
     tracker.noteStart(kEventKey1, true, 15 * NS_PER_SEC, conkey); // start key1
     EXPECT_EQ(1u, anomalyTracker->mAlarms.size());
diff --git a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
index 55c078d..ce4fa32 100644
--- a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
@@ -44,6 +44,7 @@
 const int64_t bucket2StartTimeNs = bucketStartTimeNs + bucketSizeNs;
 const int64_t bucket3StartTimeNs = bucketStartTimeNs + 2 * bucketSizeNs;
 const int64_t bucket4StartTimeNs = bucketStartTimeNs + 3 * bucketSizeNs;
+const int64_t eventUpgradeTimeNs = bucketStartTimeNs + 15 * NS_PER_SEC;
 
 /*
  * Tests pulled atoms with no conditions
@@ -65,6 +66,7 @@
 
     ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
                                       tagId, bucketStartTimeNs, pullerManager);
+    valueProducer.setBucketSize(60 * NS_PER_SEC);
 
     vector<shared_ptr<LogEvent>> allData;
     allData.clear();
@@ -78,6 +80,8 @@
     // has one slice
     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
     ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
+    valueProducer.setBucketSize(60 * NS_PER_SEC);
+
     // startUpdated:true tainted:0 sum:0 start:11
     EXPECT_EQ(true, curInterval.startUpdated);
     EXPECT_EQ(0, curInterval.tainted);
@@ -161,7 +165,7 @@
 
     ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, tagId, bucketStartTimeNs,
                                       pullerManager);
-
+    valueProducer.setBucketSize(60 * NS_PER_SEC);
     valueProducer.onConditionChanged(true, bucketStartTimeNs + 8);
 
     // has one slice
@@ -202,6 +206,103 @@
     EXPECT_EQ(false, curInterval.startUpdated);
 }
 
+TEST(ValueMetricProducerTest, TestPushedEventsWithUpgrade) {
+    ValueMetric metric;
+    metric.set_id(metricId);
+    metric.set_bucket(ONE_MINUTE);
+    metric.mutable_value_field()->set_field(tagId);
+    metric.mutable_value_field()->add_child()->set_field(2);
+
+    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+    shared_ptr<MockStatsPullerManager> pullerManager =
+            make_shared<StrictMock<MockStatsPullerManager>>();
+    ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, -1, bucketStartTimeNs,
+                                      pullerManager);
+    valueProducer.setBucketSize(60 * NS_PER_SEC);
+
+    shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
+    event1->write(1);
+    event1->write(10);
+    event1->init();
+    valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
+    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+
+    valueProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
+    EXPECT_EQ(1UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+    EXPECT_EQ((uint64_t)eventUpgradeTimeNs, valueProducer.mCurrentBucketStartTimeNs);
+
+    shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 59 * NS_PER_SEC);
+    event2->write(1);
+    event2->write(10);
+    event2->init();
+    valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
+    EXPECT_EQ(1UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+    EXPECT_EQ((uint64_t)eventUpgradeTimeNs, valueProducer.mCurrentBucketStartTimeNs);
+
+    // Next value should create a new bucket.
+    shared_ptr<LogEvent> event3 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 65 * NS_PER_SEC);
+    event3->write(1);
+    event3->write(10);
+    event3->init();
+    valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event3);
+    EXPECT_EQ(2UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+    EXPECT_EQ((uint64_t)bucketStartTimeNs + bucketSizeNs, valueProducer.mCurrentBucketStartTimeNs);
+}
+
+TEST(ValueMetricProducerTest, TestPulledValueWithUpgrade) {
+    ValueMetric metric;
+    metric.set_id(metricId);
+    metric.set_bucket(ONE_MINUTE);
+    metric.mutable_value_field()->set_field(tagId);
+    metric.mutable_value_field()->add_child()->set_field(2);
+
+    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+    shared_ptr<MockStatsPullerManager> pullerManager =
+            make_shared<StrictMock<MockStatsPullerManager>>();
+    EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _)).WillOnce(Return());
+    EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
+    EXPECT_CALL(*pullerManager, Pull(tagId, _))
+            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+                data->clear();
+                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
+                event->write(tagId);
+                event->write(120);
+                event->init();
+                data->push_back(event);
+                return true;
+            }));
+    ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, tagId, bucketStartTimeNs,
+                                      pullerManager);
+    valueProducer.setBucketSize(60 * NS_PER_SEC);
+
+    vector<shared_ptr<LogEvent>> allData;
+    allData.clear();
+    shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
+    event->write(tagId);
+    event->write(100);
+    event->init();
+    allData.push_back(event);
+
+    valueProducer.onDataPulled(allData);
+    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+
+    valueProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
+    EXPECT_EQ(1UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+    EXPECT_EQ((uint64_t)eventUpgradeTimeNs, valueProducer.mCurrentBucketStartTimeNs);
+    EXPECT_EQ(20L, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mValue);
+
+    allData.clear();
+    event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
+    event->write(tagId);
+    event->write(150);
+    event->init();
+    allData.push_back(event);
+    valueProducer.onDataPulled(allData);
+    EXPECT_EQ(2UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+    EXPECT_EQ((uint64_t)bucket2StartTimeNs, valueProducer.mCurrentBucketStartTimeNs);
+    EXPECT_EQ(30L, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][1].mValue);
+}
+
 TEST(ValueMetricProducerTest, TestPushedEventsWithoutCondition) {
     ValueMetric metric;
     metric.set_id(metricId);
@@ -215,6 +316,7 @@
 
     ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, -1, bucketStartTimeNs,
                                       pullerManager);
+    valueProducer.setBucketSize(60 * NS_PER_SEC);
 
     shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
     event1->write(1);
@@ -261,6 +363,8 @@
     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
     ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
                                       -1 /*not pulled*/, bucketStartTimeNs);
+    valueProducer.setBucketSize(60 * NS_PER_SEC);
+
     sp<AnomalyTracker> anomalyTracker = valueProducer.addAnomalyTracker(alert);
 
 
@@ -310,16 +414,16 @@
     valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event4);
     // Anomaly at event 4 since Value sum == 131 > 130!
     EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
-            event4->GetTimestampNs() / NS_PER_SEC + refPeriodSec);
+            event4->GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec);
     valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event5);
     // Event 5 is within 3 sec refractory period. Thus last alarm timestamp is still event4.
     EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
-            event4->GetTimestampNs() / NS_PER_SEC + refPeriodSec);
+            event4->GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec);
 
     valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event6);
     // Anomaly at event 6 since Value sum == 160 > 130 and after refractory period.
     EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
-            event6->GetTimestampNs() / NS_PER_SEC + refPeriodSec);
+            event6->GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec);
 }
 
 }  // namespace statsd
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 0a97456..a01de63 100644
--- a/cmds/statsd/tests/metrics/metrics_test_helper.h
+++ b/cmds/statsd/tests/metrics/metrics_test_helper.h
@@ -15,6 +15,7 @@
 
 #include "src/condition/ConditionWizard.h"
 #include "src/external/StatsPullerManager.h"
+#include "src/packages/UidMap.h"
 
 #include <gmock/gmock.h>
 #include <gtest/gtest.h>
@@ -25,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 {
@@ -40,9 +39,18 @@
     MOCK_METHOD2(Pull, bool(const int pullCode, vector<std::shared_ptr<LogEvent>>* data));
 };
 
+class MockUidMap : public UidMap {
+ public:
+  MOCK_CONST_METHOD1(getHostUidOrSelf, int(int uid));
+};
+
 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..b7acef7 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;
@@ -406,7 +406,7 @@
 void sortLogEventsByTimestamp(std::vector<std::unique_ptr<LogEvent>> *events) {
   std::sort(events->begin(), events->end(),
             [](const std::unique_ptr<LogEvent>& a, const std::unique_ptr<LogEvent>& b) {
-              return a->GetTimestampNs() < b->GetTimestampNs();
+              return a->GetElapsedTimestampNs() < b->GetElapsedTimestampNs();
             });
 }
 
@@ -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/cmds/statsd/tools/dogfood/AndroidManifest.xml b/cmds/statsd/tools/dogfood/AndroidManifest.xml
index cd76c9d..52673fb 100644
--- a/cmds/statsd/tools/dogfood/AndroidManifest.xml
+++ b/cmds/statsd/tools/dogfood/AndroidManifest.xml
@@ -37,5 +37,7 @@
                 <category android:name="android.intent.category.LAUNCHER" />
             </intent-filter>
         </activity>
+
+        <service android:name=".MainActivity$ReceiverIntentService" android:exported="true" />
     </application>
 </manifest>
diff --git a/cmds/statsd/tools/dogfood/res/layout/activity_main.xml b/cmds/statsd/tools/dogfood/res/layout/activity_main.xml
index 5d35c29..784ed40 100644
--- a/cmds/statsd/tools/dogfood/res/layout/activity_main.xml
+++ b/cmds/statsd/tools/dogfood/res/layout/activity_main.xml
@@ -31,6 +31,18 @@
             android:layout_height="wrap_content"
             android:background="@android:color/holo_green_light"
             android:text="@string/push_config"/>
+        <Button
+                android:id="@+id/set_receiver"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:background="@android:color/holo_green_light"
+                android:text="@string/set_receiver"/>
+        <Button
+                android:id="@+id/remove_receiver"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:background="@android:color/holo_green_light"
+                android:text="@string/remove_receiver"/>
 
         <LinearLayout android:layout_width="wrap_content"
             android:layout_height="wrap_content"
diff --git a/cmds/statsd/tools/dogfood/res/values/strings.xml b/cmds/statsd/tools/dogfood/res/values/strings.xml
index 0eab0f4..60948a1 100644
--- a/cmds/statsd/tools/dogfood/res/values/strings.xml
+++ b/cmds/statsd/tools/dogfood/res/values/strings.xml
@@ -24,6 +24,8 @@
     <string name="statsd_not_running">Statsd NOT Running</string>
 
     <string name="push_config">Push baseline config</string>
+    <string name="set_receiver">Set pendingintent</string>
+    <string name="remove_receiver">Remove pendingintent</string>
 
     <string name="app_a_foreground">App A foreground</string>
     <string name="app_b_foreground">App B foreground</string>
diff --git a/cmds/statsd/tools/dogfood/src/com/android/statsd/dogfood/DisplayProtoUtils.java b/cmds/statsd/tools/dogfood/src/com/android/statsd/dogfood/DisplayProtoUtils.java
index 33c8abf..b6b16e4 100644
--- a/cmds/statsd/tools/dogfood/src/com/android/statsd/dogfood/DisplayProtoUtils.java
+++ b/cmds/statsd/tools/dogfood/src/com/android/statsd/dogfood/DisplayProtoUtils.java
@@ -32,11 +32,13 @@
 
         for (StatsLog.ConfigMetricsReport report : reports.getReportsList()) {
             sb.append("StatsLogReport size: ").append(report.getMetricsCount()).append("\n");
+            sb.append("Last report time:").append(getDateStr(report.getLastReportElapsedNanos())).
+                    append("\n");
+            sb.append("Current report time:").append(getDateStr(report.getCurrentReportElapsedNanos())).
+                    append("\n");
             for (StatsLog.StatsLogReport log : report.getMetricsList()) {
                 sb.append("\n\n");
                 sb.append("metric id: ").append(log.getMetricId()).append("\n");
-                sb.append("start time:").append(getDateStr(log.getStartReportNanos())).append("\n");
-                sb.append("end time:").append(getDateStr(log.getEndReportNanos())).append("\n");
 
                 switch (log.getDataCase()) {
                     case DURATION_METRICS:
@@ -107,8 +109,8 @@
             }
 
             for (StatsLog.DurationBucketInfo info : duration.getBucketInfoList())  {
-                sb.append("\t[").append(getDateStr(info.getStartBucketNanos())).append("-")
-                        .append(getDateStr(info.getEndBucketNanos())).append("] -> ")
+                sb.append("\t[").append(getDateStr(info.getStartBucketElapsedNanos())).append("-")
+                        .append(getDateStr(info.getEndBucketElapsedNanos())).append("] -> ")
                         .append(info.getDurationNanos()).append(" ns\n");
             }
         }
@@ -119,7 +121,7 @@
         StatsLog.StatsLogReport.EventMetricDataWrapper eventMetricDataWrapper =
                 log.getEventMetrics();
         for (StatsLog.EventMetricData event : eventMetricDataWrapper.getDataList()) {
-            sb.append(getDateStr(event.getTimestampNanos())).append(": ");
+            sb.append(getDateStr(event.getElapsedTimestampNanos())).append(": ");
             sb.append(event.getAtom().getPushedCase().toString()).append("\n");
         }
     }
@@ -139,8 +141,8 @@
             }
 
             for (StatsLog.CountBucketInfo info : count.getBucketInfoList())  {
-                sb.append("\t[").append(getDateStr(info.getStartBucketNanos())).append("-")
-                        .append(getDateStr(info.getEndBucketNanos())).append("] -> ")
+                sb.append("\t[").append(getDateStr(info.getStartBucketElapsedNanos())).append("-")
+                        .append(getDateStr(info.getEndBucketElapsedNanos())).append("] -> ")
                         .append(info.getCount()).append("\n");
             }
         }
diff --git a/cmds/statsd/tools/dogfood/src/com/android/statsd/dogfood/MainActivity.java b/cmds/statsd/tools/dogfood/src/com/android/statsd/dogfood/MainActivity.java
index 57575ae..0e6c933 100644
--- a/cmds/statsd/tools/dogfood/src/com/android/statsd/dogfood/MainActivity.java
+++ b/cmds/statsd/tools/dogfood/src/com/android/statsd/dogfood/MainActivity.java
@@ -16,7 +16,10 @@
 package com.android.statsd.dogfood;
 
 import android.app.Activity;
+import android.app.PendingIntent;
+import android.app.IntentService;
 import android.app.StatsManager;
+import android.content.Context;
 import android.content.Intent;
 import android.content.res.Resources;
 import android.os.Bundle;
@@ -48,69 +51,69 @@
 
         findViewById(R.id.app_a_wake_lock_acquire1).setOnClickListener(
                 new View.OnClickListener() {
-            @Override
-            public void onClick(View view) {
-                onWakeLockAcquire(0, "wl_1");
-            }
-        });
+                    @Override
+                    public void onClick(View view) {
+                        onWakeLockAcquire(0, "wl_1");
+                    }
+                });
 
         findViewById(R.id.app_b_wake_lock_acquire1).setOnClickListener(
                 new View.OnClickListener() {
-            @Override
-            public void onClick(View view) {
-                onWakeLockAcquire(1, "wl_1");
-            }
-        });
+                    @Override
+                    public void onClick(View view) {
+                        onWakeLockAcquire(1, "wl_1");
+                    }
+                });
 
         findViewById(R.id.app_a_wake_lock_acquire2).setOnClickListener(
                 new View.OnClickListener() {
-            @Override
-            public void onClick(View view) {
-                onWakeLockAcquire(0, "wl_2");
-            }
-        });
+                    @Override
+                    public void onClick(View view) {
+                        onWakeLockAcquire(0, "wl_2");
+                    }
+                });
 
         findViewById(R.id.app_b_wake_lock_acquire2).setOnClickListener(
                 new View.OnClickListener() {
-            @Override
-            public void onClick(View view) {
-                onWakeLockAcquire(1, "wl_2");
-            }
-        });
+                    @Override
+                    public void onClick(View view) {
+                        onWakeLockAcquire(1, "wl_2");
+                    }
+                });
 
         findViewById(R.id.app_a_wake_lock_release1).setOnClickListener(
                 new View.OnClickListener() {
-            @Override
-            public void onClick(View view) {
-                onWakeLockRelease(0, "wl_1");
-            }
-        });
+                    @Override
+                    public void onClick(View view) {
+                        onWakeLockRelease(0, "wl_1");
+                    }
+                });
 
 
         findViewById(R.id.app_b_wake_lock_release1).setOnClickListener(
                 new View.OnClickListener() {
-            @Override
-            public void onClick(View view) {
-                onWakeLockRelease(1, "wl_1");
-            }
-        });
+                    @Override
+                    public void onClick(View view) {
+                        onWakeLockRelease(1, "wl_1");
+                    }
+                });
 
         findViewById(R.id.app_a_wake_lock_release2).setOnClickListener(
                 new View.OnClickListener() {
-            @Override
-            public void onClick(View view) {
-                onWakeLockRelease(0, "wl_2");
-            }
-        });
+                    @Override
+                    public void onClick(View view) {
+                        onWakeLockRelease(0, "wl_2");
+                    }
+                });
 
 
         findViewById(R.id.app_b_wake_lock_release2).setOnClickListener(
                 new View.OnClickListener() {
-            @Override
-            public void onClick(View view) {
-                onWakeLockRelease(1, "wl_2");
-            }
-        });
+                    @Override
+                    public void onClick(View view) {
+                        onWakeLockRelease(1, "wl_2");
+                    }
+                });
 
 
         findViewById(R.id.plug).setOnClickListener(new View.OnClickListener() {
@@ -191,8 +194,7 @@
                     byte[] config = new byte[inputStream.available()];
                     inputStream.read(config);
                     if (mStatsManager != null) {
-                        if (mStatsManager.addConfiguration(CONFIG_ID,
-                                config, getPackageName(), MainActivity.this.getClass().getName())) {
+                        if (mStatsManager.addConfiguration(CONFIG_ID, config)) {
                             Toast.makeText(
                                     MainActivity.this, "Config pushed", Toast.LENGTH_LONG).show();
                         } else {
@@ -205,6 +207,55 @@
                 }
             }
         });
+
+        PendingIntent pi = PendingIntent.getService(this, 0,
+                new Intent(this, ReceiverIntentService.class), PendingIntent.FLAG_UPDATE_CURRENT);
+        findViewById(R.id.set_receiver).setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View view) {
+                try {
+                    if (!statsdRunning()) {
+                        return;
+                    }
+                    if (mStatsManager != null) {
+                        if (mStatsManager.setDataFetchOperation(CONFIG_ID, pi)) {
+                            Toast.makeText(MainActivity.this,
+                                    "Receiver specified to pending intent", Toast.LENGTH_LONG)
+                                    .show();
+                        } else {
+                            Toast.makeText(MainActivity.this, "Statsd did not set receiver",
+                                    Toast.LENGTH_LONG)
+                                    .show();
+                        }
+                    }
+                } catch (Exception e) {
+                    Toast.makeText(MainActivity.this, "failed to set receiver", Toast.LENGTH_LONG);
+                }
+            }
+        });
+        findViewById(R.id.remove_receiver).setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View view) {
+                try {
+                    if (!statsdRunning()) {
+                        return;
+                    }
+                    if (mStatsManager != null) {
+                        if (mStatsManager.setDataFetchOperation(CONFIG_ID, null)) {
+                            Toast.makeText(MainActivity.this, "Receiver remove", Toast.LENGTH_LONG)
+                                    .show();
+                        } else {
+                            Toast.makeText(MainActivity.this, "Statsd did not remove receiver",
+                                    Toast.LENGTH_LONG)
+                                    .show();
+                        }
+                    }
+                } catch (Exception e) {
+                    Toast.makeText(
+                            MainActivity.this, "failed to remove receiver", Toast.LENGTH_LONG);
+                }
+            }
+        });
         mStatsManager = (StatsManager) getSystemService("stats");
     }
 
@@ -257,8 +308,8 @@
             Log.d(TAG, "invalid pkg id");
             return;
         }
-        int[] uids = new int[] {mUids[id]};
-        String[] tags  = new String[] {"acquire"};
+        int[] uids = new int[]{mUids[id]};
+        String[] tags = new String[]{"acquire"};
         StatsLog.write(StatsLog.WAKELOCK_STATE_CHANGED, uids, tags,
                 StatsLog.WAKELOCK_STATE_CHANGED__LEVEL__PARTIAL_WAKE_LOCK, name,
                 StatsLog.WAKELOCK_STATE_CHANGED__STATE__ACQUIRE);
@@ -273,8 +324,8 @@
             Log.d(TAG, "invalid pkg id");
             return;
         }
-        int[] uids = new int[] {mUids[id]};
-        String[] tags  = new String[] {"release"};
+        int[] uids = new int[]{mUids[id]};
+        String[] tags = new String[]{"release"};
         StatsLog.write(StatsLog.WAKELOCK_STATE_CHANGED, uids, tags,
                 StatsLog.WAKELOCK_STATE_CHANGED__LEVEL__PARTIAL_WAKE_LOCK, name,
                 StatsLog.WAKELOCK_STATE_CHANGED__STATE__RELEASE);
@@ -283,4 +334,20 @@
                 .append(", ").append(name).append(", 0);");
         Toast.makeText(this, sb.toString(), Toast.LENGTH_LONG).show();
     }
+
+    public static class ReceiverIntentService extends IntentService {
+        public ReceiverIntentService() {
+            super("ReceiverIntentService");
+        }
+
+        /**
+         * The IntentService calls this method from the default worker thread with
+         * the intent that started the service. When this method returns, IntentService
+         * stops the service, as appropriate.
+         */
+        @Override
+        protected void onHandleIntent(Intent intent) {
+            Log.i(TAG, "Received notification that we should call getData");
+        }
+    }
 }
diff --git a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/DisplayProtoUtils.java b/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/DisplayProtoUtils.java
index 75489ad..d55f3f3 100644
--- a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/DisplayProtoUtils.java
+++ b/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/DisplayProtoUtils.java
@@ -36,6 +36,10 @@
         int numMetrics = 0;
         for (StatsLog.ConfigMetricsReport report : reports.getReportsList()) {
             sb.append("StatsLogReport size: ").append(report.getMetricsCount()).append("\n");
+            sb.append("Last report time:").append(getDateStr(report.getLastReportElapsedNanos())).
+                    append("\n");
+            sb.append("Current report time:").append(getDateStr(report.getCurrentReportElapsedNanos())).
+                    append("\n");
             for (StatsLog.StatsLogReport log : report.getMetricsList()) {
                 numMetrics++;
                 if (numMetrics > MAX_NUM_METRICS_TO_DISPLAY) {
@@ -45,8 +49,6 @@
                 }
                 sb.append("\n");
                 sb.append("metric id: ").append(log.getMetricId()).append("\n");
-                sb.append("start time:").append(getDateStr(log.getStartReportNanos())).append("\n");
-                sb.append("end time:").append(getDateStr(log.getEndReportNanos())).append("\n");
 
                 switch (log.getDataCase()) {
                     case DURATION_METRICS:
@@ -118,8 +120,8 @@
             }
 
             for (StatsLog.DurationBucketInfo info : duration.getBucketInfoList())  {
-                sb.append("\t[").append(getDateStr(info.getStartBucketNanos())).append("-")
-                        .append(getDateStr(info.getEndBucketNanos())).append("] -> ")
+                sb.append("\t[").append(getDateStr(info.getStartBucketElapsedNanos())).append("-")
+                        .append(getDateStr(info.getEndBucketElapsedNanos())).append("] -> ")
                         .append(info.getDurationNanos()).append(" ns\n");
             }
         }
@@ -130,7 +132,7 @@
         StatsLog.StatsLogReport.EventMetricDataWrapper eventMetricDataWrapper =
                 log.getEventMetrics();
         for (StatsLog.EventMetricData event : eventMetricDataWrapper.getDataList()) {
-            sb.append(getDateStr(event.getTimestampNanos())).append(": ");
+            sb.append(getDateStr(event.getElapsedTimestampNanos())).append(": ");
             sb.append(event.getAtom().getPushedCase().toString()).append("\n");
         }
     }
@@ -150,8 +152,8 @@
             }
 
             for (StatsLog.CountBucketInfo info : count.getBucketInfoList())  {
-                sb.append("\t[").append(getDateStr(info.getStartBucketNanos())).append("-")
-                        .append(getDateStr(info.getEndBucketNanos())).append("] -> ")
+                sb.append("\t[").append(getDateStr(info.getStartBucketElapsedNanos())).append("-")
+                        .append(getDateStr(info.getEndBucketElapsedNanos())).append("] -> ")
                         .append(info.getCount()).append("\n");
             }
         }
diff --git a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/LoadtestActivity.java b/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/LoadtestActivity.java
index 652f6b2..bed4d98 100644
--- a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/LoadtestActivity.java
+++ b/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/LoadtestActivity.java
@@ -47,10 +47,12 @@
 import android.widget.Spinner;
 import android.widget.TextView;
 import android.widget.Toast;
+
 import com.android.os.StatsLog.ConfigMetricsReport;
 import com.android.os.StatsLog.ConfigMetricsReportList;
 import com.android.os.StatsLog.StatsdStatsReport;
 import com.android.internal.os.StatsdConfigProto.TimeUnit;
+
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
@@ -60,18 +62,18 @@
  * Runs a load test for statsd.
  * How it works:
  * <ul>
- *   <li> Sets up and pushes a custom config with metrics that exercise a large swath of code paths.
- *   <li> Periodically logs certain atoms into logd.
- *   <li> Impact on battery can be printed to logcat, or a bug report can be filed and analyzed
- *        in battery Historian.
+ * <li> Sets up and pushes a custom config with metrics that exercise a large swath of code paths.
+ * <li> Periodically logs certain atoms into logd.
+ * <li> Impact on battery can be printed to logcat, or a bug report can be filed and analyzed
+ * in battery Historian.
  * </ul>
  * The load depends on how demanding the config is, as well as how frequently atoms are pushsed
  * to logd. Those are all controlled by 4 adjustable parameters:
  * <ul>
- *   <li> The 'replication' parameter artificially multiplies the number of metrics in the config.
- *   <li> The bucket size controls the time-bucketing the aggregate metrics.
- *   <li> The period parameter controls how frequently atoms are pushed to logd.
- *   <li> The 'burst' parameter controls how many atoms are pushed at the same time (per period).
+ * <li> The 'replication' parameter artificially multiplies the number of metrics in the config.
+ * <li> The bucket size controls the time-bucketing the aggregate metrics.
+ * <li> The period parameter controls how frequently atoms are pushed to logd.
+ * <li> The 'burst' parameter controls how many atoms are pushed at the same time (per period).
  * </ul>
  */
 public class LoadtestActivity extends Activity implements AdapterView.OnItemSelectedListener {
@@ -93,7 +95,7 @@
             Intent activityIntent = new Intent(context, LoadtestActivity.class);
             activityIntent.putExtra(TYPE, PUSH_ALARM);
             context.startActivity(activityIntent);
-         }
+        }
     }
 
     public final static class StopperAlarmReceiver extends BroadcastReceiver {
@@ -102,7 +104,7 @@
             Intent activityIntent = new Intent(context, LoadtestActivity.class);
             activityIntent.putExtra(TYPE, STOP);
             context.startActivity(activityIntent);
-         }
+        }
     }
 
     private static Map<String, TimeUnit> initializeTimeUnitMap() {
@@ -119,6 +121,7 @@
         labels.put("1s", TimeUnit.CTS);
         return labels;
     }
+
     private static List<String> initializeTimeUnitLabels() {
         List<String> labels = new ArrayList();
         labels.add("1s");
@@ -136,10 +139,14 @@
 
     private AlarmManager mAlarmMgr;
 
-    /** Used to periodically log atoms to logd. */
+    /**
+     * Used to periodically log atoms to logd.
+     */
     private PendingIntent mPushPendingIntent;
 
-    /** Used to end the loadtest. */
+    /**
+     * Used to end the loadtest.
+     */
     private PendingIntent mStopPendingIntent;
 
     private Button mStartStop;
@@ -156,13 +163,19 @@
     private CheckBox mValueMetricCheckBox;
     private CheckBox mGaugeMetricCheckBox;
 
-    /** When the load test started. */
+    /**
+     * When the load test started.
+     */
     private long mStartedTimeMillis;
 
-    /** For measuring perf data. */
+    /**
+     * For measuring perf data.
+     */
     private PerfData mPerfData;
 
-    /** For communicating with statsd. */
+    /**
+     * For communicating with statsd.
+     */
     private StatsManager mStatsManager;
 
     private PowerManager mPowerManager;
@@ -199,34 +212,54 @@
      */
     private boolean mIncludeGaugeMetric;
 
-    /** The burst size. */
+    /**
+     * The burst size.
+     */
     private int mBurst;
 
-    /** The metrics replication. */
+    /**
+     * The metrics replication.
+     */
     private int mReplication;
 
-    /** The period, in seconds, at which batches of atoms are pushed. */
+    /**
+     * The period, in seconds, at which batches of atoms are pushed.
+     */
     private long mPeriodSecs;
 
-    /** The bucket size, in minutes, for aggregate metrics. */
+    /**
+     * The bucket size, in minutes, for aggregate metrics.
+     */
     private TimeUnit mBucket;
 
-    /** The duration, in minutes, of the loadtest. */
+    /**
+     * The duration, in minutes, of the loadtest.
+     */
     private long mDurationMins;
 
-    /** Whether the loadtest has started. */
+    /**
+     * Whether the loadtest has started.
+     */
     private boolean mStarted = false;
 
-    /** Orchestrates the logging of pushed events into logd. */
+    /**
+     * Orchestrates the logging of pushed events into logd.
+     */
     private SequencePusher mPusher;
 
-    /** Generates statsd configs. */
+    /**
+     * Generates statsd configs.
+     */
     private ConfigFactory mFactory;
 
-    /** For intra-minute periods. */
+    /**
+     * For intra-minute periods.
+     */
     private final Handler mHandler = new Handler();
 
-    /** Number of metrics in the current config. */
+    /**
+     * Number of metrics in the current config.
+     */
     private int mNumMetrics;
 
     @Override
@@ -250,7 +283,7 @@
             @Override
             public boolean onTouch(View v, MotionEvent event) {
                 InputMethodManager imm =
-                    (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
+                        (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
                 if (getCurrentFocus() != null) {
                     imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
                 }
@@ -380,10 +413,10 @@
         }
         // Piggy-back on that alarm to show the elapsed time.
         long elapsedTimeMins = (long) Math.floor(
-            (SystemClock.elapsedRealtime() - mStartedTimeMillis) / 60 / 1000);
+                (SystemClock.elapsedRealtime() - mStartedTimeMillis) / 60 / 1000);
         mReportText.setText("Loadtest in progress.\n"
-            + "num metrics =" + mNumMetrics
-            + "\nElapsed time = " + elapsedTimeMins + " min(s)");
+                + "num metrics =" + mNumMetrics
+                + "\nElapsed time = " + elapsedTimeMins + " min(s)");
     }
 
     private void onAlarm() {
@@ -402,12 +435,14 @@
         mWakeLock = null;
     }
 
-    /** Schedules the next cycle of pushing atoms into logd. */
+    /**
+     * Schedules the next cycle of pushing atoms into logd.
+     */
     private void scheduleNext() {
         Intent intent = new Intent(this, PusherAlarmReceiver.class);
         intent.putExtra(TYPE, PUSH_ALARM);
         mPushPendingIntent = PendingIntent.getBroadcast(this, 0, intent, 0);
-        long nextTime =  SystemClock.elapsedRealtime() + mPeriodSecs * 1000;
+        long nextTime = SystemClock.elapsedRealtime() + mPeriodSecs * 1000;
         mAlarmMgr.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, nextTime, mPushPendingIntent);
     }
 
@@ -433,7 +468,7 @@
         Intent intent = new Intent(this, StopperAlarmReceiver.class);
         intent.putExtra(TYPE, STOP);
         mStopPendingIntent = PendingIntent.getBroadcast(this, 0, intent, 0);
-        long nextTime =  SystemClock.elapsedRealtime() + mDurationMins * 60 * 1000;
+        long nextTime = SystemClock.elapsedRealtime() + mDurationMins * 60 * 1000;
         mAlarmMgr.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, nextTime, mStopPendingIntent);
 
         // Log atoms.
@@ -441,8 +476,8 @@
 
         // Start tracking performance.
         mPerfData = new PerfData(this, mPlacebo, mReplication, mBucket, mPeriodSecs, mBurst,
-            mIncludeCountMetric, mIncludeDurationMetric, mIncludeEventMetric, mIncludeValueMetric,
-            mIncludeGaugeMetric);
+                mIncludeCountMetric, mIncludeDurationMetric, mIncludeEventMetric, mIncludeValueMetric,
+                mIncludeGaugeMetric);
         mPerfData.startRecording(this);
 
         mReportText.setText("Loadtest in progress.\nnum metrics =" + mNumMetrics);
@@ -476,7 +511,7 @@
         getData();
 
         long elapsedTimeMins = (long) Math.floor(
-            (SystemClock.elapsedRealtime() - mStartedTimeMillis) / 60 / 1000);
+                (SystemClock.elapsedRealtime() - mStartedTimeMillis) / 60 / 1000);
         mReportText.setText("Loadtest ended. Elapsed time = " + elapsedTimeMins + " min(s)");
         clearConfigs();
         updateStarted(false);
@@ -485,7 +520,7 @@
     private synchronized void updateStarted(boolean started) {
         mStarted = started;
         mStartStop.setBackgroundColor(started ?
-            Color.parseColor("#FFFF0000") : Color.parseColor("#FF00FF00"));
+                Color.parseColor("#FFFF0000") : Color.parseColor("#FF00FF00"));
         mStartStop.setText(started ? getString(R.string.stop) : getString(R.string.start));
         updateControlsEnabled();
     }
@@ -538,22 +573,21 @@
     }
 
     private boolean setConfig(ConfigFactory.ConfigMetadata configData) {
-      if (mStatsManager != null) {
-            if (mStatsManager.addConfiguration(ConfigFactory.CONFIG_ID,
-                configData.bytes, getPackageName(), LoadtestActivity.this.getClass().getName())) {
+        if (mStatsManager != null) {
+            if (mStatsManager.addConfiguration(ConfigFactory.CONFIG_ID, configData.bytes)) {
                 mNumMetrics = configData.numMetrics;
                 Log.d(TAG, "Config pushed to statsd");
                 return true;
             } else {
                 Log.d(TAG, "Failed to push config to statsd");
             }
-      }
-      return false;
+        }
+        return false;
     }
 
     private synchronized void setReplication(int replication) {
         if (mStarted) {
-          return;
+            return;
         }
         mReplicationText.setText("" + replication);
     }
@@ -614,13 +648,13 @@
         mBucketSpinner = (Spinner) findViewById(R.id.bucket_spinner);
 
         ArrayAdapter<String> dataAdapter = new ArrayAdapter<String>(
-            this, R.layout.spinner_item, TIME_UNIT_LABELS);
+                this, R.layout.spinner_item, TIME_UNIT_LABELS);
 
         mBucketSpinner.setAdapter(dataAdapter);
         mBucketSpinner.setOnItemSelectedListener(this);
 
         for (String label : TIME_UNIT_MAP.keySet()) {
-          if (defaultValue.equals(TIME_UNIT_MAP.get(label).toString())) {
+            if (defaultValue.equals(TIME_UNIT_MAP.get(label).toString())) {
                 mBucketSpinner.setSelection(dataAdapter.getPosition(label));
             }
         }
diff --git a/config/hiddenapi-light-greylist.txt b/config/hiddenapi-light-greylist.txt
index 58936fc..a7d07e3 100644
--- a/config/hiddenapi-light-greylist.txt
+++ b/config/hiddenapi-light-greylist.txt
@@ -1,63 +1,121 @@
 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;
 Landroid/app/Activity;->getActivityToken()Landroid/os/IBinder;
 Landroid/app/Activity;->mActivityInfo:Landroid/content/pm/ActivityInfo;
+Landroid/app/ActivityManager;->addOnUidImportanceListener(Landroid/app/ActivityManager$OnUidImportanceListener;I)V
 Landroid/app/ActivityManager;->clearApplicationUserData(Ljava/lang/String;Landroid/content/pm/IPackageDataObserver;)Z
 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;
+Landroid/app/ActivityManagerNative;->asInterface(Landroid/os/IBinder;)Landroid/app/IActivityManager;
 Landroid/app/ActivityManagerNative;->getDefault()Landroid/app/IActivityManager;
 Landroid/app/ActivityManager;->PROCESS_STATE_TOP:I
 Landroid/app/ActivityManager$RecentTaskInfo;->firstActiveTime:J
+Landroid/app/ActivityManager;->removeOnUidImportanceListener(Landroid/app/ActivityManager$OnUidImportanceListener;)V
 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/Activity;->setPersistent(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;->processName:Ljava/lang/String;
+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;->RELAUNCH_ACTIVITY: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;->mDensityCompatMode:Z
+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;->mLocalProvidersByName:Landroid/util/ArrayMap;
 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;->performNewIntents(Landroid/os/IBinder;Ljava/util/List;Z)V
 Landroid/app/ActivityThread;->performStopActivity(Landroid/os/IBinder;ZLjava/lang/String;)V
+Landroid/app/ActivityThread$ProviderClientRecord;->mHolder:Landroid/app/ContentProviderHolder;
+Landroid/app/ActivityThread$ProviderClientRecord;->mLocalProvider:Landroid/content/ContentProvider;
+Landroid/app/ActivityThread$ProviderClientRecord;->mProvider:Landroid/content/IContentProvider;
+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/ActivityThread;->startActivityNow(Landroid/app/Activity;Ljava/lang/String;Landroid/content/Intent;Landroid/content/pm/ActivityInfo;Landroid/os/IBinder;Landroid/os/Bundle;Landroid/app/Activity$NonConfigurationInstances;)Landroid/app/Activity;
+Landroid/app/admin/DevicePolicyManager;->getDeviceOwnerComponentOnAnyUser()Landroid/content/ComponentName;
+Landroid/app/admin/DevicePolicyManager;->getDeviceOwner()Ljava/lang/String;
+Landroid/app/admin/DevicePolicyManager;->getProfileOwner()Landroid/content/ComponentName;
 Landroid/app/admin/DevicePolicyManager;->getTrustAgentConfiguration(Landroid/content/ComponentName;Landroid/content/ComponentName;I)Ljava/util/List;
 Landroid/app/admin/DevicePolicyManager;->notifyPendingSystemUpdate(J)V
 Landroid/app/admin/DevicePolicyManager;->notifyPendingSystemUpdate(JZ)V
@@ -65,74 +123,229 @@
 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
+Landroid/app/AlarmManager;->WINDOW_HEURISTIC:J
 Landroid/app/AlertDialog$Builder;->P:Lcom/android/internal/app/AlertController$AlertParams;
 Landroid/app/AlertDialog;->mAlert:Lcom/android/internal/app/AlertController;
 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;->configurationChanged()V
 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
+Landroid/app/backup/BackupManager;->getAvailableRestoreToken(Ljava/lang/String;)J
+Landroid/app/backup/BackupManager;->getCurrentTransport()Ljava/lang/String;
+Landroid/app/backup/BackupManager;->isBackupEnabled()Z
+Landroid/app/backup/BackupManager;->listAllTransports()[Ljava/lang/String;
+Landroid/app/backup/BackupManagerMonitor;-><init>()V
+Landroid/app/backup/BackupManager;->requestBackup([Ljava/lang/String;Landroid/app/backup/BackupObserver;Landroid/app/backup/BackupManagerMonitor;I)I
+Landroid/app/backup/BackupManager;->selectBackupTransport(Landroid/content/ComponentName;Landroid/app/backup/SelectBackupTransportCallback;)V
+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;->info:Landroid/content/pm/ProviderInfo;
+Landroid/app/ContentProviderHolder;-><init>(Landroid/content/pm/ProviderInfo;)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;->getReceiverRestrictedContext()Landroid/content/Context;
+Landroid/app/ContextImpl;->mBasePackageName:Ljava/lang/String;
+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/ContextImpl;->sSharedPrefsCache:Landroid/util/ArrayMap;
 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;->bindService(Landroid/app/IApplicationThread;Landroid/os/IBinder;Landroid/content/Intent;Ljava/lang/String;Landroid/app/IServiceConnection;ILjava/lang/String;I)I
+Landroid/app/IActivityManager;->finishActivity(Landroid/os/IBinder;ILandroid/content/Intent;I)Z
+Landroid/app/IActivityManager;->finishReceiver(Landroid/os/IBinder;ILjava/lang/String;Landroid/os/Bundle;ZI)V
 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;->moveTaskToFront(IILandroid/os/Bundle;)V
+Landroid/app/IActivityManager;->publishContentProviders(Landroid/app/IApplicationThread;Ljava/util/List;)V
 Landroid/app/IActivityManager;->resumeAppSwitches()V
+Landroid/app/IActivityManager;->setRequestedOrientation(Landroid/os/IBinder;I)V
+Landroid/app/IActivityManager;->setTaskResizeable(II)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/IActivityManager;->unbindService(Landroid/app/IServiceConnection;)Z
+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;->getClassLoader()Ljava/lang/ClassLoader;
+Landroid/app/LoadedApk;->getDataDirFile()Ljava/io/File;
+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;->mDataDirFile:Ljava/io/File;
+Landroid/app/LoadedApk;->mDataDir:Ljava/lang/String;
+Landroid/app/LoadedApk;->mDisplayAdjustments:Landroid/view/DisplayAdjustments;
+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$Builder;->setChannel(Ljava/lang/String;)Landroid/app/Notification$Builder;
 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/StatusBarManager;->getService()Lcom/android/internal/statusbar/IStatusBarService;
 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;
 Landroid/app/WallpaperManager;->getIWallpaperManager()Landroid/app/IWallpaperManager;
@@ -143,9 +356,14 @@
 Landroid/appwidget/AppWidgetManager;->bindAppWidgetId(ILandroid/content/ComponentName;Landroid/os/Bundle;)V
 Landroid/appwidget/AppWidgetManager;->bindAppWidgetId(ILandroid/content/ComponentName;)V
 Landroid/bluetooth/BluetoothA2dp;->connect(Landroid/bluetooth/BluetoothDevice;)Z
+Landroid/bluetooth/BluetoothAdapter;->disableBLE()Z
 Landroid/bluetooth/BluetoothAdapter;->disable(Z)Z
+Landroid/bluetooth/BluetoothAdapter;->enableBLE()Z
 Landroid/bluetooth/BluetoothAdapter;->enableNoAutoConnect()Z
 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
@@ -163,42 +381,94 @@
 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/ContentProviderClient;->mContentProvider:Landroid/content/IContentProvider;
+Landroid/content/ContentProviderClient;->mPackageName:Ljava/lang/String;
+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;
 Landroid/content/Context;->createPackageContextAsUser(Ljava/lang/String;ILandroid/os/UserHandle;)Landroid/content/Context;
 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/IContentProvider;->call(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Landroid/os/Bundle;)Landroid/os/Bundle;
 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;->asInterface(Landroid/os/IBinder;)Landroid/content/IContentService;
+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/LauncherActivityInfo;->mActivityInfo:Landroid/content/pm/ActivityInfo;
 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
@@ -209,27 +479,70 @@
 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;
@@ -240,9 +553,16 @@
 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;
@@ -251,15 +571,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
@@ -272,18 +597,49 @@
 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/AbstractCursor;->mRowIdColumnIndex:I
 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;
@@ -293,6 +649,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
@@ -301,27 +662,199 @@
 Landroid/graphics/drawable/StateListDrawable;->getStateSet(I)[I
 Landroid/graphics/drawable/StateListDrawable;->mStateListState:Landroid/graphics/drawable/StateListDrawable$StateListState;
 Landroid/graphics/drawable/StateListDrawable;->updateStateFromTypedArray(Landroid/content/res/TypedArray;)V
+Landroid/graphics/FontFamily;->abortCreation()V
+Landroid/graphics/FontFamily;->addFontFromAssetManager(Landroid/content/res/AssetManager;Ljava/lang/String;IZIII[Landroid/graphics/fonts/FontVariationAxis;)Z
+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;
+Landroid/hardware/location/ContextHubInfo;->getId()I
+Landroid/hardware/location/ContextHubInfo;->getMaxPacketLengthBytes()I
+Landroid/hardware/location/ContextHubManager$Callback;-><init>()V
+Landroid/hardware/location/ContextHubManager;->findNanoAppOnHub(ILandroid/hardware/location/NanoAppFilter;)[I
+Landroid/hardware/location/ContextHubManager;->getContextHubHandles()[I
+Landroid/hardware/location/ContextHubManager;->getContextHubInfo(I)Landroid/hardware/location/ContextHubInfo;
+Landroid/hardware/location/ContextHubManager;->getNanoAppInstanceInfo(I)Landroid/hardware/location/NanoAppInstanceInfo;
+Landroid/hardware/location/ContextHubManager;->loadNanoApp(ILandroid/hardware/location/NanoApp;)I
+Landroid/hardware/location/ContextHubManager;->registerCallback(Landroid/hardware/location/ContextHubManager$Callback;)I
+Landroid/hardware/location/ContextHubManager;->sendMessage(IILandroid/hardware/location/ContextHubMessage;)I
+Landroid/hardware/location/ContextHubManager;->unloadNanoApp(I)I
+Landroid/hardware/location/ContextHubMessage;->getData()[B
+Landroid/hardware/location/ContextHubMessage;->getMsgType()I
+Landroid/hardware/location/ContextHubMessage;->getVersion()I
+Landroid/hardware/location/ContextHubMessage;-><init>(II[B)V
+Landroid/hardware/location/GeofenceHardware;->addGeofence(IILandroid/hardware/location/GeofenceHardwareRequest;Landroid/hardware/location/GeofenceHardwareCallback;)Z
+Landroid/hardware/location/GeofenceHardwareCallback;-><init>()V
+Landroid/hardware/location/GeofenceHardwareCallback;->onGeofenceAdd(II)V
+Landroid/hardware/location/GeofenceHardwareCallback;->onGeofenceRemove(II)V
+Landroid/hardware/location/GeofenceHardwareCallback;->onGeofenceTransition(IILandroid/location/Location;JI)V
+Landroid/hardware/location/GeofenceHardware;->getMonitoringTypes()[I
+Landroid/hardware/location/GeofenceHardware;->getStatusOfMonitoringType(I)I
+Landroid/hardware/location/GeofenceHardwareMonitorCallback;-><init>()V
+Landroid/hardware/location/GeofenceHardwareMonitorCallback;->onMonitoringSystemChange(IZLandroid/location/Location;)V
+Landroid/hardware/location/GeofenceHardware;->registerForMonitorStateChangeCallback(ILandroid/hardware/location/GeofenceHardwareMonitorCallback;)Z
+Landroid/hardware/location/GeofenceHardware;->removeGeofence(II)Z
+Landroid/hardware/location/GeofenceHardwareRequest;->createCircularGeofence(DDD)Landroid/hardware/location/GeofenceHardwareRequest;
+Landroid/hardware/location/GeofenceHardwareRequest;->setLastTransition(I)V
+Landroid/hardware/location/GeofenceHardwareRequest;->setMonitorTransitions(I)V
+Landroid/hardware/location/GeofenceHardwareRequest;->setNotificationResponsiveness(I)V
+Landroid/hardware/location/GeofenceHardwareRequest;->setUnknownTimer(I)V
+Landroid/hardware/location/NanoAppFilter;-><init>(JIIJ)V
+Landroid/hardware/location/NanoApp;-><init>(J[B)V
+Landroid/hardware/location/NanoAppInstanceInfo;->getAppId()J
+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
 Landroid/media/AudioManager;->requestAudioFocus(Landroid/media/AudioManager$OnAudioFocusChangeListener;Landroid/media/AudioAttributes;II)I
 Landroid/media/AudioManager;->requestAudioFocus(Landroid/media/AudioManager$OnAudioFocusChangeListener;Landroid/media/AudioAttributes;IILandroid/media/audiopolicy/AudioPolicy;)I
@@ -329,18 +862,84 @@
 Landroid/media/AudioManager;->STREAM_BLUETOOTH_SCO:I
 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;
+Landroid/media/audiopolicy/AudioPolicy$Builder;-><init>(Landroid/content/Context;)V
+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
@@ -352,12 +951,60 @@
 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;
+Landroid/metrics/LogMaker;->getCounterValue()I
+Landroid/metrics/LogMaker;->getTimestamp()J
+Landroid/metrics/LogMaker;->isLongCounterBucket()Z
+Landroid/metrics/LogMaker;->serialize()[Ljava/lang/Object;
+Landroid/metrics/MetricsReader;->checkpoint()V
+Landroid/metrics/MetricsReader;->hasNext()Z
+Landroid/metrics/MetricsReader;-><init>()V
+Landroid/metrics/MetricsReader;->next()Landroid/metrics/LogMaker;
+Landroid/metrics/MetricsReader;->read(J)V
+Landroid/metrics/MetricsReader;->reset()V
 Landroid/net/ConnectivityManager;->ACTION_TETHER_STATE_CHANGED:Ljava/lang/String;
 Landroid/net/ConnectivityManager;->EXTRA_ACTIVE_TETHER:Ljava/lang/String;
 Landroid/net/ConnectivityManager;->getActiveLinkProperties()Landroid/net/LinkProperties;
@@ -370,11 +1017,35 @@
 Landroid/net/ConnectivityManager;->isNetworkTypeMobile(I)Z
 Landroid/net/ConnectivityManager;->isTetheringSupported()Z
 Landroid/net/ConnectivityManager;->mService:Landroid/net/IConnectivityManager;
+Landroid/net/ConnectivityManager$OnStartTetheringCallback;-><init>()V
 Landroid/net/ConnectivityManager;->requestRouteToHostAddress(ILjava/net/InetAddress;)Z
 Landroid/net/ConnectivityManager;->requestRouteToHost(II)Z
+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
+Landroid/net/NetworkScoreManager;->clearScores()Z
+Landroid/net/NetworkScoreManager;->getActiveScorerPackage()Ljava/lang/String;
+Landroid/net/NetworkScoreManager;->updateScores([Landroid/net/ScoredNetwork;)Z
 Landroid/net/NetworkStats;->capacity:I
 Landroid/net/NetworkStats;->defaultNetwork:[I
 Landroid/net/NetworkStats;->iface:[Ljava/lang/String;
@@ -389,37 +1060,117 @@
 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
+Landroid/net/ScoredNetwork;-><init>(Landroid/net/NetworkKey;Landroid/net/RssiCurve;)V
+Landroid/net/ScoredNetwork;-><init>(Landroid/net/NetworkKey;Landroid/net/RssiCurve;ZLandroid/os/Bundle;)V
+Landroid/net/ScoredNetwork;-><init>(Landroid/net/NetworkKey;Landroid/net/RssiCurve;Z)V
+Landroid/net/SSLCertificateSocketFactory;->castToOpenSSLSocket(Ljava/net/Socket;)Lcom/android/org/conscrypt/OpenSSLSocketImpl;
+Landroid/net/SSLCertificateSocketFactory;->getAlpnSelectedProtocol(Ljava/net/Socket;)[B
+Landroid/net/SSLCertificateSocketFactory;->getDelegate()Ljavax/net/ssl/SSLSocketFactory;
 Landroid/net/SSLCertificateSocketFactory;->getHttpSocketFactory(ILandroid/net/SSLSessionCache;)Lorg/apache/http/conn/ssl/SSLSocketFactory;
+Landroid/net/SSLCertificateSocketFactory;-><init>(ILandroid/net/SSLSessionCache;Z)V
+Landroid/net/SSLCertificateSocketFactory;->INSECURE_TRUST_MANAGER:[Ljavax/net/ssl/TrustManager;
+Landroid/net/SSLCertificateSocketFactory;->isSslCheckRelaxed()Z
+Landroid/net/SSLCertificateSocketFactory;->makeSocketFactory([Ljavax/net/ssl/KeyManager;[Ljavax/net/ssl/TrustManager;)Ljavax/net/ssl/SSLSocketFactory;
+Landroid/net/SSLCertificateSocketFactory;->mAlpnProtocols:[B
+Landroid/net/SSLCertificateSocketFactory;->mChannelIdPrivateKey:Ljava/security/PrivateKey;
+Landroid/net/SSLCertificateSocketFactory;->mHandshakeTimeoutMillis:I
+Landroid/net/SSLCertificateSocketFactory;->mInsecureFactory:Ljavax/net/ssl/SSLSocketFactory;
+Landroid/net/SSLCertificateSocketFactory;->mKeyManagers:[Ljavax/net/ssl/KeyManager;
+Landroid/net/SSLCertificateSocketFactory;->mNpnProtocols:[B
+Landroid/net/SSLCertificateSocketFactory;->mSecureFactory:Ljavax/net/ssl/SSLSocketFactory;
+Landroid/net/SSLCertificateSocketFactory;->mSecure:Z
+Landroid/net/SSLCertificateSocketFactory;->mSessionCache:Lcom/android/org/conscrypt/SSLClientSessionCache;
+Landroid/net/SSLCertificateSocketFactory;->mTrustManagers:[Ljavax/net/ssl/TrustManager;
+Landroid/net/SSLCertificateSocketFactory;->setAlpnProtocols([[B)V
+Landroid/net/SSLCertificateSocketFactory;->setChannelIdPrivateKey(Ljava/security/PrivateKey;)V
+Landroid/net/SSLCertificateSocketFactory;->setSoWriteTimeout(Ljava/net/Socket;I)V
+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;
 Landroid/net/wifi/p2p/WifiP2pManager;->deletePersistentGroup(Landroid/net/wifi/p2p/WifiP2pManager$Channel;ILandroid/net/wifi/p2p/WifiP2pManager$ActionListener;)V
 Landroid/net/wifi/p2p/WifiP2pManager;->requestPersistentGroupInfo(Landroid/net/wifi/p2p/WifiP2pManager$Channel;Landroid/net/wifi/p2p/WifiP2pManager$PersistentGroupInfoListener;)V
 Landroid/net/wifi/p2p/WifiP2pManager;->setDeviceName(Landroid/net/wifi/p2p/WifiP2pManager$Channel;Ljava/lang/String;Landroid/net/wifi/p2p/WifiP2pManager$ActionListener;)V
+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/WifiInfo;->mMacAddress:Ljava/lang/String;
+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;
 Landroid/net/wifi/WifiManager;->forget(ILandroid/net/wifi/WifiManager$ActionListener;)V
+Landroid/net/wifi/WifiManager;->getPrivilegedConfiguredNetworks()Ljava/util/List;
 Landroid/net/wifi/WifiManager;->getWifiApConfiguration()Landroid/net/wifi/WifiConfiguration;
 Landroid/net/wifi/WifiManager;->getWifiApState()I
 Landroid/net/wifi/WifiManager;->isDualBandSupported()Z
 Landroid/net/wifi/WifiManager;->isWifiApEnabled()Z
+Landroid/net/wifi/WifiManager;->isWifiScannerSupported()Z
 Landroid/net/wifi/WifiManager;->mService:Landroid/net/wifi/IWifiManager;
 Landroid/net/wifi/WifiManager;->save(Landroid/net/wifi/WifiConfiguration;Landroid/net/wifi/WifiManager$ActionListener;)V
 Landroid/net/wifi/WifiManager;->setWifiApConfiguration(Landroid/net/wifi/WifiConfiguration;)Z
+Landroid/net/wifi/WifiManager;->startScan(Landroid/os/WorkSource;)Z
 Landroid/net/wifi/WifiManager;->WIFI_AP_STATE_CHANGED_ACTION:Ljava/lang/String;
 Landroid/net/wifi/WifiManager;->WIFI_AP_STATE_DISABLED:I
 Landroid/net/wifi/WifiManager;->WIFI_AP_STATE_DISABLING:I
 Landroid/net/wifi/WifiManager;->WIFI_AP_STATE_ENABLED:I
 Landroid/net/wifi/WifiManager;->WIFI_AP_STATE_ENABLING:I
 Landroid/net/wifi/WifiManager;->WIFI_AP_STATE_FAILED:I
+Landroid/net/wifi/WifiScanner;->getScanResults()Z
+Landroid/net/wifi/WifiScanner$ScanData;->getResults()[Landroid/net/wifi/ScanResult;
+Landroid/net/wifi/WifiScanner$ScanSettings;-><init>()V
+Landroid/net/wifi/WifiScanner;->startBackgroundScan(Landroid/net/wifi/WifiScanner$ScanSettings;Landroid/net/wifi/WifiScanner$ScanListener;)V
+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
 Landroid/nfc/NfcAdapter;->getDefaultAdapter()Landroid/nfc/NfcAdapter;
+Landroid/nfc/NfcAdapter;->removeNfcUnlockHandler(Landroid/nfc/NfcAdapter$NfcUnlockHandler;)Z
 Landroid/nfc/NfcAdapter;->setNdefPushMessageCallback(Landroid/nfc/NfcAdapter$CreateNdefMessageCallback;Landroid/app/Activity;I)V
+Landroid/nfc/NfcAdapter;->setNdefPushMessage(Landroid/nfc/NdefMessage;Landroid/app/Activity;I)V
 Landroid/opengl/GLSurfaceView$EglHelper;->mEglContext:Ljavax/microedition/khronos/egl/EGLContext;
 Landroid/opengl/GLSurfaceView$GLThread;->mEglHelper:Landroid/opengl/GLSurfaceView$EglHelper;
 Landroid/opengl/GLSurfaceView;->mGLThread:Landroid/opengl/GLSurfaceView$GLThread;
@@ -429,6 +1180,8 @@
 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
 Landroid/os/BatteryStats$Uid;->getFullWifiLockTime(JI)J
@@ -442,18 +1195,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
@@ -468,21 +1248,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
@@ -490,6 +1289,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
@@ -503,18 +1303,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;
@@ -525,6 +1337,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
@@ -532,6 +1347,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
@@ -546,32 +1363,52 @@
 Landroid/os/UpdateEngine;->applyPayload(Ljava/lang/String;JJ[Ljava/lang/String;)V
 Landroid/os/UpdateEngine;->bind(Landroid/os/UpdateEngineCallback;Landroid/os/Handler;)Z
 Landroid/os/UpdateEngine;->bind(Landroid/os/UpdateEngineCallback;)Z
+Landroid/os/UpdateEngineCallback;-><init>()V
+Landroid/os/UpdateEngineCallback;->onPayloadApplicationComplete(I)V
+Landroid/os/UpdateEngineCallback;->onStatusUpdate(IF)V
 Landroid/os/UpdateEngine;->cancel()V
+Landroid/os/UpdateEngine;-><init>()V
 Landroid/os/UpdateEngine;->resetStatus()V
 Landroid/os/UpdateLock;->acquire()V
 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;
 Landroid/os/UserManager;->getMaxSupportedUsers()I
 Landroid/os/UserManager;->getProfiles(I)Ljava/util/List;
 Landroid/os/UserManager;->getUserHandle()I
 Landroid/os/UserManager;->getUserHandle(I)I
 Landroid/os/UserManager;->getUserInfo(I)Landroid/content/pm/UserInfo;
+Landroid/os/UserManager;->getUserRestrictionSource(Ljava/lang/String;Landroid/os/UserHandle;)I
 Landroid/os/UserManager;->getUserSerialNumber(I)I
 Landroid/os/UserManager;->getUsers()Ljava/util/List;
 Landroid/os/UserManager;->hasBaseUserRestriction(Ljava/lang/String;Landroid/os/UserHandle;)Z
 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;
@@ -591,6 +1428,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;
@@ -607,20 +1445,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;
@@ -629,6 +1481,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
@@ -636,50 +1489,127 @@
 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
+Landroid/service/resolver/ResolverRankerService;-><init>()V
+Landroid/service/resolver/ResolverTarget;->getChooserScore()F
+Landroid/service/resolver/ResolverTarget;->getLaunchScore()F
+Landroid/service/resolver/ResolverTarget;->getRecencyScore()F
+Landroid/service/resolver/ResolverTarget;->getSelectProbability()F
+Landroid/service/resolver/ResolverTarget;->getTimeSpentScore()F
+Landroid/service/resolver/ResolverTarget;->setSelectProbability(F)V
+Landroid/service/trust/TrustAgentService;-><init>()V
+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
+Landroid/telecom/Call;->addListener(Landroid/telecom/Call$Listener;)V
+Landroid/telecom/Call$Listener;-><init>()V
+Landroid/telecom/Call;->removeListener(Landroid/telecom/Call$Listener;)V
+Landroid/telecom/Phone;->addListener(Landroid/telecom/Phone$Listener;)V
+Landroid/telecom/Phone;->getAudioState()Landroid/telecom/AudioState;
+Landroid/telecom/Phone;->getCallAudioState()Landroid/telecom/CallAudioState;
+Landroid/telecom/Phone;->getCalls()Ljava/util/List;
+Landroid/telecom/Phone$Listener;-><init>()V
+Landroid/telecom/Phone;->removeListener(Landroid/telecom/Phone$Listener;)V
+Landroid/telecom/Phone;->setAudioRoute(I)V
+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;->mGsmBitErrorRate:I
+Landroid/telephony/SignalStrength;->mGsmSignalStrength:I
+Landroid/telephony/SignalStrength;->mLteCqi:I
+Landroid/telephony/SignalStrength;->mLteRsrp:I
+Landroid/telephony/SignalStrength;->mLteRsrq:I
+Landroid/telephony/SignalStrength;->mLteRssnr:I
+Landroid/telephony/SignalStrength;->mLteSignalStrength: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
 Landroid/telephony/SubscriptionManager;->getSubId(I)[I
 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;->isVolteAvailable()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;
@@ -691,61 +1621,192 @@
 Landroid/text/SpannableStringBuilder;->mSpanFlags:[I
 Landroid/text/SpannableStringBuilder;->mSpans:[Ljava/lang/Object;
 Landroid/text/SpannableStringBuilder;->mSpanStarts:[I
+Landroid/text/SpannableStringInternal;->charAt(I)C
+Landroid/text/SpannableStringInternal;->checkRange(Ljava/lang/String;II)V
+Landroid/text/SpannableStringInternal;->COLUMNS:I
+Landroid/text/SpannableStringInternal;->copySpans(Landroid/text/SpannableStringInternal;II)V
+Landroid/text/SpannableStringInternal;->copySpans(Landroid/text/Spanned;II)V
+Landroid/text/SpannableStringInternal;->EMPTY:[Ljava/lang/Object;
+Landroid/text/SpannableStringInternal;->END:I
+Landroid/text/SpannableStringInternal;->FLAGS:I
+Landroid/text/SpannableStringInternal;->getChars(II[CI)V
+Landroid/text/SpannableStringInternal;->getSpanEnd(Ljava/lang/Object;)I
+Landroid/text/SpannableStringInternal;->getSpanFlags(Ljava/lang/Object;)I
+Landroid/text/SpannableStringInternal;->getSpans(IILjava/lang/Class;)[Ljava/lang/Object;
+Landroid/text/SpannableStringInternal;->getSpanStart(Ljava/lang/Object;)I
+Landroid/text/SpannableStringInternal;-><init>(Ljava/lang/CharSequence;II)V
+Landroid/text/SpannableStringInternal;->isIndexFollowsNextLine(I)Z
+Landroid/text/SpannableStringInternal;->isOutOfCopyRange(IIII)Z
+Landroid/text/SpannableStringInternal;->length()I
+Landroid/text/SpannableStringInternal;->mSpanCount:I
+Landroid/text/SpannableStringInternal;->mSpanData:[I
+Landroid/text/SpannableStringInternal;->mSpans:[Ljava/lang/Object;
+Landroid/text/SpannableStringInternal;->mText:Ljava/lang/String;
+Landroid/text/SpannableStringInternal;->nextSpanTransition(IILjava/lang/Class;)I
+Landroid/text/SpannableStringInternal;->region(II)Ljava/lang/String;
+Landroid/text/SpannableStringInternal;->removeSpan(Ljava/lang/Object;)V
+Landroid/text/SpannableStringInternal;->sendSpanAdded(Ljava/lang/Object;II)V
+Landroid/text/SpannableStringInternal;->sendSpanChanged(Ljava/lang/Object;IIII)V
+Landroid/text/SpannableStringInternal;->sendSpanRemoved(Ljava/lang/Object;II)V
+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;->getThemeResId()I
 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/InputMethodInfo;->mSubtypes:Landroid/view/inputmethod/InputMethodSubtypeArray;
 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/inputmethod/InputMethodSubtypeArray;-><init>(Ljava/util/List;)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;
@@ -756,10 +1817,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
@@ -772,28 +1841,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
@@ -809,8 +1887,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
@@ -818,9 +1898,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
@@ -828,43 +1914,118 @@
 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;->initialize()V
 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;
@@ -885,6 +2046,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
@@ -893,6 +2057,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
@@ -907,23 +2072,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;
@@ -933,6 +2116,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;
@@ -948,8 +2133,13 @@
 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;->mTouchInterceptor:Landroid/view/View$OnTouchListener;
 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
@@ -966,9 +2156,20 @@
 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$BitmapReflectionAction;->bitmap:Landroid/graphics/Bitmap;
+Landroid/widget/RemoteViews$BitmapReflectionAction;->methodName:Ljava/lang/String;
+Landroid/widget/RemoteViews;->estimateMemoryUsage()I
 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;->mPortrait:Landroid/widget/RemoteViews;
 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
@@ -984,6 +2185,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
@@ -995,17 +2197,44 @@
 Landroid/widget/TextView;->mMaximum:I
 Landroid/widget/TextView;->mMaxMode:I
 Landroid/widget/TextView;->mSingleLine:Z
+Landroid/widget/TextView;->mTextPaint:Landroid/text/TextPaint;
+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;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/app/IAppOpsService;
+Lcom/android/internal/app/IAppOpsService$Stub$Proxy;->checkOperation(IILjava/lang/String;)I
+Lcom/android/internal/app/IAppOpsService$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 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
+Lcom/android/internal/os/BatterySipper;-><init>(Lcom/android/internal/os/BatterySipper$DrainType;Landroid/os/BatteryStats$Uid;D)V
+Lcom/android/internal/os/BatterySipper;->mPackages:[Ljava/lang/String;
+Lcom/android/internal/os/BatterySipper;->packageWithHighestDrain:Ljava/lang/String;
+Lcom/android/internal/os/BatterySipper;->totalPowerMah:D
+Lcom/android/internal/os/BatterySipper;->uidObj:Landroid/os/BatteryStats$Uid;
+Lcom/android/internal/os/BatteryStatsHelper;->getMaxPower()D
+Lcom/android/internal/os/BatteryStatsHelper;->getStats()Landroid/os/BatteryStats;
+Lcom/android/internal/os/BatteryStatsHelper;->getTotalPower()D
+Lcom/android/internal/os/BatteryStatsHelper;-><init>(Landroid/content/Context;ZZ)V
+Lcom/android/internal/os/BatteryStatsHelper;->load()V
+Lcom/android/internal/os/BatteryStatsHelper;->mBatteryInfo:Lcom/android/internal/app/IBatteryStats;
+Lcom/android/internal/os/BatteryStatsHelper;->mPowerProfile:Lcom/android/internal/os/PowerProfile;
+Lcom/android/internal/os/BatteryStatsHelper;->mUsageList:Ljava/util/List;
+Lcom/android/internal/os/BatteryStatsHelper;->refreshStats(II)V
 Lcom/android/internal/os/BatteryStatsImpl;->computeBatteryRealtime(JI)J
 Lcom/android/internal/os/BatteryStatsImpl;->computeBatteryUptime(JI)J
 Lcom/android/internal/os/BatteryStatsImpl;->CREATOR:Landroid/os/Parcelable$Creator;
+Lcom/android/internal/os/BatteryStatsImpl;->getDischargeAmount(I)I
 Lcom/android/internal/os/BatteryStatsImpl;->getGlobalWifiRunningTime(JI)J
 Lcom/android/internal/os/BatteryStatsImpl;->getScreenOnTime(JI)J
 Lcom/android/internal/os/BatteryStatsImpl;->getUidStats()Landroid/util/SparseArray;
@@ -1029,15 +2258,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
@@ -1050,13 +2296,53 @@
 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;->AccountAuthenticator_accountPreferences:I
+Lcom/android/internal/R$styleable;->AccountAuthenticator_accountType:I
+Lcom/android/internal/R$styleable;->AccountAuthenticator_customTokens:I
+Lcom/android/internal/R$styleable;->AccountAuthenticator:[I
+Lcom/android/internal/R$styleable;->AccountAuthenticator_icon:I
+Lcom/android/internal/R$styleable;->AccountAuthenticator_label:I
+Lcom/android/internal/R$styleable;->AccountAuthenticator_smallIcon: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;->SyncAdapter_accountType:I
+Lcom/android/internal/R$styleable;->SyncAdapter_allowParallelSyncs:I
+Lcom/android/internal/R$styleable;->SyncAdapter_contentAuthority:I
+Lcom/android/internal/R$styleable;->SyncAdapter:[I
+Lcom/android/internal/R$styleable;->SyncAdapter_isAlwaysSyncable:I
+Lcom/android/internal/R$styleable;->SyncAdapter_settingsActivity:I
+Lcom/android/internal/R$styleable;->SyncAdapter_supportsUploading:I
+Lcom/android/internal/R$styleable;->SyncAdapter_userVisible:I
 Lcom/android/internal/R$styleable;->TabWidget:[I
 Lcom/android/internal/R$styleable;->TextView_drawableBottom:I
 Lcom/android/internal/R$styleable;->TextView_drawableLeft:I
@@ -1064,48 +2350,91 @@
 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:[I
 Lcom/android/internal/R$styleable;->Window_windowActionBarFullscreenDecorLayout:I
+Lcom/android/internal/R$styleable;->Window_windowIsFloating:I
+Lcom/android/internal/R$styleable;->Window_windowIsTranslucent:I
+Lcom/android/internal/R$styleable;->Window_windowShowWallpaper: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;
+Ldalvik/system/BlockGuard$Policy;->onNetwork()V
+Ldalvik/system/CloseGuard;->close()V
 Ldalvik/system/CloseGuard;->get()Ldalvik/system/CloseGuard;
 Ldalvik/system/CloseGuard;->open(Ljava/lang/String;)V
 Ldalvik/system/CloseGuard;->warnIfOpen()V
+Ldalvik/system/DexFile;->getClassNameList(Ljava/lang/Object;)[Ljava/lang/String;
+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;->makeInMemoryDexElements([Ljava/nio/ByteBuffer;Ljava/util/List;)[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$NativeLibraryElement;->path:Ljava/io/File;
 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;
@@ -1113,52 +2442,336 @@
 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;->setTargetSdkVersion(I)V
 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;->keyType:Ljava/lang/Class;
+Ljava/util/EnumMap;->readObject(Ljava/io/ObjectInputStream;)V
+Ljava/util/EnumMap;->writeObject(Ljava/io/ObjectOutputStream;)V
+Ljava/util/EnumSet;->elementType:Ljava/lang/Class;
+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.bp b/core/java/Android.bp
index f7c5c57..fb27f74 100644
--- a/core/java/Android.bp
+++ b/core/java/Android.bp
@@ -7,33 +7,3 @@
     name: "IDropBoxManagerService.aidl",
     srcs: ["com/android/internal/os/IDropBoxManagerService.aidl"],
 }
-
-// only used by key_store_service
-cc_library_shared {
-    name: "libkeystore_aidl",
-    srcs: ["android/security/IKeystoreService.aidl",
-           "android/security/IConfirmationPromptCallback.aidl"],
-    aidl: {
-        export_aidl_headers: true,
-        include_dirs: [
-            "frameworks/base/core/java/",
-            "system/security/keystore/",
-        ],
-    },
-    shared_libs: [
-        "libbinder",
-        "libcutils",
-        "libhardware",
-        "libhidlbase",
-        "libhidltransport",
-        "libhwbinder",
-        "liblog",
-        "libkeystore_parcelables",
-        "libselinux",
-        "libutils",
-    ],
-    export_shared_lib_headers: [
-        "libbinder",
-        "libkeystore_parcelables",
-    ],
-}
diff --git a/core/java/android/accounts/OWNERS b/core/java/android/accounts/OWNERS
new file mode 100644
index 0000000..ea5fd36
--- /dev/null
+++ b/core/java/android/accounts/OWNERS
@@ -0,0 +1,10 @@
+carlosvaldivia@google.com
+dementyev@google.com
+sandrakwan@google.com
+hackbod@google.com
+svetoslavganov@google.com
+moltmann@google.com
+fkupolov@google.com
+yamasani@google.com
+omakoto@google.com
+
diff --git a/core/java/android/annotation/OWNERS b/core/java/android/annotation/OWNERS
new file mode 100644
index 0000000..d6bb71b
--- /dev/null
+++ b/core/java/android/annotation/OWNERS
@@ -0,0 +1 @@
+tnorbye@google.com
diff --git a/core/java/android/annotation/RequiresFeature.java b/core/java/android/annotation/RequiresFeature.java
new file mode 100644
index 0000000..fc93f03
--- /dev/null
+++ b/core/java/android/annotation/RequiresFeature.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.annotation;
+
+import static java.lang.annotation.ElementType.CONSTRUCTOR;
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
+import android.content.pm.PackageManager;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Denotes that the annotated element requires one or more device features. This
+ * is used to auto-generate documentation.
+ *
+ * @see PackageManager#hasSystemFeature(String)
+ * @hide
+ */
+@Retention(SOURCE)
+@Target({TYPE,FIELD,METHOD,CONSTRUCTOR})
+public @interface RequiresFeature {
+    /**
+     * The name of the device feature that is required.
+     *
+     * @see PackageManager#hasSystemFeature(String)
+     */
+    String value();
+}
diff --git a/core/java/android/annotation/SystemService.java b/core/java/android/annotation/SystemService.java
index ba5002a..0c5d15e 100644
--- a/core/java/android/annotation/SystemService.java
+++ b/core/java/android/annotation/SystemService.java
@@ -26,12 +26,19 @@
 
 /**
  * Description of a system service available through
- * {@link Context#getSystemService(Class)}.
+ * {@link Context#getSystemService(Class)}. This is used to auto-generate
+ * documentation explaining how to obtain a reference to the service.
  *
  * @hide
  */
 @Retention(SOURCE)
 @Target(TYPE)
 public @interface SystemService {
+    /**
+     * The string name of the system service that can be passed to
+     * {@link Context#getSystemService(String)}.
+     *
+     * @see Context#getSystemServiceName(Class)
+     */
     String value();
 }
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 0bc510a..83fe4dd 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -17,6 +17,7 @@
 package android.app;
 
 import static android.Manifest.permission.CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS;
+
 import static java.lang.Character.MIN_VALUE;
 
 import android.annotation.CallSuper;
@@ -135,6 +136,7 @@
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
 
@@ -1733,7 +1735,7 @@
      *
      * <p>This callback and {@link #onUserInteraction} are intended to help
      * activities manage status bar notifications intelligently; specifically,
-     * for helping activities determine the proper time to cancel a notfication.
+     * for helping activities determine the proper time to cancel a notification.
      *
      * @see #onUserInteraction()
      */
@@ -1741,32 +1743,16 @@
     }
 
     /**
-     * Generate a new thumbnail for this activity.  This method is called before
-     * pausing the activity, and should draw into <var>outBitmap</var> the
-     * imagery for the desired thumbnail in the dimensions of that bitmap.  It
-     * can use the given <var>canvas</var>, which is configured to draw into the
-     * bitmap, for rendering if desired.
-     *
-     * <p>The default implementation returns fails and does not draw a thumbnail;
-     * this will result in the platform creating its own thumbnail if needed.
-     *
-     * @param outBitmap The bitmap to contain the thumbnail.
-     * @param canvas Can be used to render into the bitmap.
-     *
-     * @return Return true if you have drawn into the bitmap; otherwise after
-     *         you return it will be filled with a default thumbnail.
-     *
-     * @see #onCreateDescription
-     * @see #onSaveInstanceState
-     * @see #onPause
+     * @deprecated Method doesn't do anything and will be removed in the future.
      */
+    @Deprecated
     public boolean onCreateThumbnail(Bitmap outBitmap, Canvas canvas) {
         return false;
     }
 
     /**
      * Generate a new description for this activity.  This method is called
-     * before pausing the activity and can, if desired, return some textual
+     * before stopping the activity and can, if desired, return some textual
      * description of its current state to be displayed to the user.
      *
      * <p>The default implementation returns null, which will cause you to
@@ -1777,9 +1763,8 @@
      * @return A description of what the user is doing.  It should be short and
      *         sweet (only a few words).
      *
-     * @see #onCreateThumbnail
      * @see #onSaveInstanceState
-     * @see #onPause
+     * @see #onStop
      */
     @Nullable
     public CharSequence onCreateDescription() {
@@ -1915,7 +1900,7 @@
 
         if (isFinishing()) {
             if (mAutoFillResetNeeded) {
-                getAutofillManager().onActivityFinished();
+                getAutofillManager().onActivityFinishing();
             } else if (mIntent != null
                     && mIntent.hasExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN)) {
                 // Activity was launched when user tapped a link in the Autofill Save UI - since
@@ -6358,6 +6343,8 @@
 
         final AutofillManager afm = getAutofillManager();
         if (afm != null) {
+            writer.print(prefix); writer.print("Autofill Compat Mode: ");
+            writer.println(isAutofillCompatibilityEnabled());
             afm.dump(prefix, writer);
         } else {
             writer.print(prefix); writer.println("No AutofillManager");
@@ -7179,8 +7166,8 @@
 
                 String appName = getApplicationInfo().loadLabel(getPackageManager())
                         .toString();
-                String warning = "Detected problems with API compatiblity\n"
-                                 + "(please consult log for detail)";
+                String warning = "Detected problems with API compatibility\n"
+                                 + "(visit g.co/dev/appcompat for more info)";
                 if (isAppDebuggable) {
                     new AlertDialog.Builder(this)
                         .setTitle(appName)
@@ -7706,6 +7693,9 @@
                 }
             }
         }
+        if (android.view.autofill.Helper.sVerbose) {
+            Log.v(TAG, "autofillClientGetViewVisibility(): " + Arrays.toString(visible));
+        }
         return visible;
     }
 
@@ -7768,7 +7758,6 @@
      * @param disable {@code true} to disable preview screenshots; {@code false} otherwise.
      * @hide
      */
-    @SystemApi
     public void setDisablePreviewScreenshots(boolean disable) {
         try {
             ActivityManager.getService().setDisablePreviewScreenshots(mToken, disable);
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index ae47a68..03faeee 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -44,6 +44,7 @@
 import android.graphics.Matrix;
 import android.graphics.Point;
 import android.graphics.Rect;
+import android.net.Uri;
 import android.os.BatteryStats;
 import android.os.Binder;
 import android.os.Build;
@@ -2750,6 +2751,30 @@
     }
 
     /**
+     * Updates (grants or revokes) a persitable URI permission.
+     *
+     * @param uri URI to be granted or revoked.
+     * @param prefix if {@code false}, permission apply to this specific URI; if {@code true}, it
+     * applies to all URIs that are prefixed by this URI.
+     * @param packageName target package.
+     * @param grant if {@code true} a new permission will be granted, otherwise an existing
+     * permission will be revoked.
+     *
+     * @return whether or not the requested succeeded.
+     *
+     * @hide
+     */
+    public boolean updatePersistableUriPermission(Uri uri, boolean prefix, String packageName,
+            boolean grant) {
+        try {
+            return getService().updatePersistableUriPermission(uri, prefix, packageName, grant,
+                    UserHandle.myUserId());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Information you can retrieve about any processes that are in an error condition.
      */
     public static class ProcessErrorStateInfo implements Parcelable {
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index 5ee7ede..0c98267 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,
@@ -348,4 +351,14 @@
      * Returns is the caller has the same uid as the Recents component
      */
     public abstract boolean isCallerRecents(int callingUid);
+
+    /**
+     * Whether an UID is active or idle.
+     */
+    public abstract boolean isUidActive(int uid);
+
+    /**
+     * Returns a list that contains the memory stats for currently running processes.
+     */
+    public abstract List<ProcessMemoryState> getMemoryStateForProcesses();
 }
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java
index fee5827..d5430f0 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -1106,6 +1106,11 @@
     }
 
     /** @hide */
+    public void setRemoteAnimationAdapter(RemoteAnimationAdapter remoteAnimationAdapter) {
+        mRemoteAnimationAdapter = remoteAnimationAdapter;
+    }
+
+    /** @hide */
     public static ActivityOptions fromBundle(Bundle bOptions) {
         return bOptions != null ? new ActivityOptions(bOptions) : null;
     }
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 45c57ca..a96f484 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -113,6 +113,7 @@
 import android.util.EventLog;
 import android.util.Log;
 import android.util.LogPrinter;
+import android.util.MergedConfiguration;
 import android.util.Pair;
 import android.util.PrintWriterPrinter;
 import android.util.Slog;
@@ -166,9 +167,9 @@
 import java.lang.reflect.Method;
 import java.net.InetAddress;
 import java.text.DateFormat;
-import java.util.ArrayDeque;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
@@ -204,7 +205,7 @@
     private static final boolean DEBUG_SERVICE = false;
     public static final boolean DEBUG_MEMORY_TRIM = false;
     private static final boolean DEBUG_PROVIDER = false;
-    private static final boolean DEBUG_ORDER = false;
+    public static final boolean DEBUG_ORDER = false;
     private static final long MIN_TIME_BETWEEN_GCS = 5*1000;
     private static final int SQLITE_MEM_RELEASED_EVENT_LOG_TAG = 75003;
     private static final int LOG_AM_ON_PAUSE_CALLED = 30021;
@@ -222,7 +223,7 @@
     private static final boolean REPORT_TO_ACTIVITY = true;
 
     // Maximum number of recent tokens to maintain for debugging purposes
-    private static final int MAX_RECENT_TOKENS = 10;
+    private static final int MAX_DESTROYED_ACTIVITIES = 10;
 
     /**
      * Denotes an invalid sequence number corresponding to a process state change.
@@ -256,7 +257,7 @@
     final H mH = new H();
     final Executor mExecutor = new HandlerExecutor(mH);
     final ArrayMap<IBinder, ActivityClientRecord> mActivities = new ArrayMap<>();
-    final ArrayDeque<Integer> mRecentTokens = new ArrayDeque<>();
+    final ArrayList<DestroyedActivityInfo> mRecentDestroyedActivities = new ArrayList<>();
 
     // List of new activities (via ActivityRecord.nextIdle) that should
     // be reported when next we idle.
@@ -339,6 +340,26 @@
         }
     }
 
+    /**
+     * TODO(b/71506345): Remove this once bug is resolved.
+     */
+    private static final class DestroyedActivityInfo {
+        private final Integer mToken;
+        private final String mReason;
+        private final long mTime;
+
+        DestroyedActivityInfo(Integer token, String reason) {
+            mToken = token;
+            mReason = reason;
+            mTime = System.currentTimeMillis();
+        }
+
+        void dump(PrintWriter pw, String prefix) {
+            pw.println(prefix + "[token:" + mToken + " | time:" + mTime + " | reason:" + mReason
+                    + "]");
+        }
+    }
+
     // The lock of mProviderMap protects the following variables.
     final ArrayMap<ProviderKey, ProviderClientRecord> mProviderMap
         = new ArrayMap<ProviderKey, ProviderClientRecord>();
@@ -398,7 +419,6 @@
         boolean startsNotResumed;
         public final boolean isForward;
         int pendingConfigChanges;
-        boolean onlyLocalRequest;
 
         Window mPendingRemoveWindow;
         WindowManager mPendingRemoveWindowManager;
@@ -520,7 +540,6 @@
             sb.append(", startsNotResumed=").append(startsNotResumed);
             sb.append(", isForward=").append(isForward);
             sb.append(", pendingConfigChanges=").append(pendingConfigChanges);
-            sb.append(", onlyLocalRequest=").append(onlyLocalRequest);
             sb.append(", preserveWindow=").append(mPreserveWindow);
             if (activity != null) {
                 sb.append(", Activity{");
@@ -765,15 +784,6 @@
             sendMessage(H.SLEEPING, token, sleeping ? 1 : 0);
         }
 
-        @Override
-        public final void scheduleRelaunchActivity(IBinder token,
-                List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
-                int configChanges, boolean notResumed, Configuration config,
-                Configuration overrideConfig, boolean preserveWindow) {
-            requestRelaunchActivity(token, pendingResults, pendingNewIntents,
-                    configChanges, notResumed, config, overrideConfig, true, preserveWindow);
-        }
-
         public final void scheduleReceiver(Intent intent, ActivityInfo info,
                 CompatibilityInfo compatInfo, int resultCode, String data, Bundle extras,
                 boolean sync, int sendingUser, int processState) {
@@ -1531,7 +1541,6 @@
         public static final int UNBIND_SERVICE          = 122;
         public static final int DUMP_SERVICE            = 123;
         public static final int LOW_MEMORY              = 124;
-        public static final int RELAUNCH_ACTIVITY       = 126;
         public static final int PROFILER_CONTROL        = 127;
         public static final int CREATE_BACKUP_AGENT     = 128;
         public static final int DESTROY_BACKUP_AGENT    = 129;
@@ -1577,7 +1586,6 @@
                     case UNBIND_SERVICE: return "UNBIND_SERVICE";
                     case DUMP_SERVICE: return "DUMP_SERVICE";
                     case LOW_MEMORY: return "LOW_MEMORY";
-                    case RELAUNCH_ACTIVITY: return "RELAUNCH_ACTIVITY";
                     case PROFILER_CONTROL: return "PROFILER_CONTROL";
                     case CREATE_BACKUP_AGENT: return "CREATE_BACKUP_AGENT";
                     case DESTROY_BACKUP_AGENT: return "DESTROY_BACKUP_AGENT";
@@ -1611,12 +1619,6 @@
         public void handleMessage(Message msg) {
             if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
             switch (msg.what) {
-                case RELAUNCH_ACTIVITY: {
-                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityRestart");
-                    ActivityClientRecord r = (ActivityClientRecord)msg.obj;
-                    handleRelaunchActivity(r);
-                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
-                } break;
                 case BIND_APPLICATION:
                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");
                     AppBindData data = (AppBindData)msg.obj;
@@ -2182,14 +2184,28 @@
 
     @Override
     public void dump(PrintWriter pw, String prefix) {
-        pw.println(prefix + "mActivities:");
+        pw.println(prefix + "Activities:");
 
-        for (ArrayMap.Entry<IBinder, ActivityClientRecord> entry : mActivities.entrySet()) {
-            pw.println(prefix + "  [token:" + entry.getKey().hashCode() + " record:"
-                    + entry.getValue().toString() + "]");
+        if (!mActivities.isEmpty()) {
+            final Iterator<Map.Entry<IBinder, ActivityClientRecord>> activitiesIterator =
+                    mActivities.entrySet().iterator();
+
+            while (activitiesIterator.hasNext()) {
+                final ArrayMap.Entry<IBinder, ActivityClientRecord> entry =
+                        activitiesIterator.next();
+                pw.println(prefix + "  [token:" + entry.getKey().hashCode() + " record:"
+                        + entry.getValue().toString() + "]");
+            }
         }
 
-        pw.println(prefix + "mRecentTokens:" + mRecentTokens);
+        if (!mRecentDestroyedActivities.isEmpty()) {
+            pw.println(prefix + "Recent destroyed activities:");
+            for (int i = 0, size = mRecentDestroyedActivities.size(); i < size; i++) {
+                final DestroyedActivityInfo info = mRecentDestroyedActivities.get(i);
+                pw.print(prefix);
+                info.dump(pw, "  ");
+            }
+        }
     }
 
     public static void dumpMemInfoTable(PrintWriter pw, Debug.MemoryInfo memInfo, boolean checkin,
@@ -2876,11 +2892,6 @@
             r.setState(ON_CREATE);
 
             mActivities.put(r.token, r);
-            mRecentTokens.push(r.token.hashCode());
-
-            if (mRecentTokens.size() > MAX_RECENT_TOKENS) {
-                mRecentTokens.removeLast();
-            }
 
         } catch (SuperNotCalledException e) {
             throw e;
@@ -3726,20 +3737,6 @@
                 }
                 r.activity.performResume(r.startsNotResumed);
 
-                synchronized (mResourcesManager) {
-                    // If there is a pending local relaunch that was requested when the activity was
-                    // paused, it will put the activity into paused state when it finally happens.
-                    // Since the activity resumed before being relaunched, we don't want that to
-                    // happen, so we need to clear the request to relaunch paused.
-                    for (int i = mRelaunchingActivities.size() - 1; i >= 0; i--) {
-                        final ActivityClientRecord relaunching = mRelaunchingActivities.get(i);
-                        if (relaunching.token == r.token
-                                && relaunching.onlyLocalRequest && relaunching.startsNotResumed) {
-                            relaunching.startsNotResumed = false;
-                        }
-                    }
-                }
-
                 EventLog.writeEvent(LOG_AM_ON_RESUME_CALLED, UserHandle.myUserId(),
                         r.activity.getComponentName().getClassName(), reason);
 
@@ -3888,14 +3885,12 @@
                 }
             }
 
-            if (!r.onlyLocalRequest) {
-                r.nextIdle = mNewActivities;
-                mNewActivities = r;
-                if (localLOGV) Slog.v(
-                    TAG, "Scheduling idle handler for " + r);
-                Looper.myQueue().addIdleHandler(new Idler());
+            r.nextIdle = mNewActivities;
+            mNewActivities = r;
+            if (localLOGV) {
+                Slog.v(TAG, "Scheduling idle handler for " + r);
             }
-            r.onlyLocalRequest = false;
+            Looper.myQueue().addIdleHandler(new Idler());
         } else {
             // If an exception was thrown when trying to resume, then
             // just end this activity.
@@ -3909,62 +3904,6 @@
         }
     }
 
-    private int mThumbnailWidth = -1;
-    private int mThumbnailHeight = -1;
-    private Bitmap mAvailThumbnailBitmap = null;
-    private Canvas mThumbnailCanvas = null;
-
-    private Bitmap createThumbnailBitmap(ActivityClientRecord r) {
-        Bitmap thumbnail = mAvailThumbnailBitmap;
-        try {
-            if (thumbnail == null) {
-                int w = mThumbnailWidth;
-                int h;
-                if (w < 0) {
-                    Resources res = r.activity.getResources();
-                    int wId = com.android.internal.R.dimen.thumbnail_width;
-                    int hId = com.android.internal.R.dimen.thumbnail_height;
-                    mThumbnailWidth = w = res.getDimensionPixelSize(wId);
-                    mThumbnailHeight = h = res.getDimensionPixelSize(hId);
-                } else {
-                    h = mThumbnailHeight;
-                }
-
-                // On platforms where we don't want thumbnails, set dims to (0,0)
-                if ((w > 0) && (h > 0)) {
-                    thumbnail = Bitmap.createBitmap(r.activity.getResources().getDisplayMetrics(),
-                            w, h, THUMBNAIL_FORMAT);
-                    thumbnail.eraseColor(0);
-                }
-            }
-
-            if (thumbnail != null) {
-                Canvas cv = mThumbnailCanvas;
-                if (cv == null) {
-                    mThumbnailCanvas = cv = new Canvas();
-                }
-
-                cv.setBitmap(thumbnail);
-                if (!r.activity.onCreateThumbnail(thumbnail, cv)) {
-                    mAvailThumbnailBitmap = thumbnail;
-                    thumbnail = null;
-                }
-                cv.setBitmap(null);
-            }
-
-        } catch (Exception e) {
-            if (!mInstrumentation.onException(r.activity, e)) {
-                throw new RuntimeException(
-                        "Unable to create thumbnail of "
-                        + r.intent.getComponent().toShortString()
-                        + ": " + e.toString(), e);
-            }
-            thumbnail = null;
-        }
-
-        return thumbnail;
-    }
-
     @Override
     public void handlePauseActivity(IBinder token, boolean finished, boolean userLeaving,
             int configChanges, boolean dontReport, PendingTransactionActions pendingActions) {
@@ -4453,7 +4392,7 @@
 
     /** Core implementation of activity destroy call. */
     ActivityClientRecord performDestroyActivity(IBinder token, boolean finishing,
-            int configChanges, boolean getNonConfigInstance) {
+            int configChanges, boolean getNonConfigInstance, String reason) {
         ActivityClientRecord r = mActivities.get(token);
         Class<? extends Activity> activityClass = null;
         if (localLOGV) Slog.v(TAG, "Performing finish of " + r);
@@ -4505,6 +4444,12 @@
             r.setState(ON_DESTROY);
         }
         mActivities.remove(token);
+        mRecentDestroyedActivities.add(0, new DestroyedActivityInfo(token.hashCode(), reason));
+
+        final int recentDestroyedActivitiesSize = mRecentDestroyedActivities.size();
+        if (recentDestroyedActivitiesSize > MAX_DESTROYED_ACTIVITIES) {
+            mRecentDestroyedActivities.remove(recentDestroyedActivitiesSize - 1);
+        }
         StrictMode.decrementExpectedActivityCount(activityClass);
         return r;
     }
@@ -4516,9 +4461,9 @@
 
     @Override
     public void handleDestroyActivity(IBinder token, boolean finishing, int configChanges,
-            boolean getNonConfigInstance) {
+            boolean getNonConfigInstance, String reason) {
         ActivityClientRecord r = performDestroyActivity(token, finishing,
-                configChanges, getNonConfigInstance);
+                configChanges, getNonConfigInstance, reason);
         if (r != null) {
             cleanUpPendingRemoveWindows(r, finishing);
             WindowManager wm = r.activity.getWindowManager();
@@ -4586,15 +4531,12 @@
         mSomeActivitiesChanged = true;
     }
 
-    /**
-     * @param preserveWindow Whether the activity should try to reuse the window it created,
-     *                        including the decor view after the relaunch.
-     */
-    public final void requestRelaunchActivity(IBinder token,
+    @Override
+    public ActivityClientRecord prepareRelaunchActivity(IBinder token,
             List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
-            int configChanges, boolean notResumed, Configuration config,
-            Configuration overrideConfig, boolean fromServer, boolean preserveWindow) {
+            int configChanges, MergedConfiguration config, boolean preserveWindow) {
         ActivityClientRecord target = null;
+        boolean scheduleRelaunch = false;
 
         synchronized (mResourcesManager) {
             for (int i=0; i<mRelaunchingActivities.size(); i++) {
@@ -4616,57 +4558,31 @@
                             r.pendingIntents = pendingNewIntents;
                         }
                     }
-
-                    // For each relaunch request, activity manager expects an answer
-                    if (!r.onlyLocalRequest && fromServer) {
-                        try {
-                            ActivityManager.getService().activityRelaunched(token);
-                        } catch (RemoteException e) {
-                            throw e.rethrowFromSystemServer();
-                        }
-                    }
                     break;
                 }
             }
 
             if (target == null) {
-                if (DEBUG_ORDER) Slog.d(TAG, "requestRelaunchActivity: target is null, fromServer:"
-                        + fromServer);
+                if (DEBUG_ORDER) Slog.d(TAG, "requestRelaunchActivity: target is null");
                 target = new ActivityClientRecord();
                 target.token = token;
                 target.pendingResults = pendingResults;
                 target.pendingIntents = pendingNewIntents;
                 target.mPreserveWindow = preserveWindow;
-                if (!fromServer) {
-                    final ActivityClientRecord existing = mActivities.get(token);
-                    if (DEBUG_ORDER) Slog.d(TAG, "requestRelaunchActivity: " + existing);
-                    if (existing != null) {
-                        if (DEBUG_ORDER) Slog.d(TAG, "requestRelaunchActivity: paused= "
-                                + existing.paused);;
-                        target.startsNotResumed = existing.paused;
-                        target.overrideConfig = existing.overrideConfig;
-                    }
-                    target.onlyLocalRequest = true;
-                }
                 mRelaunchingActivities.add(target);
-                sendMessage(H.RELAUNCH_ACTIVITY, target);
+                scheduleRelaunch = true;
             }
-
-            if (fromServer) {
-                target.startsNotResumed = notResumed;
-                target.onlyLocalRequest = false;
-            }
-            if (config != null) {
-                target.createdConfig = config;
-            }
-            if (overrideConfig != null) {
-                target.overrideConfig = overrideConfig;
-            }
+            target.createdConfig = config.getGlobalConfiguration();
+            target.overrideConfig = config.getOverrideConfiguration();
             target.pendingConfigChanges |= configChanges;
         }
+
+        return scheduleRelaunch ? target : null;
     }
 
-    private void handleRelaunchActivity(ActivityClientRecord tmp) {
+    @Override
+    public void handleRelaunchActivity(ActivityClientRecord tmp,
+            PendingTransactionActions pendingActions) {
         // If we are getting ready to gc after going to the background, well
         // we are back active so skip it.
         unscheduleGcIdler();
@@ -4735,18 +4651,10 @@
         ActivityClientRecord r = mActivities.get(tmp.token);
         if (DEBUG_CONFIGURATION) Slog.v(TAG, "Handling relaunch of " + r);
         if (r == null) {
-            if (!tmp.onlyLocalRequest) {
-                try {
-                    ActivityManager.getService().activityRelaunched(tmp.token);
-                } catch (RemoteException e) {
-                    throw e.rethrowFromSystemServer();
-                }
-            }
             return;
         }
 
         r.activity.mConfigChangeFlags |= configChanges;
-        r.onlyLocalRequest = tmp.onlyLocalRequest;
         r.mPreserveWindow = tmp.mPreserveWindow;
 
         r.activity.mChangingConfigurations = true;
@@ -4763,9 +4671,9 @@
         // preserved by the server, so we want to notify it that we are preparing to replace
         // everything
         try {
-            if (r.mPreserveWindow || r.onlyLocalRequest) {
+            if (r.mPreserveWindow) {
                 WindowManagerGlobal.getWindowSession().prepareToReplaceWindows(
-                        r.token, !r.onlyLocalRequest);
+                        r.token, true /* childrenOnly */);
             }
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
@@ -4780,7 +4688,7 @@
             callActivityOnStop(r, true /* saveState */, "handleRelaunchActivity");
         }
 
-        handleDestroyActivity(r.token, false, configChanges, true);
+        handleDestroyActivity(r.token, false, configChanges, true, "handleRelaunchActivity");
 
         r.activity = null;
         r.window = null;
@@ -4804,24 +4712,22 @@
         r.startsNotResumed = tmp.startsNotResumed;
         r.overrideConfig = tmp.overrideConfig;
 
-        // TODO(lifecycler): Move relaunch to lifecycler.
-        PendingTransactionActions pendingActions = new PendingTransactionActions();
         handleLaunchActivity(r, pendingActions);
-        handleStartActivity(r, pendingActions);
-        handleResumeActivity(r.token, false /* clearHide */, r.isForward, "relaunch");
-        if (r.startsNotResumed) {
-            performPauseActivity(r, false /* finished */, "relaunch", pendingActions);
-        }
+        // Only report a successful relaunch to WindowManager.
+        pendingActions.setReportRelaunchToWindowManager(true);
+    }
 
-        if (!tmp.onlyLocalRequest) {
-            try {
-                ActivityManager.getService().activityRelaunched(r.token);
-                if (r.window != null) {
-                    r.window.reportActivityRelaunched();
-                }
-            } catch (RemoteException e) {
-                throw e.rethrowFromSystemServer();
+    @Override
+    public void reportRelaunch(IBinder token, PendingTransactionActions pendingActions) {
+        try {
+            ActivityManager.getService().activityRelaunched(token);
+            final ActivityClientRecord r = mActivities.get(token);
+            if (pendingActions.shouldReportRelaunchToWindowManager() && r != null
+                    && r.window != null) {
+                r.window.reportActivityRelaunched();
             }
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -5897,21 +5803,23 @@
 
         // Preload fonts resources
         FontsContract.setApplicationContextForResources(appContext);
-        try {
-            final ApplicationInfo info =
-                    getPackageManager().getApplicationInfo(
-                            data.appInfo.packageName,
-                            PackageManager.GET_META_DATA /*flags*/,
-                            UserHandle.myUserId());
-            if (info.metaData != null) {
-                final int preloadedFontsResource = info.metaData.getInt(
-                        ApplicationInfo.METADATA_PRELOADED_FONTS, 0);
-                if (preloadedFontsResource != 0) {
-                    data.info.getResources().preloadFonts(preloadedFontsResource);
+        if (!Process.isIsolated()) {
+            try {
+                final ApplicationInfo info =
+                        getPackageManager().getApplicationInfo(
+                                data.appInfo.packageName,
+                                PackageManager.GET_META_DATA /*flags*/,
+                                UserHandle.myUserId());
+                if (info.metaData != null) {
+                    final int preloadedFontsResource = info.metaData.getInt(
+                            ApplicationInfo.METADATA_PRELOADED_FONTS, 0);
+                    if (preloadedFontsResource != 0) {
+                        data.info.getResources().preloadFonts(preloadedFontsResource);
+                    }
                 }
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
             }
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
         }
     }
 
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 4c9fb74..1026550 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -543,7 +543,6 @@
             OP_CAMERA,
             // Body sensors
             OP_BODY_SENSORS,
-            OP_REQUEST_DELETE_PACKAGES,
 
             // APPOP PERMISSIONS
             OP_ACCESS_NOTIFICATIONS,
diff --git a/core/java/android/app/ClientTransactionHandler.java b/core/java/android/app/ClientTransactionHandler.java
index 5b61fdf..310965e 100644
--- a/core/java/android/app/ClientTransactionHandler.java
+++ b/core/java/android/app/ClientTransactionHandler.java
@@ -21,6 +21,7 @@
 import android.content.res.CompatibilityInfo;
 import android.content.res.Configuration;
 import android.os.IBinder;
+import android.util.MergedConfiguration;
 
 import com.android.internal.content.ReferrerIntent;
 
@@ -60,7 +61,7 @@
 
     /** Destroy the activity. */
     public abstract void handleDestroyActivity(IBinder token, boolean finishing, int configChanges,
-            boolean getNonConfigInstance);
+            boolean getNonConfigInstance, String reason);
 
     /** Pause the activity. */
     public abstract void handlePauseActivity(IBinder token, boolean finished, boolean userLeaving,
@@ -124,6 +125,39 @@
     public abstract ActivityThread.ActivityClientRecord getActivityClient(IBinder token);
 
     /**
+     * Prepare activity relaunch to update internal bookkeeping. This is used to track multiple
+     * relaunch and config update requests.
+     * @param token Activity token.
+     * @param pendingResults Activity results to be delivered.
+     * @param pendingNewIntents New intent messages to be delivered.
+     * @param configChanges Mask of configuration changes that have occurred.
+     * @param config New configuration applied to the activity.
+     * @param preserveWindow Whether the activity should try to reuse the window it created,
+     *                        including the decor view after the relaunch.
+     * @return An initialized instance of {@link ActivityThread.ActivityClientRecord} to use during
+     *         relaunch, or {@code null} if relaunch cancelled.
+     */
+    public abstract ActivityThread.ActivityClientRecord prepareRelaunchActivity(IBinder token,
+            List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
+            int configChanges, MergedConfiguration config, boolean preserveWindow);
+
+    /**
+     * Perform activity relaunch.
+     * @param r Activity client record prepared for relaunch.
+     * @param pendingActions Pending actions to be used on later stages of activity transaction.
+     * */
+    public abstract void handleRelaunchActivity(ActivityThread.ActivityClientRecord r,
+            PendingTransactionActions pendingActions);
+
+    /**
+     * Report that relaunch request was handled.
+     * @param token Target activity token.
+     * @param pendingActions Pending actions initialized on earlier stages of activity transaction.
+     *                       Used to check if we should report relaunch to WM.
+     * */
+    public abstract void reportRelaunch(IBinder token, PendingTransactionActions pendingActions);
+
+    /**
      * Debugging output.
      * @param pw {@link PrintWriter} to write logs to.
      * @param prefix Prefix to prepend to output.
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 4a9b2bc..99fb465 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.TestApi;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.ContentProvider;
@@ -409,6 +410,7 @@
         return sp;
     }
 
+    @GuardedBy("ContextImpl.class")
     private ArrayMap<File, SharedPreferencesImpl> getSharedPreferencesCacheLocked() {
         if (sSharedPrefsCache == null) {
             sSharedPrefsCache = new ArrayMap<>();
@@ -2263,6 +2265,7 @@
     }
 
     /** @hide */
+    @TestApi
     @Override
     public void setAutofillCompatibilityEnabled(boolean autofillCompatEnabled) {
         mIsAutofillCompatEnabled = autofillCompatEnabled;
diff --git a/core/java/android/app/Dialog.java b/core/java/android/app/Dialog.java
index 2b648ea..eb26026 100644
--- a/core/java/android/app/Dialog.java
+++ b/core/java/android/app/Dialog.java
@@ -609,18 +609,19 @@
 
     /**
      * A key was pressed down.
+     * <p>
+     * If the focused view didn't want this event, this method is called.
+     * <p>
+     * Default implementation consumes {@link KeyEvent#KEYCODE_BACK KEYCODE_BACK}
+     * and, as of {@link android.os.Build.VERSION_CODES#P P}, {@link KeyEvent#KEYCODE_ESCAPE
+     * KEYCODE_ESCAPE} to later handle them in {@link #onKeyUp}.
      * 
-     * <p>If the focused view didn't want this event, this method is called.
-     *
-     * <p>The default implementation consumed the KEYCODE_BACK to later
-     * handle it in {@link #onKeyUp}.
-     *
      * @see #onKeyUp
      * @see android.view.KeyEvent
      */
     @Override
     public boolean onKeyDown(int keyCode, @NonNull KeyEvent event) {
-        if (keyCode == KeyEvent.KEYCODE_BACK) {
+        if (keyCode == KeyEvent.KEYCODE_BACK || keyCode == KeyEvent.KEYCODE_ESCAPE) {
             event.startTracking();
             return true;
         }
@@ -640,16 +641,18 @@
 
     /**
      * A key was released.
-     * 
-     * <p>The default implementation handles KEYCODE_BACK to close the
-     * dialog.
+     * <p>
+     * Default implementation consumes {@link KeyEvent#KEYCODE_BACK KEYCODE_BACK}
+     * and, as of {@link android.os.Build.VERSION_CODES#P P}, {@link KeyEvent#KEYCODE_ESCAPE
+     * KEYCODE_ESCAPE} to close the dialog.
      *
      * @see #onKeyDown
-     * @see KeyEvent
+     * @see android.view.KeyEvent
      */
     @Override
     public boolean onKeyUp(int keyCode, @NonNull KeyEvent event) {
-        if (keyCode == KeyEvent.KEYCODE_BACK && event.isTracking()
+        if ((keyCode == KeyEvent.KEYCODE_BACK || keyCode == KeyEvent.KEYCODE_ESCAPE)
+                && event.isTracking()
                 && !event.isCanceled()) {
             onBackPressed();
             return true;
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index 02be002..54fd0c4 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -68,6 +68,7 @@
 import android.service.voice.IVoiceInteractionSession;
 import android.view.IRecentsAnimationRunner;
 import android.view.RemoteAnimationDefinition;
+import android.view.RemoteAnimationAdapter;
 import com.android.internal.app.IVoiceInteractor;
 import com.android.internal.os.IResultReceiver;
 import com.android.internal.policy.IKeyguardDismissCallback;
@@ -423,6 +424,8 @@
     void restart();
     void performIdleMaintenance();
     void takePersistableUriPermission(in Uri uri, int modeFlags, int userId);
+    boolean updatePersistableUriPermission(in Uri uri, boolean prefix, String packageName,
+                                           boolean grant, int userId);
     void releasePersistableUriPermission(in Uri uri, int modeFlags, int userId);
     ParceledListSlice getPersistedUriPermissions(in String packageName, boolean incoming);
     void appNotRespondingViaProvider(in IBinder connection);
@@ -683,17 +686,24 @@
     // If a transaction which will also be used on the native side is being inserted, add it
     // alongside with other transactions of this kind at the top of this file.
 
-     void setShowWhenLocked(in IBinder token, boolean showWhenLocked);
-     void setTurnScreenOn(in IBinder token, boolean turnScreenOn);
+    void setShowWhenLocked(in IBinder token, boolean showWhenLocked);
+    void setTurnScreenOn(in IBinder token, boolean turnScreenOn);
 
-     /**
-      *  Similar to {@link #startUserInBackground(int userId), but with a listener to report
-      *  user unlock progress.
-      */
-     boolean startUserInBackgroundWithListener(int userid, IProgressListener unlockProgressListener);
+    /**
+     *  Similar to {@link #startUserInBackground(int userId), but with a listener to report
+     *  user unlock progress.
+     */
+    boolean startUserInBackgroundWithListener(int userid, IProgressListener unlockProgressListener);
 
-     /**
-      * Registers remote animations for a specific activity.
-      */
-     void registerRemoteAnimations(in IBinder token, in RemoteAnimationDefinition definition);
+    /**
+     * Registers remote animations for a specific activity.
+     */
+    void registerRemoteAnimations(in IBinder token, in RemoteAnimationDefinition definition);
+
+    /**
+     * Registers a remote animation to be run for all activity starts from a certain package during
+     * a short predefined amount of time.
+     */
+    void registerRemoteAnimationForNextActivityStart(in String packageName,
+           in RemoteAnimationAdapter adapter);
 }
diff --git a/core/java/android/app/IAlarmManager.aidl b/core/java/android/app/IAlarmManager.aidl
index 7b05b49..ded4c49 100644
--- a/core/java/android/app/IAlarmManager.aidl
+++ b/core/java/android/app/IAlarmManager.aidl
@@ -37,4 +37,5 @@
     void remove(in PendingIntent operation, in IAlarmListener listener);
     long getNextWakeFromIdleTime();
     AlarmManager.AlarmClockInfo getNextAlarmClock(int userId);
+    long currentNetworkTimeMillis();
 }
diff --git a/core/java/android/app/IApplicationThread.aidl b/core/java/android/app/IApplicationThread.aidl
index 9e99a78..ae9b83e 100644
--- a/core/java/android/app/IApplicationThread.aidl
+++ b/core/java/android/app/IApplicationThread.aidl
@@ -83,9 +83,6 @@
             int resultCode, in String data, in Bundle extras, boolean ordered,
             boolean sticky, int sendingUser, int processState);
     void scheduleLowMemory();
-    void scheduleRelaunchActivity(IBinder token, in List<ResultInfo> pendingResults,
-            in List<ReferrerIntent> pendingNewIntents, int configChanges, boolean notResumed,
-            in Configuration config, in Configuration overrideConfig, boolean preserveWindow);
     void scheduleSleeping(IBinder token, boolean sleeping);
     void profilerControl(boolean start, in ProfilerInfo profilerInfo, int profileType);
     void setSchedulingGroup(int group);
diff --git a/core/java/android/app/LocalActivityManager.java b/core/java/android/app/LocalActivityManager.java
index 1d34595..e297719 100644
--- a/core/java/android/app/LocalActivityManager.java
+++ b/core/java/android/app/LocalActivityManager.java
@@ -380,7 +380,7 @@
         }
         if (localLOGV) Log.v(TAG, r.id + ": destroying");
         mActivityThread.performDestroyActivity(r, finish, 0 /* configChanges */,
-                false /* getNonConfigInstance */);
+                false /* getNonConfigInstance */, "LocalActivityManager::performDestroy");
         r.activity = null;
         r.window = null;
         if (finish) {
@@ -645,7 +645,7 @@
             LocalActivityRecord r = mActivityArray.get(i);
             if (localLOGV) Log.v(TAG, r.id + ": destroying");
             mActivityThread.performDestroyActivity(r, finishing, 0 /* configChanges */,
-                    false /* getNonConfigInstance */);
+                    false /* getNonConfigInstance */, "LocalActivityManager::dispatchDestroy");
         }
         mActivities.clear();
         mActivityArray.clear();
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 6e40986..e80610b 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -1055,11 +1055,10 @@
     /**
      * {@link #extras} key: A
      * {@link android.content.ContentUris content URI} pointing to an image that can be displayed
-     * in the background when the notification is selected. The URI must point to an image stream
-     * suitable for passing into
+     * in the background when the notification is selected. Used on television platforms.
+     * The URI must point to an image stream suitable for passing into
      * {@link android.graphics.BitmapFactory#decodeStream(java.io.InputStream)
-     * BitmapFactory.decodeStream}; all other content types will be ignored. The content provider
-     * URI used for this purpose must require no permissions to read the image data.
+     * BitmapFactory.decodeStream}; all other content types will be ignored.
      */
     public static final String EXTRA_BACKGROUND_IMAGE_URI = "android.backgroundImageUri";
 
@@ -4617,10 +4616,15 @@
                 if (N>MAX_ACTION_BUTTONS) N=MAX_ACTION_BUTTONS;
                 for (int i=0; i<N; i++) {
                     Action action = mActions.get(i);
-                    validRemoteInput |= hasValidRemoteInput(action);
+                    boolean actionHasValidInput = hasValidRemoteInput(action);
+                    validRemoteInput |= actionHasValidInput;
 
                     final RemoteViews button = generateActionButton(action, emphazisedMode,
                             i % 2 != 0, p.ambient);
+                    if (actionHasValidInput) {
+                        // Clear the drawable
+                        button.setInt(R.id.action0, "setBackgroundResource", 0);
+                    }
                     big.addView(R.id.actions, button);
                 }
             } else {
@@ -6435,7 +6439,7 @@
         public RemoteViews makeContentView(boolean increasedHeight) {
             mBuilder.mOriginalActions = mBuilder.mActions;
             mBuilder.mActions = new ArrayList<>();
-            RemoteViews remoteViews = makeBigContentView(true /* showRightIcon */);
+            RemoteViews remoteViews = makeMessagingView(true /* isCollapsed */);
             mBuilder.mActions = mBuilder.mOriginalActions;
             mBuilder.mOriginalActions = null;
             return remoteViews;
@@ -6470,11 +6474,11 @@
          */
         @Override
         public RemoteViews makeBigContentView() {
-            return makeBigContentView(false /* showRightIcon */);
+            return makeMessagingView(false /* isCollapsed */);
         }
 
         @NonNull
-        private RemoteViews makeBigContentView(boolean showRightIcon) {
+        private RemoteViews makeMessagingView(boolean isCollapsed) {
             CharSequence conversationTitle = !TextUtils.isEmpty(super.mBigContentTitle)
                     ? super.mBigContentTitle
                     : mConversationTitle;
@@ -6485,21 +6489,24 @@
                 nameReplacement = conversationTitle;
                 conversationTitle = null;
             }
+            boolean hideLargeIcon = !isCollapsed || isOneToOne;
             RemoteViews contentView = mBuilder.applyStandardTemplateWithActions(
                     mBuilder.getMessagingLayoutResource(),
                     mBuilder.mParams.reset().hasProgress(false).title(conversationTitle).text(null)
-                            .hideLargeIcon(!showRightIcon || isOneToOne)
+                            .hideLargeIcon(hideLargeIcon)
                             .headerTextSecondary(conversationTitle)
-                            .alwaysShowReply(showRightIcon));
+                            .alwaysShowReply(isCollapsed));
             addExtras(mBuilder.mN.extras);
             // also update the end margin if there is an image
             int endMargin = R.dimen.notification_content_margin_end;
-            if (mBuilder.mN.hasLargeIcon() && showRightIcon) {
+            if (isCollapsed) {
                 endMargin = R.dimen.notification_content_plus_picture_margin_end;
             }
             contentView.setViewLayoutMarginEndDimen(R.id.notification_main_column, endMargin);
             contentView.setInt(R.id.status_bar_latest_event_content, "setLayoutColor",
                     mBuilder.resolveContrastColor());
+            contentView.setBoolean(R.id.status_bar_latest_event_content, "setIsCollapsed",
+                    isCollapsed);
             contentView.setIcon(R.id.status_bar_latest_event_content, "setLargeIcon",
                     mBuilder.mN.mLargeIcon);
             contentView.setCharSequence(R.id.status_bar_latest_event_content, "setNameReplacement",
@@ -6566,7 +6573,7 @@
          */
         @Override
         public RemoteViews makeHeadsUpContentView(boolean increasedHeight) {
-            RemoteViews remoteViews = makeBigContentView(true /* showRightIcon */);
+            RemoteViews remoteViews = makeMessagingView(true /* isCollapsed */);
             remoteViews.setInt(R.id.notification_messaging, "setMaxDisplayedLines", 1);
             return remoteViews;
         }
@@ -8855,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;
@@ -8863,6 +8871,7 @@
         private String mChannelId;
         private PendingIntent mContentIntent;
         private PendingIntent mDeleteIntent;
+        private boolean mSuppressShowOverApps;
 
         /**
          * Create a {@link TvExtender} with default options.
@@ -8882,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);
             }
@@ -8898,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);
             }
@@ -8990,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/NotificationManager.java b/core/java/android/app/NotificationManager.java
index 538623f..b10e608 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -24,6 +24,7 @@
 import android.app.Notification.Builder;
 import android.content.ComponentName;
 import android.content.Context;
+import android.content.Intent;
 import android.content.pm.ParceledListSlice;
 import android.graphics.drawable.Icon;
 import android.net.Uri;
@@ -350,6 +351,14 @@
      * the same tag and id has already been posted by your application and has not yet been
      * canceled, it will be replaced by the updated information.
      *
+     * All {@link android.service.notification.NotificationListenerService listener services} will
+     * be granted {@link Intent#FLAG_GRANT_READ_URI_PERMISSION} access to any {@link Uri uris}
+     * provided on this notification or the
+     * {@link NotificationChannel} this notification is posted to using
+     * {@link Context#grantUriPermission(String, Uri, int)}. Permission will be revoked when the
+     * notification is canceled, or you can revoke permissions with
+     * {@link Context#revokeUriPermission(Uri, int)}.
+     *
      * @param tag A string identifier for this notification.  May be {@code null}.
      * @param id An identifier for this notification.  The pair (tag, id) must be unique
      *        within your application.
@@ -370,11 +379,13 @@
         String pkg = mContext.getPackageName();
         // Fix the notification as best we can.
         Notification.addFieldsFromContext(mContext, notification);
+
         if (notification.sound != null) {
             notification.sound = notification.sound.getCanonicalUri();
             if (StrictMode.vmFileUriExposureEnabled()) {
                 notification.sound.checkFileUriExposed("Notification.sound");
             }
+
         }
         fixLegacySmallIcon(notification, pkg);
         if (mContext.getApplicationInfo().targetSdkVersion > Build.VERSION_CODES.LOLLIPOP_MR1) {
@@ -385,6 +396,7 @@
         }
         if (localLOGV) Log.v(TAG, pkg + ": notify(" + id + ", " + notification + ")");
         notification.reduceImageSizes(mContext);
+
         ActivityManager am = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
         boolean isLowRam = am.isLowRamDevice();
         final Notification copy = Builder.maybeCloneStrippedForDelivery(notification, isLowRam);
diff --git a/core/java/android/app/ProcessMemoryState.java b/core/java/android/app/ProcessMemoryState.java
new file mode 100644
index 0000000..39db16d
--- /dev/null
+++ b/core/java/android/app/ProcessMemoryState.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * The memory stats for a process.
+ * {@hide}
+ */
+public class ProcessMemoryState implements Parcelable {
+    public int uid;
+    public String processName;
+    public int oomScore;
+    public long pgfault;
+    public long pgmajfault;
+    public long rssInBytes;
+    public long cacheInBytes;
+    public long swapInBytes;
+
+    public ProcessMemoryState(int uid, String processName, int oomScore, long pgfault,
+                              long pgmajfault, long rssInBytes, long cacheInBytes,
+                              long swapInBytes) {
+        this.uid = uid;
+        this.processName = processName;
+        this.oomScore = oomScore;
+        this.pgfault = pgfault;
+        this.pgmajfault = pgmajfault;
+        this.rssInBytes = rssInBytes;
+        this.cacheInBytes = cacheInBytes;
+        this.swapInBytes = swapInBytes;
+    }
+
+    private ProcessMemoryState(Parcel in) {
+        uid = in.readInt();
+        processName = in.readString();
+        oomScore = in.readInt();
+        pgfault = in.readLong();
+        pgmajfault = in.readLong();
+        rssInBytes = in.readLong();
+        cacheInBytes = in.readLong();
+        swapInBytes = in.readLong();
+    }
+
+    public static final Creator<ProcessMemoryState> CREATOR = new Creator<ProcessMemoryState>() {
+        @Override
+        public ProcessMemoryState createFromParcel(Parcel in) {
+            return new ProcessMemoryState(in);
+        }
+
+        @Override
+        public ProcessMemoryState[] newArray(int size) {
+            return new ProcessMemoryState[size];
+        }
+    };
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel parcel, int i) {
+        parcel.writeInt(uid);
+        parcel.writeString(processName);
+        parcel.writeInt(oomScore);
+        parcel.writeLong(pgfault);
+        parcel.writeLong(pgmajfault);
+        parcel.writeLong(rssInBytes);
+        parcel.writeLong(cacheInBytes);
+        parcel.writeLong(swapInBytes);
+    }
+}
diff --git a/core/java/android/app/StatsManager.java b/core/java/android/app/StatsManager.java
index c525c89..c2c91c2 100644
--- a/core/java/android/app/StatsManager.java
+++ b/core/java/android/app/StatsManager.java
@@ -30,20 +30,27 @@
  * @hide
  */
 @SystemApi
-public final class StatsManager extends android.util.StatsManager { // TODO: Remove the extends.
+public final class StatsManager {
     IStatsManager mService;
     private static final String TAG = "StatsManager";
+    private static final boolean DEBUG = false;
 
-    /** Long extra of uid that added the relevant stats config. */
-    public static final String EXTRA_STATS_CONFIG_UID =
-            "android.app.extra.STATS_CONFIG_UID";
-    /** Long extra of the relevant stats config's configKey. */
-    public static final String EXTRA_STATS_CONFIG_KEY =
-            "android.app.extra.STATS_CONFIG_KEY";
-    /** Long extra of the relevant statsd_config.proto's Subscription.id. */
+    /**
+     * Long extra of uid that added the relevant stats config.
+     */
+    public static final String EXTRA_STATS_CONFIG_UID = "android.app.extra.STATS_CONFIG_UID";
+    /**
+     * Long extra of the relevant stats config's configKey.
+     */
+    public static final String EXTRA_STATS_CONFIG_KEY = "android.app.extra.STATS_CONFIG_KEY";
+    /**
+     * Long extra of the relevant statsd_config.proto's Subscription.id.
+     */
     public static final String EXTRA_STATS_SUBSCRIPTION_ID =
             "android.app.extra.STATS_SUBSCRIPTION_ID";
-    /** Long extra of the relevant statsd_config.proto's Subscription.rule_id. */
+    /**
+     * Long extra of the relevant statsd_config.proto's Subscription.rule_id.
+     */
     public static final String EXTRA_STATS_SUBSCRIPTION_RULE_ID =
             "android.app.extra.STATS_SUBSCRIPTION_RULE_ID";
     /**
@@ -68,28 +75,34 @@
     }
 
     /**
+     * Temporary. Will be deleted.
+     */
+    @RequiresPermission(Manifest.permission.DUMP)
+    public boolean addConfiguration(long configKey, byte[] config, String a, String b) {
+        return addConfiguration(configKey, config);
+    }
+
+    /**
      * Clients can send a configuration and simultaneously registers the name of a broadcast
      * receiver that listens for when it should request data.
      *
      * @param configKey An arbitrary integer that allows clients to track the configuration.
      * @param config    Wire-encoded StatsDConfig proto that specifies metrics (and all
      *                  dependencies eg, conditions and matchers).
-     * @param pkg       The package name to receive the broadcast.
-     * @param cls       The name of the class that receives the broadcast.
      * @return true if successful
      */
     @RequiresPermission(Manifest.permission.DUMP)
-    public boolean addConfiguration(long configKey, byte[] config, String pkg, String cls) {
+    public boolean addConfiguration(long configKey, byte[] config) {
         synchronized (this) {
             try {
                 IStatsManager service = getIStatsManagerLocked();
                 if (service == null) {
-                    Slog.d(TAG, "Failed to find statsd when adding configuration");
+                    if (DEBUG) Slog.d(TAG, "Failed to find statsd when adding configuration");
                     return false;
                 }
-                return service.addConfiguration(configKey, config, pkg, cls);
+                return service.addConfiguration(configKey, config);
             } catch (RemoteException e) {
-                Slog.d(TAG, "Failed to connect to statsd when adding configuration");
+                if (DEBUG) Slog.d(TAG, "Failed to connect to statsd when adding configuration");
                 return false;
             }
         }
@@ -107,12 +120,12 @@
             try {
                 IStatsManager service = getIStatsManagerLocked();
                 if (service == null) {
-                    Slog.d(TAG, "Failed to find statsd when removing configuration");
+                    if (DEBUG) Slog.d(TAG, "Failed to find statsd when removing configuration");
                     return false;
                 }
                 return service.removeConfiguration(configKey);
             } catch (RemoteException e) {
-                Slog.d(TAG, "Failed to connect to statsd when removing configuration");
+                if (DEBUG) Slog.d(TAG, "Failed to connect to statsd when removing configuration");
                 return false;
             }
         }
@@ -121,38 +134,34 @@
     /**
      * Set the PendingIntent to be used when broadcasting subscriber information to the given
      * subscriberId within the given config.
-     *
      * <p>
      * Suppose that the calling uid has added a config with key configKey, and that in this config
      * it is specified that when a particular anomaly is detected, a broadcast should be sent to
      * a BroadcastSubscriber with id subscriberId. This function links the given pendingIntent with
      * that subscriberId (for that config), so that this pendingIntent is used to send the broadcast
      * when the anomaly is detected.
-     *
      * <p>
      * When statsd sends the broadcast, the PendingIntent will used to send an intent with
      * information of
-     *   {@link #EXTRA_STATS_CONFIG_UID},
-     *   {@link #EXTRA_STATS_CONFIG_KEY},
-     *   {@link #EXTRA_STATS_SUBSCRIPTION_ID},
-     *   {@link #EXTRA_STATS_SUBSCRIPTION_RULE_ID}, and
-     *   {@link #EXTRA_STATS_DIMENSIONS_VALUE}.
-     *
+     * {@link #EXTRA_STATS_CONFIG_UID},
+     * {@link #EXTRA_STATS_CONFIG_KEY},
+     * {@link #EXTRA_STATS_SUBSCRIPTION_ID},
+     * {@link #EXTRA_STATS_SUBSCRIPTION_RULE_ID}, and
+     * {@link #EXTRA_STATS_DIMENSIONS_VALUE}.
      * <p>
      * This function can only be called by the owner (uid) of the config. It must be called each
      * time statsd starts. The config must have been added first (via addConfiguration()).
      *
-     * @param configKey The integer naming the config to which this subscriber is attached.
-     * @param subscriberId ID of the subscriber, as used in the config.
+     * @param configKey     The integer naming the config to which this subscriber is attached.
+     * @param subscriberId  ID of the subscriber, as used in the config.
      * @param pendingIntent the PendingIntent to use when broadcasting info to the subscriber
      *                      associated with the given subscriberId. May be null, in which case
      *                      it undoes any previous setting of this subscriberId.
      * @return true if successful
      */
     @RequiresPermission(Manifest.permission.DUMP)
-    public boolean setBroadcastSubscriber(long configKey,
-                                          long subscriberId,
-                                          PendingIntent pendingIntent) {
+    public boolean setBroadcastSubscriber(
+            long configKey, long subscriberId, PendingIntent pendingIntent) {
         synchronized (this) {
             try {
                 IStatsManager service = getIStatsManagerLocked();
@@ -175,6 +184,44 @@
     }
 
     /**
+     * Registers the operation that is called to retrieve the metrics data. This must be called
+     * each time statsd starts. The config must have been added first (via addConfiguration(),
+     * although addConfiguration could have been called on a previous boot). This operation allows
+     * statsd to send metrics data whenever statsd determines that the metrics in memory are
+     * approaching the memory limits. The fetch operation should call {@link #getData} to fetch the
+     * data, which also deletes the retrieved metrics from statsd's memory.
+     *
+     * @param configKey     The integer naming the config to which this operation is attached.
+     * @param pendingIntent the PendingIntent to use when broadcasting info to the subscriber
+     *                      associated with the given subscriberId. May be null, in which case
+     *                      it removes any associated pending intent with this configKey.
+     * @return true if successful
+     */
+    @RequiresPermission(Manifest.permission.DUMP)
+    public boolean setDataFetchOperation(long configKey, PendingIntent pendingIntent) {
+        synchronized (this) {
+            try {
+                IStatsManager service = getIStatsManagerLocked();
+                if (service == null) {
+                    Slog.d(TAG, "Failed to find statsd when registering data listener.");
+                    return false;
+                }
+                if (pendingIntent == null) {
+                    return service.removeDataFetchOperation(configKey);
+                } else {
+                    // Extracts IIntentSender from the PendingIntent and turns it into an IBinder.
+                    IBinder intentSender = pendingIntent.getTarget().asBinder();
+                    return service.setDataFetchOperation(configKey, intentSender);
+                }
+
+            } catch (RemoteException e) {
+                Slog.d(TAG, "Failed to connect to statsd when registering data listener.");
+                return false;
+            }
+        }
+    }
+
+    /**
      * Clients can request data with a binder call. This getter is destructive and also clears
      * the retrieved metrics from statsd memory.
      *
@@ -187,12 +234,12 @@
             try {
                 IStatsManager service = getIStatsManagerLocked();
                 if (service == null) {
-                    Slog.d(TAG, "Failed to find statsd when getting data");
+                    if (DEBUG) Slog.d(TAG, "Failed to find statsd when getting data");
                     return null;
                 }
                 return service.getData(configKey);
             } catch (RemoteException e) {
-                Slog.d(TAG, "Failed to connecto statsd when getting data");
+                if (DEBUG) Slog.d(TAG, "Failed to connecto statsd when getting data");
                 return null;
             }
         }
@@ -211,12 +258,12 @@
             try {
                 IStatsManager service = getIStatsManagerLocked();
                 if (service == null) {
-                    Slog.d(TAG, "Failed to find statsd when getting metadata");
+                    if (DEBUG) Slog.d(TAG, "Failed to find statsd when getting metadata");
                     return null;
                 }
                 return service.getMetadata();
             } catch (RemoteException e) {
-                Slog.d(TAG, "Failed to connecto statsd when getting metadata");
+                if (DEBUG) Slog.d(TAG, "Failed to connecto statsd when getting metadata");
                 return null;
             }
         }
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 87f32b2..aa52cde 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -38,7 +38,6 @@
 import android.content.Context;
 import android.content.IRestrictionsManager;
 import android.content.RestrictionsManager;
-import android.content.pm.ApplicationInfo;
 import android.content.pm.CrossProfileApps;
 import android.content.pm.ICrossProfileApps;
 import android.content.pm.IShortcutService;
@@ -90,7 +89,6 @@
 import android.net.lowpan.LowpanManager;
 import android.net.nsd.INsdManager;
 import android.net.nsd.NsdManager;
-import android.net.wifi.IRttManager;
 import android.net.wifi.IWifiManager;
 import android.net.wifi.IWifiScanner;
 import android.net.wifi.RttManager;
@@ -117,7 +115,6 @@
 import android.os.IUserManager;
 import android.os.IncidentManager;
 import android.os.PowerManager;
-import android.os.Process;
 import android.os.RecoverySystem;
 import android.os.ServiceManager;
 import android.os.ServiceManager.ServiceNotFoundException;
@@ -639,13 +636,13 @@
 
         registerService(Context.WIFI_RTT_SERVICE, RttManager.class,
                 new CachedServiceFetcher<RttManager>() {
-            @Override
-            public RttManager createService(ContextImpl ctx) throws ServiceNotFoundException {
-                IBinder b = ServiceManager.getServiceOrThrow(Context.WIFI_RTT_SERVICE);
-                IRttManager service = IRttManager.Stub.asInterface(b);
-                return new RttManager(ctx.getOuterContext(), service,
-                        ConnectivityThread.getInstanceLooper());
-            }});
+                @Override
+                public RttManager createService(ContextImpl ctx) throws ServiceNotFoundException {
+                    IBinder b = ServiceManager.getServiceOrThrow(Context.WIFI_RTT_RANGING_SERVICE);
+                    IWifiRttManager service = IWifiRttManager.Stub.asInterface(b);
+                    return new RttManager(ctx.getOuterContext(),
+                            new WifiRttManager(ctx.getOuterContext(), service));
+                }});
 
         registerService(Context.WIFI_RTT_RANGING_SERVICE, WifiRttManager.class,
                 new CachedServiceFetcher<WifiRttManager>() {
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 8d16100..14b2119 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -21,6 +21,7 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.RequiresFeature;
 import android.annotation.RequiresPermission;
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
@@ -116,6 +117,7 @@
  * guide. </div>
  */
 @SystemService(Context.DEVICE_POLICY_SERVICE)
+@RequiresFeature(PackageManager.FEATURE_DEVICE_ADMIN)
 public class DevicePolicyManager {
     private static String TAG = "DevicePolicyManager";
 
@@ -3444,9 +3446,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;
 
@@ -9404,41 +9403,6 @@
     }
 
     /**
-     * Allows/disallows printing.
-     *
-     * Called by a device owner or a profile owner.
-     * Device owner changes policy for all users. Profile owner can override it if present.
-     * Printing is enabled by default. If {@code FEATURE_PRINTING} is absent, the call is ignored.
-     *
-     * @param admin which {@link DeviceAdminReceiver} this request is associated with.
-     * @param enabled whether printing should be allowed or not.
-     * @throws SecurityException if {@code admin} is neither device, nor profile owner.
-     */
-    public void setPrintingEnabled(@NonNull ComponentName admin, boolean enabled) {
-        try {
-            mService.setPrintingEnabled(admin, enabled);
-        } catch (RemoteException re) {
-            throw re.rethrowFromSystemServer();
-        }
-    }
-
-    /**
-     * Returns whether printing is enabled for this user.
-     *
-     * Always {@code false} if {@code FEATURE_PRINTING} is absent.
-     * Otherwise, {@code true} by default.
-     *
-     * @return {@code true} iff printing is enabled.
-     */
-    public boolean isPrintingEnabled() {
-        try {
-            return mService.isPrintingEnabled();
-        } catch (RemoteException re) {
-            throw re.rethrowFromSystemServer();
-        }
-    }
-
-    /**
      * Called by device owner to add an override APN.
      *
      * @param admin which {@link DeviceAdminReceiver} this request is associated with
diff --git a/core/java/android/app/admin/FreezeInterval.java b/core/java/android/app/admin/FreezeInterval.java
index 7acdfc8..de5e21a 100644
--- a/core/java/android/app/admin/FreezeInterval.java
+++ b/core/java/android/app/admin/FreezeInterval.java
@@ -84,6 +84,10 @@
         }
     }
 
+    boolean after(LocalDate localDate) {
+        return mStartDay > dayOfYearDisregardLeapYear(localDate);
+    }
+
     /**
      * Instantiate the current interval to real calendar dates, given a calendar date
      * {@code now}. If the interval contains now, the returned calendar dates should be the
@@ -161,7 +165,7 @@
      *     3. At most one wrapped Interval remains, and it will be at the end of the list
      * @hide
      */
-    private static List<FreezeInterval> canonicalizeIntervals(List<FreezeInterval> intervals) {
+    protected static List<FreezeInterval> canonicalizeIntervals(List<FreezeInterval> intervals) {
         boolean[] taken = new boolean[DAYS_IN_YEAR];
         // First convert the intervals into flat array
         for (FreezeInterval interval : intervals) {
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index ef99007..5218a73 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -402,9 +402,6 @@
     CharSequence getStartUserSessionMessage(in ComponentName admin);
     CharSequence getEndUserSessionMessage(in ComponentName admin);
 
-    void setPrintingEnabled(in ComponentName admin, boolean enabled);
-    boolean isPrintingEnabled();
-
     List<String> setMeteredDataDisabled(in ComponentName admin, in List<String> packageNames);
     List<String> getMeteredDataDisabled(in ComponentName admin);
 
diff --git a/core/java/android/app/admin/SecurityLog.java b/core/java/android/app/admin/SecurityLog.java
index 08effd9..faaa004 100644
--- a/core/java/android/app/admin/SecurityLog.java
+++ b/core/java/android/app/admin/SecurityLog.java
@@ -77,6 +77,9 @@
             TAG_KEY_DESTRUCTION,
             TAG_CERT_AUTHORITY_INSTALLED,
             TAG_CERT_AUTHORITY_REMOVED,
+            TAG_CRYPTO_SELF_TEST_COMPLETED,
+            TAG_KEY_INTEGRITY_VIOLATION,
+            TAG_CERT_VALIDATION_FAILURE,
     })
     public @interface SecurityLogTag {}
 
@@ -316,6 +319,7 @@
      * {@link SecurityEvent#getData()}:
      * <li> [0] admin package name ({@code String}),
      * <li> [1] admin user ID ({@code Integer}).
+     * <li> [2] target user ID ({@code Integer})
      */
     public static final int TAG_REMOTE_LOCK = SecurityLogTags.SECURITY_REMOTE_LOCK;
 
@@ -400,6 +404,31 @@
             SecurityLogTags.SECURITY_USER_RESTRICTION_REMOVED;
 
     /**
+     * Indicates that cryptographic functionality self test has completed. The log entry contains an
+     * {@code Integer} payload, indicating the result of the test (0 if the test failed, 1 if
+     * succeeded) and accessible via {@link SecurityEvent#getData()}.
+     */
+    public static final int TAG_CRYPTO_SELF_TEST_COMPLETED =
+            SecurityLogTags.SECURITY_CRYPTO_SELF_TEST_COMPLETED;
+
+    /**
+     * Indicates a failed cryptographic key integrity check. The log entry contains the following
+     * information about the event, encapsulated in an {@link Object} array and accessible via
+     * {@link SecurityEvent#getData()}:
+     * <li> [0] alias of the key ({@code String})
+     * <li> [1] owner application uid ({@code Integer}).
+     */
+    public static final int TAG_KEY_INTEGRITY_VIOLATION =
+            SecurityLogTags.SECURITY_KEY_INTEGRITY_VIOLATION;
+
+    /**
+     * Indicates a failure to validate X.509v3 certificate. The log entry contains a {@code String}
+     * payload indicating the failure reason, accessible via {@link SecurityEvent#getData()}.
+     */
+    public static final int TAG_CERT_VALIDATION_FAILURE =
+            SecurityLogTags.SECURITY_CERT_VALIDATION_FAILURE;
+
+    /**
      * Event severity level indicating that the event corresponds to normal workflow.
      */
     public static final int LEVEL_INFO = 1;
@@ -529,6 +558,7 @@
                 case TAG_USER_RESTRICTION_REMOVED:
                     return LEVEL_INFO;
                 case TAG_CERT_AUTHORITY_REMOVED:
+                case TAG_CRYPTO_SELF_TEST_COMPLETED:
                     return getSuccess() ? LEVEL_INFO : LEVEL_ERROR;
                 case TAG_CERT_AUTHORITY_INSTALLED:
                 case TAG_KEYGUARD_DISMISS_AUTH_ATTEMPT:
@@ -538,7 +568,10 @@
                     return getSuccess() ? LEVEL_INFO : LEVEL_WARNING;
                 case TAG_LOG_BUFFER_SIZE_CRITICAL:
                 case TAG_WIPE_FAILURE:
+                case TAG_KEY_INTEGRITY_VIOLATION:
                     return LEVEL_ERROR;
+                case TAG_CERT_VALIDATION_FAILURE:
+                    return LEVEL_WARNING;
                 default:
                     return LEVEL_INFO;
             }
diff --git a/core/java/android/app/admin/SecurityLogTags.logtags b/core/java/android/app/admin/SecurityLogTags.logtags
index be62678..fe2519d 100644
--- a/core/java/android/app/admin/SecurityLogTags.logtags
+++ b/core/java/android/app/admin/SecurityLogTags.logtags
@@ -34,4 +34,7 @@
 210027 security_user_restriction_added          (package|3),(admin_user|1),(restriction|3)
 210028 security_user_restriction_removed        (package|3),(admin_user|1),(restriction|3)
 210029 security_cert_authority_installed        (success|1),(subject|3)
-210030 security_cert_authority_removed          (success|1),(subject|3)
\ No newline at end of file
+210030 security_cert_authority_removed          (success|1),(subject|3)
+210031 security_crypto_self_test_completed      (success|1)
+210032 security_key_integrity_violation         (key_id|3),(uid|1)
+210033 security_cert_validation_failure         (reason|3)
diff --git a/core/java/android/app/admin/SystemUpdatePolicy.java b/core/java/android/app/admin/SystemUpdatePolicy.java
index 05d3fd9..47b3a81 100644
--- a/core/java/android/app/admin/SystemUpdatePolicy.java
+++ b/core/java/android/app/admin/SystemUpdatePolicy.java
@@ -21,6 +21,7 @@
 import static org.xmlpull.v1.XmlPullParser.TEXT;
 
 import android.annotation.IntDef;
+import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.Log;
@@ -33,9 +34,15 @@
 import java.io.IOException;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.time.Instant;
 import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.time.ZoneId;
 import java.util.ArrayList;
+import java.util.Calendar;
 import java.util.List;
+import java.util.concurrent.TimeUnit;
 import java.util.stream.Collectors;
 
 /**
@@ -103,6 +110,19 @@
      */
     public static final int TYPE_POSTPONE = 3;
 
+    /**
+     * Incoming system updates (including security updates) should be blocked. This flag is not
+     * exposed to third-party apps (and any attempt to set it will raise exceptions). This is used
+     * to represent the current installation option type to the privileged system update clients,
+     * for example to indicate OTA freeze is currently in place or when system is outside a daily
+     * maintenance window.
+     *
+     * @see InstallationOption
+     * @hide
+     */
+    @SystemApi
+    public static final int TYPE_PAUSE = 4;
+
     private static final String KEY_POLICY_TYPE = "policy_type";
     private static final String KEY_INSTALL_WINDOW_START = "install_window_start";
     private static final String KEY_INSTALL_WINDOW_END = "install_window_end";
@@ -460,6 +480,30 @@
         return null;
     }
 
+    /**
+     * Returns time (in milliseconds) until the start of the next freeze period, assuming now
+     * is not within a freeze period.
+     */
+    private long timeUntilNextFreezePeriod(long now) {
+        List<FreezeInterval> sortedPeriods = FreezeInterval.canonicalizeIntervals(mFreezePeriods);
+        LocalDate nowDate = millisToDate(now);
+        LocalDate nextFreezeStart = null;
+        for (FreezeInterval interval : sortedPeriods) {
+            if (interval.after(nowDate)) {
+                nextFreezeStart = interval.toCurrentOrFutureRealDates(nowDate).first;
+                break;
+            } else if (interval.contains(nowDate)) {
+                throw new IllegalArgumentException("Given date is inside a freeze period");
+            }
+        }
+        if (nextFreezeStart == null) {
+            // If no interval is after now, then it must be the one that starts at the beginning
+            // of next year
+            nextFreezeStart = sortedPeriods.get(0).toCurrentOrFutureRealDates(nowDate).first;
+        }
+        return dateToMillis(nextFreezeStart) - now;
+    }
+
     /** @hide */
     public void validateFreezePeriods() {
         FreezeInterval.validatePeriods(mFreezePeriods);
@@ -472,6 +516,134 @@
                 prevPeriodEnd, now);
     }
 
+    /**
+     * An installation option represents how system update clients should act on incoming system
+     * updates and how long this action is valid for, given the current system update policy. Its
+     * action could be one of the following
+     * <ul>
+     * <li> {@code TYPE_INSTALL_AUTOMATIC} system updates should be installed immedately and without
+     * user intervention as soon as they become available.
+     * <li> {@code TYPE_POSTPONE} system updates should be postponed for a maximum of 30 days
+     * <li> {@code TYPE_PAUSE} system updates should be postponed indefinitely until further notice
+     * </ul>
+     *
+     * The effective time measures how long this installation option is valid for from the queried
+     * time, in milliseconds.
+     *
+     * This is an internal API for system update clients.
+     * @hide
+     */
+    @SystemApi
+    public static class InstallationOption {
+        private final int mType;
+        private long mEffectiveTime;
+
+        InstallationOption(int type, long effectiveTime) {
+            this.mType = type;
+            this.mEffectiveTime = effectiveTime;
+        }
+
+        public int getType() {
+            return mType;
+        }
+
+        public long getEffectiveTime() {
+            return mEffectiveTime;
+        }
+
+        /** @hide */
+        protected void limitEffectiveTime(long otherTime) {
+            mEffectiveTime = Long.min(mEffectiveTime, otherTime);
+        }
+    }
+
+    /**
+     * Returns the installation option at the specified time, under the current
+     * {@code SystemUpdatePolicy} object. This is a convenience method for system update clients
+     * so they can instantiate this policy at any given time and find out what to do with incoming
+     * system updates, without the need of examining the overall policy structure.
+     *
+     * Normally the system update clients will query the current installation option by calling this
+     * method with the current timestamp, and act on the returned option until its effective time
+     * lapses. It can then query the latest option using a new timestamp. It should also listen
+     * for {@code DevicePolicyManager#ACTION_SYSTEM_UPDATE_POLICY_CHANGED} broadcast, in case the
+     * whole policy is updated.
+     *
+     * @param when At what time the intallation option is being queried, specified in number of
+           milliseonds since the epoch.
+     * @see InstallationOption
+     * @hide
+     */
+    @SystemApi
+    public InstallationOption getInstallationOptionAt(long when) {
+        LocalDate whenDate = millisToDate(when);
+        Pair<LocalDate, LocalDate> current = getCurrentFreezePeriod(whenDate);
+        if (current != null) {
+            return new InstallationOption(TYPE_PAUSE,
+                    dateToMillis(roundUpLeapDay(current.second).plusDays(1)) - when);
+        }
+        // We are not within a freeze period, query the underlying policy.
+        // But also consider the start of the next freeze period, which might
+        // reduce the effective time of the current installation option
+        InstallationOption option = getInstallationOptionRegardlessFreezeAt(when);
+        if (mFreezePeriods.size() > 0) {
+            option.limitEffectiveTime(timeUntilNextFreezePeriod(when));
+        }
+        return option;
+    }
+
+    private InstallationOption getInstallationOptionRegardlessFreezeAt(long when) {
+        if (mPolicyType == TYPE_INSTALL_AUTOMATIC || mPolicyType == TYPE_POSTPONE) {
+            return new InstallationOption(mPolicyType, Long.MAX_VALUE);
+        } else if (mPolicyType == TYPE_INSTALL_WINDOWED) {
+            Calendar query = Calendar.getInstance();
+            query.setTimeInMillis(when);
+            // Calculate the number of milliseconds since midnight of the time specified by when
+            long whenMillis = TimeUnit.HOURS.toMillis(query.get(Calendar.HOUR_OF_DAY))
+                    + TimeUnit.MINUTES.toMillis(query.get(Calendar.MINUTE))
+                    + TimeUnit.SECONDS.toMillis(query.get(Calendar.SECOND))
+                    + query.get(Calendar.MILLISECOND);
+            long windowStartMillis = TimeUnit.MINUTES.toMillis(mMaintenanceWindowStart);
+            long windowEndMillis = TimeUnit.MINUTES.toMillis(mMaintenanceWindowEnd);
+            final long dayInMillis = TimeUnit.DAYS.toMillis(1);
+
+            if ((windowStartMillis <= whenMillis && whenMillis <= windowEndMillis)
+                    || ((windowStartMillis > windowEndMillis)
+                    && (windowStartMillis <= whenMillis || whenMillis <= windowEndMillis))) {
+                return new InstallationOption(TYPE_INSTALL_AUTOMATIC,
+                        (windowEndMillis - whenMillis + dayInMillis) % dayInMillis);
+            } else {
+                return new InstallationOption(TYPE_PAUSE,
+                        (windowStartMillis - whenMillis + dayInMillis) % dayInMillis);
+            }
+        } else {
+            throw new RuntimeException("Unknown policy type");
+        }
+    }
+
+    private static LocalDate roundUpLeapDay(LocalDate date) {
+        if (date.isLeapYear() && date.getMonthValue() == 2 && date.getDayOfMonth() == 28) {
+            return date.plusDays(1);
+        } else {
+            return date;
+        }
+    }
+
+    /** Convert a timestamp since epoch to a LocalDate using default timezone, truncating
+     * the hour/min/seconds part.
+     */
+    private static LocalDate millisToDate(long when) {
+        return Instant.ofEpochMilli(when).atZone(ZoneId.systemDefault()).toLocalDate();
+    }
+
+    /**
+     * Returns the timestamp since epoch of a LocalDate, assuming the time is 00:00:00.
+     */
+    private static long dateToMillis(LocalDate when) {
+        return LocalDateTime.of(when, LocalTime.MIN).atZone(ZoneId.systemDefault()).toInstant()
+                .toEpochMilli();
+    }
+
     @Override
     public String toString() {
         return String.format("SystemUpdatePolicy (type: %d, windowStart: %d, windowEnd: %d, "
@@ -480,11 +652,13 @@
                 mFreezePeriods.stream().map(n -> n.toString()).collect(Collectors.joining(",")));
     }
 
+    @SystemApi
     @Override
     public int describeContents() {
         return 0;
     }
 
+    @SystemApi
     @Override
     public void writeToParcel(Parcel dest, int flags) {
         dest.writeInt(mPolicyType);
@@ -499,6 +673,7 @@
         }
     }
 
+    @SystemApi
     public static final Parcelable.Creator<SystemUpdatePolicy> CREATOR =
             new Parcelable.Creator<SystemUpdatePolicy>() {
 
diff --git a/core/java/android/app/assist/AssistStructure.java b/core/java/android/app/assist/AssistStructure.java
index 8f49bc1..1312a2e 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);
@@ -1299,6 +1303,17 @@
         }
 
         /**
+         * @hide
+         */
+        public void setWebDomain(@Nullable String domain) {
+            if (domain == null) return;
+
+            final Uri uri = Uri.parse(domain);
+            mWebScheme = uri.getScheme();
+            mWebDomain = uri.getHost();
+        }
+
+        /**
          * Returns the scheme of the HTML document represented by this view.
          *
          * <p>Typically used when the view associated with the view is a container for an HTML
@@ -1512,6 +1527,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 +1869,11 @@
         }
 
         @Override
+        public void setImportantForAutofill(@AutofillImportance int mode) {
+            mNode.mImportantForAutofill = mode;
+        }
+
+        @Override
         public void setInputType(int inputType) {
             mNode.mInputType = inputType;
         }
@@ -1870,14 +1900,7 @@
 
         @Override
         public void setWebDomain(@Nullable String domain) {
-            if (domain == null) {
-                mNode.mWebScheme = null;
-                mNode.mWebDomain = null;
-                return;
-            }
-            Uri uri = Uri.parse(domain);
-            mNode.mWebScheme = uri.getScheme();
-            mNode.mWebDomain = uri.getHost();
+            mNode.setWebDomain(domain);
         }
 
         @Override
@@ -2144,7 +2167,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/backup/BackupAgent.java b/core/java/android/app/backup/BackupAgent.java
index 72eb494..d36a794 100644
--- a/core/java/android/app/backup/BackupAgent.java
+++ b/core/java/android/app/backup/BackupAgent.java
@@ -163,6 +163,16 @@
      */
     public static final int FLAG_DEVICE_TO_DEVICE_TRANSFER = 2;
 
+    /**
+     * Flag for {@link BackupDataOutput#getTransportFlags()} and
+     * {@link FullBackupDataOutput#getTransportFlags()} only.
+     *
+     * <p>Used for internal testing only. Do not check this flag in production code.
+     *
+     * @hide
+     */
+    public static final int FLAG_FAKE_CLIENT_SIDE_ENCRYPTION_ENABLED = 1 << 31;
+
     Handler mHandler = null;
 
     Handler getHandler() {
diff --git a/core/java/android/app/backup/OWNERS b/core/java/android/app/backup/OWNERS
new file mode 100644
index 0000000..1c9a43a
--- /dev/null
+++ b/core/java/android/app/backup/OWNERS
@@ -0,0 +1,7 @@
+artikz@google.com
+brufino@google.com
+bryanmawhinney@google.com
+ctate@google.com
+jorlow@google.com
+mkarpinski@google.com
+
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/servertransaction/ActivityLifecycleItem.java b/core/java/android/app/servertransaction/ActivityLifecycleItem.java
index 9a50a00..7f8c50c 100644
--- a/core/java/android/app/servertransaction/ActivityLifecycleItem.java
+++ b/core/java/android/app/servertransaction/ActivityLifecycleItem.java
@@ -91,4 +91,9 @@
         pw.println(prefix + "target state:" + getTargetState());
         pw.println(prefix + "description: " + mDescription);
     }
+
+    @Override
+    public void recycle() {
+        setDescription(null);
+    }
 }
diff --git a/core/java/android/app/servertransaction/ActivityRelaunchItem.java b/core/java/android/app/servertransaction/ActivityRelaunchItem.java
new file mode 100644
index 0000000..d8a7463
--- /dev/null
+++ b/core/java/android/app/servertransaction/ActivityRelaunchItem.java
@@ -0,0 +1,176 @@
+/*
+ * Copyright 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.app.servertransaction;
+
+import static android.app.ActivityThread.DEBUG_ORDER;
+
+import android.app.ActivityThread;
+import android.app.ClientTransactionHandler;
+import android.app.ResultInfo;
+import android.os.IBinder;
+import android.os.Parcel;
+import android.os.Trace;
+import android.util.MergedConfiguration;
+import android.util.Slog;
+
+import com.android.internal.content.ReferrerIntent;
+
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * Activity relaunch callback.
+ * @hide
+ */
+public class ActivityRelaunchItem extends ClientTransactionItem {
+
+    private static final String TAG = "ActivityRelaunchItem";
+
+    private List<ResultInfo> mPendingResults;
+    private List<ReferrerIntent> mPendingNewIntents;
+    private int mConfigChanges;
+    private MergedConfiguration mConfig;
+    private boolean mPreserveWindow;
+
+    /**
+     * A record that was properly configured for relaunch. Execution will be cancelled if not
+     * initialized after {@link #preExecute(ClientTransactionHandler, IBinder)}.
+     */
+    private ActivityThread.ActivityClientRecord mActivityClientRecord;
+
+    @Override
+    public void preExecute(ClientTransactionHandler client, IBinder token) {
+        mActivityClientRecord = client.prepareRelaunchActivity(token, mPendingResults,
+                mPendingNewIntents, mConfigChanges, mConfig, mPreserveWindow);
+    }
+
+    @Override
+    public void execute(ClientTransactionHandler client, IBinder token,
+            PendingTransactionActions pendingActions) {
+        if (mActivityClientRecord == null) {
+            if (DEBUG_ORDER) Slog.d(TAG, "Activity relaunch cancelled");
+            return;
+        }
+        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityRestart");
+        client.handleRelaunchActivity(mActivityClientRecord, pendingActions);
+        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
+    }
+
+    @Override
+    public void postExecute(ClientTransactionHandler client, IBinder token,
+            PendingTransactionActions pendingActions) {
+        client.reportRelaunch(token, pendingActions);
+    }
+
+    // ObjectPoolItem implementation
+
+    private ActivityRelaunchItem() {}
+
+    /** Obtain an instance initialized with provided params. */
+    public static ActivityRelaunchItem obtain(List<ResultInfo> pendingResults,
+            List<ReferrerIntent> pendingNewIntents, int configChanges, MergedConfiguration config,
+            boolean preserveWindow) {
+        ActivityRelaunchItem instance = ObjectPool.obtain(ActivityRelaunchItem.class);
+        if (instance == null) {
+            instance = new ActivityRelaunchItem();
+        }
+        instance.mPendingResults = pendingResults;
+        instance.mPendingNewIntents = pendingNewIntents;
+        instance.mConfigChanges = configChanges;
+        instance.mConfig = config;
+        instance.mPreserveWindow = preserveWindow;
+
+        return instance;
+    }
+
+    @Override
+    public void recycle() {
+        mPendingResults = null;
+        mPendingNewIntents = null;
+        mConfigChanges = 0;
+        mConfig = null;
+        mPreserveWindow = false;
+        mActivityClientRecord = null;
+        ObjectPool.recycle(this);
+    }
+
+
+    // Parcelable implementation
+
+    /** Write to Parcel. */
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeTypedList(mPendingResults, flags);
+        dest.writeTypedList(mPendingNewIntents, flags);
+        dest.writeInt(mConfigChanges);
+        dest.writeTypedObject(mConfig, flags);
+        dest.writeBoolean(mPreserveWindow);
+    }
+
+    /** Read from Parcel. */
+    private ActivityRelaunchItem(Parcel in) {
+        mPendingResults = in.createTypedArrayList(ResultInfo.CREATOR);
+        mPendingNewIntents = in.createTypedArrayList(ReferrerIntent.CREATOR);
+        mConfigChanges = in.readInt();
+        mConfig = in.readTypedObject(MergedConfiguration.CREATOR);
+        mPreserveWindow = in.readBoolean();
+    }
+
+    public static final Creator<ActivityRelaunchItem> CREATOR =
+            new Creator<ActivityRelaunchItem>() {
+                public ActivityRelaunchItem createFromParcel(Parcel in) {
+                    return new ActivityRelaunchItem(in);
+                }
+
+                public ActivityRelaunchItem[] newArray(int size) {
+                    return new ActivityRelaunchItem[size];
+                }
+            };
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+        final ActivityRelaunchItem other = (ActivityRelaunchItem) o;
+        return Objects.equals(mPendingResults, other.mPendingResults)
+                && Objects.equals(mPendingNewIntents, other.mPendingNewIntents)
+                && mConfigChanges == other.mConfigChanges && Objects.equals(mConfig, other.mConfig)
+                && mPreserveWindow == other.mPreserveWindow;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = 17;
+        result = 31 * result + Objects.hashCode(mPendingResults);
+        result = 31 * result + Objects.hashCode(mPendingNewIntents);
+        result = 31 * result + mConfigChanges;
+        result = 31 * result + Objects.hashCode(mConfig);
+        result = 31 * result + (mPreserveWindow ? 1 : 0);
+        return result;
+    }
+
+    @Override
+    public String toString() {
+        return "ActivityRelaunchItem{pendingResults=" + mPendingResults
+                + ",pendingNewIntents=" + mPendingNewIntents + ",configChanges="  + mConfigChanges
+                + ",config=" + mConfig + ",preserveWindow" + mPreserveWindow + "}";
+    }
+}
diff --git a/core/java/android/app/servertransaction/DestroyActivityItem.java b/core/java/android/app/servertransaction/DestroyActivityItem.java
index cbcf6c7..0edcf18 100644
--- a/core/java/android/app/servertransaction/DestroyActivityItem.java
+++ b/core/java/android/app/servertransaction/DestroyActivityItem.java
@@ -37,7 +37,7 @@
             PendingTransactionActions pendingActions) {
         Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityDestroy");
         client.handleDestroyActivity(token, mFinished, mConfigChanges,
-                false /* getNonConfigInstance */);
+                false /* getNonConfigInstance */, getDescription());
         Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
     }
 
@@ -65,6 +65,7 @@
 
     @Override
     public void recycle() {
+        super.recycle();
         mFinished = false;
         mConfigChanges = 0;
         ObjectPool.recycle(this);
diff --git a/core/java/android/app/servertransaction/PauseActivityItem.java b/core/java/android/app/servertransaction/PauseActivityItem.java
index 70a4755..91e73cd 100644
--- a/core/java/android/app/servertransaction/PauseActivityItem.java
+++ b/core/java/android/app/servertransaction/PauseActivityItem.java
@@ -102,6 +102,7 @@
 
     @Override
     public void recycle() {
+        super.recycle();
         mFinished = false;
         mUserLeaving = false;
         mConfigChanges = 0;
diff --git a/core/java/android/app/servertransaction/PendingTransactionActions.java b/core/java/android/app/servertransaction/PendingTransactionActions.java
index 073d28c..af7b7a2 100644
--- a/core/java/android/app/servertransaction/PendingTransactionActions.java
+++ b/core/java/android/app/servertransaction/PendingTransactionActions.java
@@ -44,6 +44,7 @@
     private boolean mCallOnPostCreate;
     private Bundle mOldState;
     private StopInfo mStopInfo;
+    private boolean mReportRelaunchToWM;
 
     public PendingTransactionActions() {
         clear();
@@ -91,6 +92,24 @@
         mStopInfo = stopInfo;
     }
 
+    /**
+     * Check if we should report an activity relaunch to WindowManager. We report back for every
+     * relaunch request to ActivityManager, but only for those that were actually finished to we
+     * report to WindowManager.
+     */
+    public boolean shouldReportRelaunchToWindowManager() {
+        return mReportRelaunchToWM;
+    }
+
+    /**
+     * Set if we should report an activity relaunch to WindowManager. We report back for every
+     * relaunch request to ActivityManager, but only for those that were actually finished we report
+     * to WindowManager.
+     */
+    public void setReportRelaunchToWindowManager(boolean reportToWm) {
+        mReportRelaunchToWM = reportToWm;
+    }
+
     /** Reports to server about activity stop. */
     public static class StopInfo implements Runnable {
         private static final String TAG = "ActivityStopInfo";
diff --git a/core/java/android/app/servertransaction/ResumeActivityItem.java b/core/java/android/app/servertransaction/ResumeActivityItem.java
index ed90f2c..af2fb71 100644
--- a/core/java/android/app/servertransaction/ResumeActivityItem.java
+++ b/core/java/android/app/servertransaction/ResumeActivityItem.java
@@ -101,6 +101,7 @@
 
     @Override
     public void recycle() {
+        super.recycle();
         mProcState = ActivityManager.PROCESS_STATE_UNKNOWN;
         mUpdateProcState = false;
         mIsForward = false;
diff --git a/core/java/android/app/servertransaction/StopActivityItem.java b/core/java/android/app/servertransaction/StopActivityItem.java
index b814d1a..f955a90 100644
--- a/core/java/android/app/servertransaction/StopActivityItem.java
+++ b/core/java/android/app/servertransaction/StopActivityItem.java
@@ -72,6 +72,7 @@
 
     @Override
     public void recycle() {
+        super.recycle();
         mShowWindow = false;
         mConfigChanges = 0;
         ObjectPool.recycle(this);
diff --git a/core/java/android/app/servertransaction/TransactionExecutor.java b/core/java/android/app/servertransaction/TransactionExecutor.java
index 78b393a..840fef8 100644
--- a/core/java/android/app/servertransaction/TransactionExecutor.java
+++ b/core/java/android/app/servertransaction/TransactionExecutor.java
@@ -194,7 +194,9 @@
                     break;
                 case ON_DESTROY:
                     mTransactionHandler.handleDestroyActivity(r.token, false /* finishing */,
-                            0 /* configChanges */, false /* getNonConfigInstance */);
+                            0 /* configChanges */, false /* getNonConfigInstance */,
+                            "performLifecycleSequence. cycling to:"
+                                    + mLifecycleSequence.get(size - 1));
                     break;
                 case ON_RESTART:
                     mTransactionHandler.performRestartActivity(r.token, false /* start */);
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/app/usage/UsageEvents.java b/core/java/android/app/usage/UsageEvents.java
index edb992b..6b573e9 100644
--- a/core/java/android/app/usage/UsageEvents.java
+++ b/core/java/android/app/usage/UsageEvents.java
@@ -16,6 +16,7 @@
 package android.app.usage;
 
 import android.annotation.IntDef;
+import android.annotation.SystemApi;
 import android.content.res.Configuration;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -104,12 +105,14 @@
          * An event type denoting that a notification was viewed by the user.
          * @hide
          */
+        @SystemApi
         public static final int NOTIFICATION_SEEN = 10;
 
         /**
          * An event type denoting a change in App Standby Bucket.
          * @hide
          */
+        @SystemApi
         public static final int STANDBY_BUCKET_CHANGED = 11;
 
         /** @hide */
@@ -257,6 +260,17 @@
             return mShortcutId;
         }
 
+        /**
+         * Returns the standby bucket of the app, if the event is of type
+         * {@link #STANDBY_BUCKET_CHANGED}, otherwise returns 0.
+         * @return the standby bucket associated with the event.
+         * @hide
+         */
+        @SystemApi
+        public int getStandbyBucket() {
+            return mBucket;
+        }
+
         /** @hide */
         public Event getObfuscatedIfInstantApp() {
             if ((mFlags & FLAG_IS_PACKAGE_INSTANT_APP) == 0) {
diff --git a/core/java/android/appwidget/AppWidgetManager.java b/core/java/android/appwidget/AppWidgetManager.java
index a2c75a6..e736f34 100644
--- a/core/java/android/appwidget/AppWidgetManager.java
+++ b/core/java/android/appwidget/AppWidgetManager.java
@@ -19,6 +19,7 @@
 import android.annotation.BroadcastBehavior;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.RequiresFeature;
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.annotation.SystemService;
@@ -29,6 +30,7 @@
 import android.content.Intent;
 import android.content.IntentSender;
 import android.content.ServiceConnection;
+import android.content.pm.PackageManager;
 import android.content.pm.ParceledListSlice;
 import android.content.pm.ShortcutInfo;
 import android.os.Bundle;
@@ -55,6 +57,7 @@
  * </div>
  */
 @SystemService(Context.APPWIDGET_SERVICE)
+@RequiresFeature(PackageManager.FEATURE_APP_WIDGETS)
 public class AppWidgetManager {
 
     /**
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index bc7823b..1dc7549 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -2307,6 +2307,9 @@
         } else if (profile == BluetoothProfile.HID_DEVICE) {
             BluetoothHidDevice hidDevice = new BluetoothHidDevice(context, listener);
             return true;
+        } else if (profile == BluetoothProfile.HEARING_AID) {
+            BluetoothHearingAid hearingAid = new BluetoothHearingAid(context, listener);
+            return true;
         } else {
             return false;
         }
@@ -2389,6 +2392,9 @@
                 BluetoothHidDevice hidDevice = (BluetoothHidDevice) proxy;
                 hidDevice.close();
                 break;
+            case BluetoothProfile.HEARING_AID:
+                BluetoothHearingAid hearingAid = (BluetoothHearingAid) proxy;
+                hearingAid.close();
         }
     }
 
diff --git a/core/java/android/bluetooth/BluetoothHearingAid.java b/core/java/android/bluetooth/BluetoothHearingAid.java
new file mode 100644
index 0000000..647e0d0
--- /dev/null
+++ b/core/java/android/bluetooth/BluetoothHearingAid.java
@@ -0,0 +1,693 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth;
+
+import android.Manifest;
+import android.annotation.RequiresPermission;
+import android.annotation.SdkConstant;
+import android.annotation.SdkConstant.SdkConstantType;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.Binder;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Log;
+
+import com.android.internal.annotations.GuardedBy;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+/**
+ * This class provides the public APIs to control the Bluetooth Hearing Aid
+ * profile.
+ *
+ * <p>BluetoothHearingAid is a proxy object for controlling the Bluetooth Hearing Aid
+ * Service via IPC. Use {@link BluetoothAdapter#getProfileProxy} to get
+ * the BluetoothHearingAid proxy object.
+ *
+ * <p> Each method is protected with its appropriate permission.
+ * @hide
+ */
+public final class BluetoothHearingAid implements BluetoothProfile {
+    private static final String TAG = "BluetoothHearingAid";
+    private static final boolean DBG = false;
+    private static final boolean VDBG = false;
+
+    /**
+     * Intent used to broadcast the change in connection state of the Hearing Aid
+     * profile.
+     *
+     * <p>This intent will have 3 extras:
+     * <ul>
+     * <li> {@link #EXTRA_STATE} - The current state of the profile. </li>
+     * <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile.</li>
+     * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li>
+     * </ul>
+     *
+     * <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of
+     * {@link #STATE_DISCONNECTED}, {@link #STATE_CONNECTING},
+     * {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTING}.
+     *
+     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to
+     * receive.
+     */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_CONNECTION_STATE_CHANGED =
+            "android.bluetooth.hearingaid.profile.action.CONNECTION_STATE_CHANGED";
+
+    /**
+     * Intent used to broadcast the change in the Playing state of the Hearing Aid
+     * profile.
+     *
+     * <p>This intent will have 3 extras:
+     * <ul>
+     * <li> {@link #EXTRA_STATE} - The current state of the profile. </li>
+     * <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile. </li>
+     * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li>
+     * </ul>
+     *
+     * <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of
+     * {@link #STATE_PLAYING}, {@link #STATE_NOT_PLAYING},
+     *
+     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to
+     * receive.
+     */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_PLAYING_STATE_CHANGED =
+            "android.bluetooth.hearingaid.profile.action.PLAYING_STATE_CHANGED";
+
+    /**
+     * Intent used to broadcast the selection of a connected device as active.
+     *
+     * <p>This intent will have one extra:
+     * <ul>
+     * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. It can
+     * be null if no device is active. </li>
+     * </ul>
+     *
+     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to
+     * receive.
+     */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_ACTIVE_DEVICE_CHANGED =
+            "android.bluetooth.hearingaid.profile.action.ACTIVE_DEVICE_CHANGED";
+
+    /**
+     * Hearing Aid device is streaming music. This state can be one of
+     * {@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} of
+     * {@link #ACTION_PLAYING_STATE_CHANGED} intent.
+     */
+    public static final int STATE_PLAYING = 10;
+
+    /**
+     * Hearing Aid device is NOT streaming music. This state can be one of
+     * {@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} of
+     * {@link #ACTION_PLAYING_STATE_CHANGED} intent.
+     */
+    public static final int STATE_NOT_PLAYING = 11;
+
+    /** This device represents Left Hearing Aid. */
+    public static final int SIDE_LEFT = IBluetoothHearingAid.SIDE_LEFT;
+
+    /** This device represents Right Hearing Aid. */
+    public static final int SIDE_RIGHT = IBluetoothHearingAid.SIDE_RIGHT;
+
+    /** This device is Monaural. */
+    public static final int MODE_MONAURAL = IBluetoothHearingAid.MODE_MONAURAL;
+
+    /** This device is Binaural (should receive only left or right audio). */
+    public static final int MODE_BINAURAL = IBluetoothHearingAid.MODE_BINAURAL;
+
+    /** Can't read ClientID for this device */
+    public static final long HI_SYNC_ID_INVALID = IBluetoothHearingAid.HI_SYNC_ID_INVALID;
+
+    private Context mContext;
+    private ServiceListener mServiceListener;
+    private final ReentrantReadWriteLock mServiceLock = new ReentrantReadWriteLock();
+    @GuardedBy("mServiceLock")
+    private IBluetoothHearingAid mService;
+    private BluetoothAdapter mAdapter;
+
+    private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
+            new IBluetoothStateChangeCallback.Stub() {
+                public void onBluetoothStateChange(boolean up) {
+                    if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up);
+                    if (!up) {
+                        if (VDBG) Log.d(TAG, "Unbinding service...");
+                        try {
+                            mServiceLock.writeLock().lock();
+                            mService = null;
+                            mContext.unbindService(mConnection);
+                        } catch (Exception re) {
+                            Log.e(TAG, "", re);
+                        } finally {
+                            mServiceLock.writeLock().unlock();
+                        }
+                    } else {
+                        try {
+                            mServiceLock.readLock().lock();
+                            if (mService == null) {
+                                if (VDBG) Log.d(TAG, "Binding service...");
+                                doBind();
+                            }
+                        } catch (Exception re) {
+                            Log.e(TAG, "", re);
+                        } finally {
+                            mServiceLock.readLock().unlock();
+                        }
+                    }
+                }
+            };
+
+    /**
+     * Create a BluetoothHearingAid proxy object for interacting with the local
+     * Bluetooth Hearing Aid service.
+     */
+    /*package*/ BluetoothHearingAid(Context context, ServiceListener l) {
+        mContext = context;
+        mServiceListener = l;
+        mAdapter = BluetoothAdapter.getDefaultAdapter();
+        IBluetoothManager mgr = mAdapter.getBluetoothManager();
+        if (mgr != null) {
+            try {
+                mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
+            } catch (RemoteException e) {
+                Log.e(TAG, "", e);
+            }
+        }
+
+        doBind();
+    }
+
+    void doBind() {
+        Intent intent = new Intent(IBluetoothHearingAid.class.getName());
+        ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
+        intent.setComponent(comp);
+        if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
+                android.os.Process.myUserHandle())) {
+            Log.e(TAG, "Could not bind to Bluetooth Hearing Aid Service with " + intent);
+            return;
+        }
+    }
+
+    /*package*/ void close() {
+        mServiceListener = null;
+        IBluetoothManager mgr = mAdapter.getBluetoothManager();
+        if (mgr != null) {
+            try {
+                mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
+            } catch (Exception e) {
+                Log.e(TAG, "", e);
+            }
+        }
+
+        try {
+            mServiceLock.writeLock().lock();
+            if (mService != null) {
+                mService = null;
+                mContext.unbindService(mConnection);
+            }
+        } catch (Exception re) {
+            Log.e(TAG, "", re);
+        } finally {
+            mServiceLock.writeLock().unlock();
+        }
+    }
+
+    @Override
+    public void finalize() {
+        // The empty finalize needs to be kept or the
+        // cts signature tests would fail.
+    }
+
+    /**
+     * Initiate connection to a profile of the remote bluetooth device.
+     *
+     * <p> This API returns false in scenarios like the profile on the
+     * device is already connected or Bluetooth is not turned on.
+     * When this API returns true, it is guaranteed that
+     * connection state intent for the profile will be broadcasted with
+     * the state. Users can get the connection state of the profile
+     * from this intent.
+     *
+     * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
+     * permission.
+     *
+     * @param device Remote Bluetooth Device
+     * @return false on immediate error, true otherwise
+     * @hide
+     */
+    public boolean connect(BluetoothDevice device) {
+        if (DBG) log("connect(" + device + ")");
+        try {
+            mServiceLock.readLock().lock();
+            if (mService != null && isEnabled() && isValidDevice(device)) {
+                return mService.connect(device);
+            }
+            if (mService == null) Log.w(TAG, "Proxy not attached to service");
+            return false;
+        } catch (RemoteException e) {
+            Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+            return false;
+        } finally {
+            mServiceLock.readLock().unlock();
+        }
+    }
+
+    /**
+     * Initiate disconnection from a profile
+     *
+     * <p> This API will return false in scenarios like the profile on the
+     * Bluetooth device is not in connected state etc. When this API returns,
+     * true, it is guaranteed that the connection state change
+     * intent will be broadcasted with the state. Users can get the
+     * disconnection state of the profile from this intent.
+     *
+     * <p> If the disconnection is initiated by a remote device, the state
+     * will transition from {@link #STATE_CONNECTED} to
+     * {@link #STATE_DISCONNECTED}. If the disconnect is initiated by the
+     * host (local) device the state will transition from
+     * {@link #STATE_CONNECTED} to state {@link #STATE_DISCONNECTING} to
+     * state {@link #STATE_DISCONNECTED}. The transition to
+     * {@link #STATE_DISCONNECTING} can be used to distinguish between the
+     * two scenarios.
+     *
+     * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
+     * permission.
+     *
+     * @param device Remote Bluetooth Device
+     * @return false on immediate error, true otherwise
+     * @hide
+     */
+    public boolean disconnect(BluetoothDevice device) {
+        if (DBG) log("disconnect(" + device + ")");
+        try {
+            mServiceLock.readLock().lock();
+            if (mService != null && isEnabled() && isValidDevice(device)) {
+                return mService.disconnect(device);
+            }
+            if (mService == null) Log.w(TAG, "Proxy not attached to service");
+            return false;
+        } catch (RemoteException e) {
+            Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+            return false;
+        } finally {
+            mServiceLock.readLock().unlock();
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public List<BluetoothDevice> getConnectedDevices() {
+        if (VDBG) log("getConnectedDevices()");
+        try {
+            mServiceLock.readLock().lock();
+            if (mService != null && isEnabled()) {
+                return mService.getConnectedDevices();
+            }
+            if (mService == null) Log.w(TAG, "Proxy not attached to service");
+            return new ArrayList<BluetoothDevice>();
+        } catch (RemoteException e) {
+            Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+            return new ArrayList<BluetoothDevice>();
+        } finally {
+            mServiceLock.readLock().unlock();
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
+        if (VDBG) log("getDevicesMatchingStates()");
+        try {
+            mServiceLock.readLock().lock();
+            if (mService != null && isEnabled()) {
+                return mService.getDevicesMatchingConnectionStates(states);
+            }
+            if (mService == null) Log.w(TAG, "Proxy not attached to service");
+            return new ArrayList<BluetoothDevice>();
+        } catch (RemoteException e) {
+            Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+            return new ArrayList<BluetoothDevice>();
+        } finally {
+            mServiceLock.readLock().unlock();
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public int getConnectionState(BluetoothDevice device) {
+        if (VDBG) log("getState(" + device + ")");
+        try {
+            mServiceLock.readLock().lock();
+            if (mService != null && isEnabled()
+                    && isValidDevice(device)) {
+                return mService.getConnectionState(device);
+            }
+            if (mService == null) Log.w(TAG, "Proxy not attached to service");
+            return BluetoothProfile.STATE_DISCONNECTED;
+        } catch (RemoteException e) {
+            Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+            return BluetoothProfile.STATE_DISCONNECTED;
+        } finally {
+            mServiceLock.readLock().unlock();
+        }
+    }
+
+    /**
+     * Set priority of the profile
+     *
+     * <p> The device should already be paired.
+     * Priority can be one of {@link #PRIORITY_ON} orgetBluetoothManager
+     * {@link #PRIORITY_OFF},
+     *
+     * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
+     * permission.
+     *
+     * @param device Paired bluetooth device
+     * @param priority
+     * @return true if priority is set, false on error
+     * @hide
+     */
+    public boolean setPriority(BluetoothDevice device, int priority) {
+        if (DBG) log("setPriority(" + device + ", " + priority + ")");
+        try {
+            mServiceLock.readLock().lock();
+            if (mService != null && isEnabled()
+                    && isValidDevice(device)) {
+                if (priority != BluetoothProfile.PRIORITY_OFF
+                        && priority != BluetoothProfile.PRIORITY_ON) {
+                    return false;
+                }
+                return mService.setPriority(device, priority);
+            }
+            if (mService == null) Log.w(TAG, "Proxy not attached to service");
+            return false;
+        } catch (RemoteException e) {
+            Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+            return false;
+        } finally {
+            mServiceLock.readLock().unlock();
+        }
+    }
+
+    /**
+     * Get the priority of the profile.
+     *
+     * <p> The priority can be any of:
+     * {@link #PRIORITY_AUTO_CONNECT}, {@link #PRIORITY_OFF},
+     * {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED}
+     *
+     * @param device Bluetooth device
+     * @return priority of the device
+     * @hide
+     */
+    @RequiresPermission(Manifest.permission.BLUETOOTH)
+    public int getPriority(BluetoothDevice device) {
+        if (VDBG) log("getPriority(" + device + ")");
+        try {
+            mServiceLock.readLock().lock();
+            if (mService != null && isEnabled()
+                    && isValidDevice(device)) {
+                return mService.getPriority(device);
+            }
+            if (mService == null) Log.w(TAG, "Proxy not attached to service");
+            return BluetoothProfile.PRIORITY_OFF;
+        } catch (RemoteException e) {
+            Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+            return BluetoothProfile.PRIORITY_OFF;
+        } finally {
+            mServiceLock.readLock().unlock();
+        }
+    }
+
+    /**
+     * Helper for converting a state to a string.
+     *
+     * For debug use only - strings are not internationalized.
+     *
+     * @hide
+     */
+    public static String stateToString(int state) {
+        switch (state) {
+            case STATE_DISCONNECTED:
+                return "disconnected";
+            case STATE_CONNECTING:
+                return "connecting";
+            case STATE_CONNECTED:
+                return "connected";
+            case STATE_DISCONNECTING:
+                return "disconnecting";
+            case STATE_PLAYING:
+                return "playing";
+            case STATE_NOT_PLAYING:
+                return "not playing";
+            default:
+                return "<unknown state " + state + ">";
+        }
+    }
+
+    /**
+     * Get the volume of the device.
+     *
+     * <p> The volume is between -128 dB (mute) to 0 dB.
+     *
+     * @return volume of the hearing aid device.
+     * @hide
+     */
+    @RequiresPermission(Manifest.permission.BLUETOOTH)
+    public int getVolume() {
+        if (VDBG) {
+            log("getVolume()");
+        }
+        try {
+            mServiceLock.readLock().lock();
+            if (mService != null && isEnabled()) {
+                return mService.getVolume();
+            }
+            if (mService == null) Log.w(TAG, "Proxy not attached to service");
+            return 0;
+        } catch (RemoteException e) {
+            Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+            return 0;
+        } finally {
+            mServiceLock.readLock().unlock();
+        }
+    }
+
+    /**
+     * Tells remote device to adjust volume. Uses the following values:
+     * <ul>
+     * <li>{@link AudioManager#ADJUST_LOWER}</li>
+     * <li>{@link AudioManager#ADJUST_RAISE}</li>
+     * <li>{@link AudioManager#ADJUST_MUTE}</li>
+     * <li>{@link AudioManager#ADJUST_UNMUTE}</li>
+     * </ul>
+     *
+     * @param direction One of the supported adjust values.
+     * @hide
+     */
+    @RequiresPermission(Manifest.permission.BLUETOOTH)
+    public void adjustVolume(int direction) {
+        if (DBG) log("adjustVolume(" + direction + ")");
+
+        try {
+            mServiceLock.readLock().lock();
+
+            if (mService == null) {
+                Log.w(TAG, "Proxy not attached to service");
+                return;
+            }
+
+            if (!isEnabled()) return;
+
+            mService.adjustVolume(direction);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+        } finally {
+            mServiceLock.readLock().unlock();
+        }
+    }
+
+    /**
+     * Tells remote device to set an absolute volume.
+     *
+     * @param volume Absolute volume to be set on remote
+     * @hide
+     */
+    public void setVolume(int volume) {
+        if (DBG) Log.d(TAG, "setVolume(" + volume + ")");
+
+        try {
+            mServiceLock.readLock().lock();
+            if (mService == null) {
+                Log.w(TAG, "Proxy not attached to service");
+                return;
+            }
+
+            if (!isEnabled()) return;
+
+            mService.setVolume(volume);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+        } finally {
+            mServiceLock.readLock().unlock();
+        }
+    }
+
+    /**
+     * Get the CustomerId of the device.
+     *
+     * @param device Bluetooth device
+     * @return the CustomerId of the device
+     * @hide
+     */
+    @RequiresPermission(Manifest.permission.BLUETOOTH)
+    public long getHiSyncId(BluetoothDevice device) {
+        if (VDBG) {
+            log("getCustomerId(" + device + ")");
+        }
+        try {
+            mServiceLock.readLock().lock();
+            if (mService == null) {
+                Log.w(TAG, "Proxy not attached to service");
+                return HI_SYNC_ID_INVALID;
+            }
+
+            if (!isEnabled() || !isValidDevice(device)) return HI_SYNC_ID_INVALID;
+
+            return mService.getHiSyncId(device);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+            return HI_SYNC_ID_INVALID;
+        } finally {
+            mServiceLock.readLock().unlock();
+        }
+    }
+
+    /**
+     * Get the side of the device.
+     *
+     * @param device Bluetooth device.
+     * @return SIDE_LEFT or SIDE_RIGHT
+     * @hide
+     */
+    @RequiresPermission(Manifest.permission.BLUETOOTH)
+    public int getDeviceSide(BluetoothDevice device) {
+        if (VDBG) {
+            log("getDeviceSide(" + device + ")");
+        }
+        try {
+            mServiceLock.readLock().lock();
+            if (mService != null && isEnabled()
+                    && isValidDevice(device)) {
+                return mService.getDeviceSide(device);
+            }
+            if (mService == null) Log.w(TAG, "Proxy not attached to service");
+            return SIDE_LEFT;
+        } catch (RemoteException e) {
+            Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+            return SIDE_LEFT;
+        } finally {
+            mServiceLock.readLock().unlock();
+        }
+    }
+
+    /**
+     * Get the mode of the device.
+     *
+     * @param device Bluetooth device
+     * @return MODE_MONAURAL or MODE_BINAURAL
+     * @hide
+     */
+    @RequiresPermission(Manifest.permission.BLUETOOTH)
+    public int getDeviceMode(BluetoothDevice device) {
+        if (VDBG) {
+            log("getDeviceMode(" + device + ")");
+        }
+        try {
+            mServiceLock.readLock().lock();
+            if (mService != null && isEnabled()
+                    && isValidDevice(device)) {
+                return mService.getDeviceMode(device);
+            }
+            if (mService == null) Log.w(TAG, "Proxy not attached to service");
+            return MODE_MONAURAL;
+        } catch (RemoteException e) {
+            Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+            return MODE_MONAURAL;
+        } finally {
+            mServiceLock.readLock().unlock();
+        }
+    }
+
+    private final ServiceConnection mConnection = new ServiceConnection() {
+        public void onServiceConnected(ComponentName className, IBinder service) {
+            if (DBG) Log.d(TAG, "Proxy object connected");
+            try {
+                mServiceLock.writeLock().lock();
+                mService = IBluetoothHearingAid.Stub.asInterface(Binder.allowBlocking(service));
+            } finally {
+                mServiceLock.writeLock().unlock();
+            }
+
+            if (mServiceListener != null) {
+                mServiceListener.onServiceConnected(BluetoothProfile.HEARING_AID,
+                                                    BluetoothHearingAid.this);
+            }
+        }
+
+        public void onServiceDisconnected(ComponentName className) {
+            if (DBG) Log.d(TAG, "Proxy object disconnected");
+            try {
+                mServiceLock.writeLock().lock();
+                mService = null;
+            } finally {
+                mServiceLock.writeLock().unlock();
+            }
+            if (mServiceListener != null) {
+                mServiceListener.onServiceDisconnected(BluetoothProfile.HEARING_AID);
+            }
+        }
+    };
+
+    private boolean isEnabled() {
+        if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true;
+        return false;
+    }
+
+    private boolean isValidDevice(BluetoothDevice device) {
+        if (device == null) return false;
+
+        if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true;
+        return false;
+    }
+
+    private static void log(String msg) {
+        Log.d(TAG, msg);
+    }
+}
diff --git a/core/java/android/bluetooth/BluetoothManager.java b/core/java/android/bluetooth/BluetoothManager.java
index 7e3bb05..11f8ab7 100644
--- a/core/java/android/bluetooth/BluetoothManager.java
+++ b/core/java/android/bluetooth/BluetoothManager.java
@@ -17,9 +17,11 @@
 package android.bluetooth;
 
 import android.Manifest;
+import android.annotation.RequiresFeature;
 import android.annotation.RequiresPermission;
 import android.annotation.SystemService;
 import android.content.Context;
+import android.content.pm.PackageManager;
 import android.os.RemoteException;
 import android.util.Log;
 
@@ -47,6 +49,7 @@
  * @see BluetoothAdapter#getDefaultAdapter()
  */
 @SystemService(Context.BLUETOOTH_SERVICE)
+@RequiresFeature(PackageManager.FEATURE_BLUETOOTH)
 public final class BluetoothManager {
     private static final String TAG = "BluetoothManager";
     private static final boolean DBG = true;
diff --git a/core/java/android/bluetooth/BluetoothProfile.java b/core/java/android/bluetooth/BluetoothProfile.java
index 0e2263f..656188f 100644
--- a/core/java/android/bluetooth/BluetoothProfile.java
+++ b/core/java/android/bluetooth/BluetoothProfile.java
@@ -165,12 +165,19 @@
     public static final int OPP = 20;
 
     /**
+     * Hearing Aid Device
+     *
+     * @hide
+     */
+    int HEARING_AID = 21;
+
+    /**
      * Max profile ID. This value should be updated whenever a new profile is added to match
      * the largest value assigned to a profile.
      *
      * @hide
      */
-    public static final int MAX_PROFILE_ID = 20;
+    int MAX_PROFILE_ID = 21;
 
     /**
      * Default priority for devices that we try to auto-connect to and
diff --git a/core/java/android/bluetooth/BluetoothUuid.java b/core/java/android/bluetooth/BluetoothUuid.java
index 76cb3f5..0a0d214 100644
--- a/core/java/android/bluetooth/BluetoothUuid.java
+++ b/core/java/android/bluetooth/BluetoothUuid.java
@@ -79,6 +79,9 @@
             ParcelUuid.fromString("00001132-0000-1000-8000-00805F9B34FB");
     public static final ParcelUuid SAP =
             ParcelUuid.fromString("0000112D-0000-1000-8000-00805F9B34FB");
+    /* TODO: b/69623109 update this value. It will change to 16bit UUID!! */
+    public static final ParcelUuid HearingAid =
+            ParcelUuid.fromString("7312C48F-22CC-497F-85FD-A0616A3B9E05");
 
     public static final ParcelUuid BASE_UUID =
             ParcelUuid.fromString("00000000-0000-1000-8000-00805F9B34FB");
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index b85a319..f184380 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -560,6 +560,7 @@
      *
      * @param resId Resource id for the CharSequence text
      */
+    @NonNull
     public final CharSequence getText(@StringRes int resId) {
         return getResources().getText(resId);
     }
@@ -616,12 +617,11 @@
      * @param id The desired resource identifier, as generated by the aapt
      *           tool. This integer encodes the package, type, and resource
      *           entry. The value 0 is an invalid identifier.
-     * @return An object that can be used to draw this resource, or
-     *         {@code null} if the resource could not be resolved.
+     * @return An object that can be used to draw this resource.
      * @throws android.content.res.Resources.NotFoundException if the given ID
      *         does not exist.
      */
-    @Nullable
+    @NonNull
     public final Drawable getDrawable(@DrawableRes int id) {
         return getResources().getDrawable(id, getTheme());
     }
@@ -633,12 +633,11 @@
      * @param id The desired resource identifier, as generated by the aapt
      *           tool. This integer encodes the package, type, and resource
      *           entry. The value 0 is an invalid identifier.
-     * @return A color state list, or {@code null} if the resource could not be
-     *         resolved.
+     * @return A color state list.
      * @throws android.content.res.Resources.NotFoundException if the given ID
      *         does not exist.
      */
-    @Nullable
+    @NonNull
     public final ColorStateList getColorStateList(@ColorRes int id) {
         return getResources().getColorStateList(id, getTheme());
     }
@@ -3539,6 +3538,7 @@
      * @hide
      */
     @SystemApi
+    @Deprecated
     public static final String WIFI_RTT_SERVICE = "rttmanager";
 
     /**
@@ -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
@@ -4921,7 +4919,7 @@
     /**
      * @hide
      */
-    public void setAutofillClient(AutofillClient client) {
+    public void setAutofillClient(@SuppressWarnings("unused") AutofillClient client) {
     }
 
     /**
@@ -4934,7 +4932,9 @@
     /**
      * @hide
      */
-    public void setAutofillCompatibilityEnabled(boolean autofillCompatEnabled) {
+    @TestApi
+    public void setAutofillCompatibilityEnabled(
+            @SuppressWarnings("unused") boolean autofillCompatEnabled) {
     }
 
     /**
diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java
index a788989..1867a6d 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.java
@@ -17,6 +17,7 @@
 package android.content;
 
 import android.annotation.SystemApi;
+import android.annotation.TestApi;
 import android.app.IApplicationThread;
 import android.app.IServiceConnection;
 import android.content.pm.ApplicationInfo;
@@ -1000,14 +1001,17 @@
      */
     @Override
     public boolean isAutofillCompatibilityEnabled() {
-        return mBase.isAutofillCompatibilityEnabled();
+        return mBase != null && mBase.isAutofillCompatibilityEnabled();
     }
 
     /**
      * @hide
      */
+    @TestApi
     @Override
     public void setAutofillCompatibilityEnabled(boolean  autofillCompatEnabled) {
-        mBase.setAutofillCompatibilityEnabled(autofillCompatEnabled);
+        if (mBase != null) {
+            mBase.setAutofillCompatibilityEnabled(autofillCompatEnabled);
+        }
     }
 }
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index fa73e3c..e7aead1 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -2399,6 +2399,26 @@
      */
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String ACTION_CONFIGURATION_CHANGED = "android.intent.action.CONFIGURATION_CHANGED";
+
+    /**
+     * Broadcast Action: The current device {@link android.content.res.Configuration} has changed
+     * such that the device may be eligible for the installation of additional configuration splits.
+     * Configuration properties that can trigger this broadcast include locale and display density.
+     *
+     * <p class="note">
+     * Unlike {@link #ACTION_CONFIGURATION_CHANGED}, you <em>can</em> receive this through
+     * components declared in manifests. However, the receiver <em>must</em> hold the
+     * {@link android.Manifest.permission#INSTALL_PACKAGES} permission.
+     *
+     * <p class="note">
+     * This is a protected intent that can only be sent by the system.
+     *
+     * @hide
+     */
+    @SystemApi
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_SPLIT_CONFIGURATION_CHANGED =
+            "android.intent.action.SPLIT_CONFIGURATION_CHANGED";
     /**
      * Broadcast Action: The current device's locale has changed.
      *
@@ -2478,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/om/IOverlayManager.aidl b/core/java/android/content/om/IOverlayManager.aidl
index 86c1aa8..5b3c9dd 100644
--- a/core/java/android/content/om/IOverlayManager.aidl
+++ b/core/java/android/content/om/IOverlayManager.aidl
@@ -83,17 +83,36 @@
      * @param packageName The name of the overlay package.
      * @param enable true to enable the overlay, false to disable it.
      * @param userId The user for which to change the overlay.
-     * @return true if the system successfully registered the request, false
-     *         otherwise.
+     * @return true if the system successfully registered the request, false otherwise.
      */
     boolean setEnabled(in String packageName, in boolean enable, in int userId);
 
     /**
-     * Version of setEnabled that will also disable any other overlays for the target package.
+     * Request that an overlay package is enabled and any other overlay packages with the same
+     * target package are disabled.
+     *
+     * See {@link #setEnabled} for the details on overlay packages.
+     *
+     * @param packageName the name of the overlay package to enable.
+     * @param enabled must be true, otherwise the operation fails.
+     * @param userId The user for which to change the overlay.
+     * @return true if the system successfully registered the request, false otherwise.
      */
     boolean setEnabledExclusive(in String packageName, in boolean enable, in int userId);
 
     /**
+     * Request that an overlay package is enabled and any other overlay packages with the same
+     * target package and category are disabled.
+     *
+     * See {@link #setEnabled} for the details on overlay packages.
+     *
+     * @param packageName the name of the overlay package to enable.
+     * @param userId The user for which to change the overlay.
+     * @return true if the system successfully registered the request, false otherwise.
+     */
+    boolean setEnabledExclusiveInCategory(in String packageName, in int userId);
+
+    /**
      * Change the priority of the given overlay to be just higher than the
      * overlay with package name newParentPackageName. Both overlay packages
      * must have the same target and user.
diff --git a/core/java/android/content/om/OverlayInfo.java b/core/java/android/content/om/OverlayInfo.java
index 8464e26..6e633426 100644
--- a/core/java/android/content/om/OverlayInfo.java
+++ b/core/java/android/content/om/OverlayInfo.java
@@ -18,6 +18,7 @@
 
 import android.annotation.IntDef;
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -66,14 +67,14 @@
     /**
      * The overlay is currently disabled. It can be enabled.
      *
-     * @see IOverlayManager.setEnabled
+     * @see IOverlayManager#setEnabled
      */
     public static final int STATE_DISABLED = 2;
 
     /**
      * The overlay is currently enabled. It can be disabled.
      *
-     * @see IOverlayManager.setEnabled
+     * @see IOverlayManager#setEnabled
      */
     public static final int STATE_ENABLED = 3;
 
@@ -90,6 +91,11 @@
     public static final int STATE_OVERLAY_UPGRADING = 5;
 
     /**
+     * Category for theme overlays.
+     */
+    public static final String CATEGORY_THEME = "android.theme";
+
+    /**
      * Package name of the overlay package
      */
     public final String packageName;
@@ -100,6 +106,11 @@
     public final String targetPackageName;
 
     /**
+     * Category of the overlay package
+     */
+    public final String category;
+
+    /**
      * Full path to the base APK for this overlay package
      */
     public final String baseCodePath;
@@ -121,14 +132,15 @@
      * @param state the new state for the source OverlayInfo
      */
     public OverlayInfo(@NonNull OverlayInfo source, @State int state) {
-        this(source.packageName, source.targetPackageName, source.baseCodePath, state,
-                source.userId);
+        this(source.packageName, source.targetPackageName, source.category, source.baseCodePath,
+                state, source.userId);
     }
 
     public OverlayInfo(@NonNull String packageName, @NonNull String targetPackageName,
-            @NonNull String baseCodePath, @State int state, int userId) {
+            @Nullable String category, @NonNull String baseCodePath, int state, int userId) {
         this.packageName = packageName;
         this.targetPackageName = targetPackageName;
+        this.category = category;
         this.baseCodePath = baseCodePath;
         this.state = state;
         this.userId = userId;
@@ -138,6 +150,7 @@
     public OverlayInfo(Parcel source) {
         packageName = source.readString();
         targetPackageName = source.readString();
+        category = source.readString();
         baseCodePath = source.readString();
         state = source.readInt();
         userId = source.readInt();
@@ -177,6 +190,7 @@
     public void writeToParcel(Parcel dest, int flags) {
         dest.writeString(packageName);
         dest.writeString(targetPackageName);
+        dest.writeString(category);
         dest.writeString(baseCodePath);
         dest.writeInt(state);
         dest.writeInt(userId);
@@ -275,6 +289,9 @@
         if (!targetPackageName.equals(other.targetPackageName)) {
             return false;
         }
+        if (!category.equals(other.category)) {
+            return false;
+        }
         if (!baseCodePath.equals(other.baseCodePath)) {
             return false;
         }
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index e115f89..0e50002 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -1631,7 +1631,7 @@
      * @hide
      */
     public boolean isAllowedToUseHiddenApi() {
-        return isSystemApp();
+        return isSystemApp() || isUpdatedSystemApp();
     }
 
     /**
diff --git a/core/java/android/content/pm/InstantAppRequest.java b/core/java/android/content/pm/InstantAppRequest.java
index 38f0225..361d4e4 100644
--- a/core/java/android/content/pm/InstantAppRequest.java
+++ b/core/java/android/content/pm/InstantAppRequest.java
@@ -18,12 +18,14 @@
 
 import android.content.Intent;
 import android.os.Bundle;
+import android.text.TextUtils;
 
 /**
  * Information needed to make an instant application resolution request.
  * @hide
  */
 public final class InstantAppRequest {
+
     /** Response from the first phase of instant application resolution */
     public final AuxiliaryResolveInfo responseObj;
     /** The original intent that triggered instant application resolution */
@@ -40,6 +42,8 @@
     public final Bundle verificationBundle;
     /** Whether resolution occurs because an application is starting */
     public final boolean resolveForStart;
+    /** The instant app digest for this request */
+    public final InstantAppResolveInfo.InstantAppDigest digest;
 
     public InstantAppRequest(AuxiliaryResolveInfo responseObj, Intent origIntent,
             String resolvedType, String callingPackage, int userId, Bundle verificationBundle,
@@ -51,5 +55,11 @@
         this.userId = userId;
         this.verificationBundle = verificationBundle;
         this.resolveForStart = resolveForStart;
+        if (origIntent.getData() != null && !TextUtils.isEmpty(origIntent.getData().getHost())) {
+            digest = new InstantAppResolveInfo.InstantAppDigest(
+                    origIntent.getData().getHost(), 5 /*maxDigests*/);
+        } else {
+            digest = InstantAppResolveInfo.InstantAppDigest.UNDEFINED;
+        }
     }
 }
diff --git a/core/java/android/content/pm/InstantAppResolveInfo.java b/core/java/android/content/pm/InstantAppResolveInfo.java
index 112c5da..3a95a5f 100644
--- a/core/java/android/content/pm/InstantAppResolveInfo.java
+++ b/core/java/android/content/pm/InstantAppResolveInfo.java
@@ -26,10 +26,13 @@
 
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
 import java.util.Locale;
+import java.util.Random;
 
 /**
  * Describes an externally resolvable instant application. There are three states that this class
@@ -227,14 +230,25 @@
      */
     @SystemApi
     public static final class InstantAppDigest implements Parcelable {
-        private static final int DIGEST_MASK = 0xfffff000;
-
+        static final int DIGEST_MASK = 0xfffff000;
         public static final InstantAppDigest UNDEFINED =
                 new InstantAppDigest(new byte[][]{}, new int[]{});
+
+        private static Random sRandom = null;
+        static {
+            try {
+                sRandom = SecureRandom.getInstance("SHA1PRNG");
+            } catch (NoSuchAlgorithmException e) {
+                // oh well
+                sRandom = new Random();
+            }
+        }
         /** Full digest of the domain hashes */
         private final byte[][] mDigestBytes;
-        /** The first 4 bytes of the domain hashes */
+        /** The first 5 bytes of the domain hashes */
         private final int[] mDigestPrefix;
+        /** The first 5 bytes of the domain hashes interspersed with random data */
+        private int[] mDigestPrefixSecure;
 
         public InstantAppDigest(@NonNull String hostName) {
             this(hostName, -1 /*maxDigests*/);
@@ -306,6 +320,7 @@
                 }
             }
             mDigestPrefix = in.createIntArray();
+            mDigestPrefixSecure = in.createIntArray();
         }
 
         public byte[][] getDigestBytes() {
@@ -316,6 +331,26 @@
             return mDigestPrefix;
         }
 
+        /**
+         * Returns a digest prefix with additional random prefixes interspersed.
+         * @hide
+         */
+        public int[] getDigestPrefixSecure() {
+            if (this == InstantAppResolveInfo.InstantAppDigest.UNDEFINED) {
+                return getDigestPrefix();
+            } else if (mDigestPrefixSecure == null) {
+                // let's generate some random data to intersperse throughout the set of prefixes
+                final int realSize = getDigestPrefix().length;
+                final int manufacturedSize = realSize + 10 + sRandom.nextInt(10);
+                mDigestPrefixSecure = Arrays.copyOf(getDigestPrefix(), manufacturedSize);
+                for (int i = realSize; i < manufacturedSize; i++) {
+                    mDigestPrefixSecure[i] = sRandom.nextInt() & DIGEST_MASK;
+                }
+                Arrays.sort(mDigestPrefixSecure);
+            }
+            return mDigestPrefixSecure;
+        }
+
         @Override
         public int describeContents() {
             return 0;
@@ -323,6 +358,11 @@
 
         @Override
         public void writeToParcel(Parcel out, int flags) {
+            final boolean isUndefined = this == UNDEFINED;
+            out.writeBoolean(isUndefined);
+            if (isUndefined) {
+                return;
+            }
             if (mDigestBytes == null) {
                 out.writeInt(-1);
             } else {
@@ -332,6 +372,7 @@
                 }
             }
             out.writeIntArray(mDigestPrefix);
+            out.writeIntArray(mDigestPrefixSecure);
         }
 
         @SuppressWarnings("hiding")
@@ -339,6 +380,9 @@
                 new Parcelable.Creator<InstantAppDigest>() {
             @Override
             public InstantAppDigest createFromParcel(Parcel in) {
+                if (in.readBoolean() /* is undefined */) {
+                    return UNDEFINED;
+                }
                 return new InstantAppDigest(in);
             }
             @Override
diff --git a/core/java/android/content/pm/PackageInfo.java b/core/java/android/content/pm/PackageInfo.java
index 09a46b8..627ceb7 100644
--- a/core/java/android/content/pm/PackageInfo.java
+++ b/core/java/android/content/pm/PackageInfo.java
@@ -362,6 +362,13 @@
      */
     public String overlayTarget;
 
+    /**
+     * The overlay category, if any, of this package
+     *
+     * @hide
+     */
+    public String overlayCategory;
+
     /** @hide */
     public int overlayPriority;
 
@@ -464,10 +471,23 @@
         dest.writeString(restrictedAccountType);
         dest.writeString(requiredAccountType);
         dest.writeString(overlayTarget);
+        dest.writeString(overlayCategory);
         dest.writeInt(overlayPriority);
         dest.writeBoolean(mOverlayIsStatic);
         dest.writeInt(compileSdkVersion);
         dest.writeString(compileSdkVersionCodename);
+        writeSigningCertificateHistoryToParcel(dest, parcelableFlags);
+    }
+
+    private void writeSigningCertificateHistoryToParcel(Parcel dest, int parcelableFlags) {
+        if (signingCertificateHistory != null) {
+            dest.writeInt(signingCertificateHistory.length);
+            for (int i = 0; i < signingCertificateHistory.length; i++) {
+                dest.writeTypedArray(signingCertificateHistory[i], parcelableFlags);
+            }
+        } else {
+            dest.writeInt(-1);
+        }
     }
 
     public static final Parcelable.Creator<PackageInfo> CREATOR
@@ -519,10 +539,12 @@
         restrictedAccountType = source.readString();
         requiredAccountType = source.readString();
         overlayTarget = source.readString();
+        overlayCategory = source.readString();
         overlayPriority = source.readInt();
         mOverlayIsStatic = source.readBoolean();
         compileSdkVersion = source.readInt();
         compileSdkVersionCodename = source.readString();
+        readSigningCertificateHistoryFromParcel(source);
 
         // The component lists were flattened with the redundant ApplicationInfo
         // instances omitted.  Distribute the canonical one here as appropriate.
@@ -534,6 +556,16 @@
         }
     }
 
+    private void readSigningCertificateHistoryFromParcel(Parcel source) {
+        int len = source.readInt();
+        if (len != -1) {
+            signingCertificateHistory = new Signature[len][];
+            for (int i = 0; i < len; i++) {
+                signingCertificateHistory[i] = source.createTypedArray(Signature.CREATOR);
+            }
+        }
+    }
+
     private void propagateApplicationInfo(ApplicationInfo appInfo, ComponentInfo[] components) {
         if (components != null) {
             for (ComponentInfo ci : components) {
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 486c86c..07a9911 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -2070,6 +2070,15 @@
             "android.hardware.sensor.hifi_sensors";
 
     /**
+     * Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}:
+     * The device supports a hardware mechanism for invoking an assist gesture.
+     * @see android.provider.Settings.Secure#ASSIST_GESTURE_ENABLED
+     * @hide
+     */
+    @SdkConstant(SdkConstantType.FEATURE)
+    public static final String FEATURE_ASSIST_GESTURE = "android.hardware.sensor.assist";
+
+    /**
      * Feature for {@link #getSystemAvailableFeatures} and
      * {@link #hasSystemFeature}: The device has a telephony radio with data
      * communication support.
@@ -2108,8 +2117,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 +5074,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 3afc346..9e4166e 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -196,10 +196,6 @@
     private static final String TAG_RESTRICT_UPDATE = "restrict-update";
     private static final String TAG_USES_SPLIT = "uses-split";
 
-    // [b/36551762] STOPSHIP remove the ability to expose components via meta-data
-    // Temporary workaround; allow meta-data to expose components to instant apps
-    private static final String META_DATA_INSTANT_APPS = "instantapps.clients.allowed";
-
     private static final String METADATA_MAX_ASPECT_RATIO = "android.max_aspect";
 
     /**
@@ -680,6 +676,7 @@
         pi.restrictedAccountType = p.mRestrictedAccountType;
         pi.requiredAccountType = p.mRequiredAccountType;
         pi.overlayTarget = p.mOverlayTarget;
+        pi.overlayCategory = p.mOverlayCategory;
         pi.overlayPriority = p.mOverlayPriority;
         pi.mOverlayIsStatic = p.mOverlayIsStatic;
         pi.compileSdkVersion = p.mCompileSdkVersion;
@@ -2077,6 +2074,8 @@
                         com.android.internal.R.styleable.AndroidManifestResourceOverlay);
                 pkg.mOverlayTarget = sa.getString(
                         com.android.internal.R.styleable.AndroidManifestResourceOverlay_targetPackage);
+                pkg.mOverlayCategory = sa.getString(
+                        com.android.internal.R.styleable.AndroidManifestResourceOverlay_category);
                 pkg.mOverlayPriority = sa.getInt(
                         com.android.internal.R.styleable.AndroidManifestResourceOverlay_priority,
                         0);
@@ -4430,24 +4429,6 @@
                         outError)) == null) {
                     return null;
                 }
-                // we don't have an attribute [or it's false], but, we have meta-data
-                if (!visibleToEphemeral && a.metaData.getBoolean(META_DATA_INSTANT_APPS)) {
-                    visibleToEphemeral = true; // set in case there are more intent filters
-                    a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP;
-                    a.info.flags &= ~ActivityInfo.FLAG_IMPLICITLY_VISIBLE_TO_INSTANT_APP;
-                    owner.visibleToInstantApps = true;
-                    // cycle through any filters already seen
-                    for (int i = a.intents.size() - 1; i >= 0; --i) {
-                        a.intents.get(i)
-                                .setVisibilityToInstantApp(IntentFilter.VISIBILITY_EXPLICIT);
-                    }
-                    if (owner.preferredActivityFilters != null) {
-                        for (int i = owner.preferredActivityFilters.size() - 1; i >= 0; --i) {
-                            owner.preferredActivityFilters.get(i)
-                                    .setVisibilityToInstantApp(IntentFilter.VISIBILITY_EXPLICIT);
-                        }
-                    }
-                }
             } else if (!receiver && parser.getName().equals("layout")) {
                 parseLayout(res, parser, a);
             } else {
@@ -4942,7 +4923,7 @@
         p.info.authority = cpname.intern();
 
         if (!parseProviderTags(
-                res, parser, visibleToEphemeral, owner, p, outError)) {
+                res, parser, visibleToEphemeral, p, outError)) {
             return null;
         }
 
@@ -4950,7 +4931,7 @@
     }
 
     private boolean parseProviderTags(Resources res, XmlResourceParser parser,
-            boolean visibleToEphemeral, Package owner, Provider outInfo, String[] outError)
+            boolean visibleToEphemeral, Provider outInfo, String[] outError)
                     throws XmlPullParserException, IOException {
         int outerDepth = parser.getDepth();
         int type;
@@ -4978,17 +4959,6 @@
                         outInfo.metaData, outError)) == null) {
                     return false;
                 }
-                // we don't have an attribute [or it's false], but, we have meta-data
-                if (!visibleToEphemeral && outInfo.metaData.getBoolean(META_DATA_INSTANT_APPS)) {
-                    visibleToEphemeral = true; // set in case there are more intent filters
-                    outInfo.info.flags |= ProviderInfo.FLAG_VISIBLE_TO_INSTANT_APP;
-                    owner.visibleToInstantApps = true;
-                    // cycle through any filters already seen
-                    for (int i = outInfo.intents.size() - 1; i >= 0; --i) {
-                        outInfo.intents.get(i)
-                                .setVisibilityToInstantApp(IntentFilter.VISIBILITY_EXPLICIT);
-                    }
-                }
 
             } else if (parser.getName().equals("grant-uri-permission")) {
                 TypedArray sa = res.obtainAttributes(parser,
@@ -5277,17 +5247,6 @@
                         outError)) == null) {
                     return null;
                 }
-                // we don't have an attribute [or it's false], but, we have meta-data
-                if (!visibleToEphemeral && s.metaData.getBoolean(META_DATA_INSTANT_APPS)) {
-                    visibleToEphemeral = true; // set in case there are more intent filters
-                    s.info.flags |= ServiceInfo.FLAG_VISIBLE_TO_INSTANT_APP;
-                    owner.visibleToInstantApps = true;
-                    // cycle through any filters already seen
-                    for (int i = s.intents.size() - 1; i >= 0; --i) {
-                        s.intents.get(i)
-                                .setVisibilityToInstantApp(IntentFilter.VISIBILITY_EXPLICIT);
-                    }
-                }
             } else {
                 if (!RIGID_PARSER) {
                     Slog.w(TAG, "Unknown element under <service>: "
@@ -6368,6 +6327,7 @@
         public String mRequiredAccountType;
 
         public String mOverlayTarget;
+        public String mOverlayCategory;
         public int mOverlayPriority;
         public boolean mOverlayIsStatic;
 
@@ -6878,6 +6838,7 @@
             mRestrictedAccountType = dest.readString();
             mRequiredAccountType = dest.readString();
             mOverlayTarget = dest.readString();
+            mOverlayCategory = dest.readString();
             mOverlayPriority = dest.readInt();
             mOverlayIsStatic = (dest.readInt() == 1);
             mCompileSdkVersion = dest.readInt();
@@ -7001,6 +6962,7 @@
             dest.writeString(mRestrictedAccountType);
             dest.writeString(mRequiredAccountType);
             dest.writeString(mOverlayTarget);
+            dest.writeString(mOverlayCategory);
             dest.writeInt(mOverlayPriority);
             dest.writeInt(mOverlayIsStatic ? 1 : 0);
             dest.writeInt(mCompileSdkVersion);
diff --git a/core/java/android/content/pm/VerifierDeviceIdentity.java b/core/java/android/content/pm/VerifierDeviceIdentity.java
index a8cdb6a..90be6f31 100644
--- a/core/java/android/content/pm/VerifierDeviceIdentity.java
+++ b/core/java/android/content/pm/VerifierDeviceIdentity.java
@@ -19,6 +19,8 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 
+import com.android.internal.annotations.VisibleForTesting;
+
 import java.io.UnsupportedEncodingException;
 import java.security.SecureRandom;
 import java.util.Random;
@@ -86,6 +88,7 @@
      * @return verifier device identity based on the input from the provided
      *         random number generator
      */
+    @VisibleForTesting
     static VerifierDeviceIdentity generate(Random rng) {
         long identity = rng.nextLong();
         return new VerifierDeviceIdentity(identity);
diff --git a/core/java/android/content/pm/permission/RuntimePermissionPresenter.java b/core/java/android/content/pm/permission/RuntimePermissionPresenter.java
index 02d0a6d..79bc9a3 100644
--- a/core/java/android/content/pm/permission/RuntimePermissionPresenter.java
+++ b/core/java/android/content/pm/permission/RuntimePermissionPresenter.java
@@ -274,6 +274,7 @@
             }
         }
 
+        @GuardedBy("mLock")
         private void scheduleNextMessageIfNeededLocked() {
             if (mBound && mRemoteInstance != null && !mPendingWork.isEmpty()) {
                 Message nextMessage = mPendingWork.remove(0);
diff --git a/core/java/android/content/res/AssetManager.java b/core/java/android/content/res/AssetManager.java
index 7866560..5f8a34d 100644
--- a/core/java/android/content/res/AssetManager.java
+++ b/core/java/android/content/res/AssetManager.java
@@ -28,6 +28,8 @@
 import android.util.SparseArray;
 import android.util.TypedValue;
 
+import com.android.internal.annotations.GuardedBy;
+
 import java.io.FileDescriptor;
 import java.io.FileNotFoundException;
 import java.io.IOException;
@@ -915,6 +917,7 @@
     private native final void init(boolean isSystem);
     private native final void destroy();
 
+    @GuardedBy("this")
     private final void incRefsLocked(long id) {
         if (DEBUG_REFS) {
             if (mRefStacks == null) {
@@ -926,7 +929,8 @@
         }
         mNumRefs++;
     }
-    
+
+    @GuardedBy("this")
     private final void decRefsLocked(long id) {
         if (DEBUG_REFS && mRefStacks != null) {
             mRefStacks.remove(id);
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index e173653c..ad85e71 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -867,8 +867,9 @@
      * @param theme The theme used to style the drawable attributes, may be {@code null}.
      * @return Drawable An object that can be used to draw this resource.
      * @throws NotFoundException Throws NotFoundException if the given ID does
-     *             not exist.
+     *             not exist, or cannot be decoded.
      */
+    @NonNull
     public Drawable getDrawableForDensity(@DrawableRes int id, int density, @Nullable Theme theme) {
         final TypedValue value = obtainTempTypedValue();
         try {
@@ -980,7 +981,7 @@
      *         or multiple colors that can be selected based on a state.
      * @deprecated Use {@link #getColorStateList(int, Theme)} instead.
      */
-    @Nullable
+    @NonNull
     @Deprecated
     public ColorStateList getColorStateList(@ColorRes int id) throws NotFoundException {
         final ColorStateList csl = getColorStateList(id, null);
@@ -1011,7 +1012,7 @@
      * @return A themed ColorStateList object containing either a single solid
      *         color or multiple colors that can be selected based on a state.
      */
-    @Nullable
+    @NonNull
     public ColorStateList getColorStateList(@ColorRes int id, @Nullable Theme theme)
             throws NotFoundException {
         final TypedValue value = obtainTempTypedValue();
@@ -1024,7 +1025,7 @@
         }
     }
 
-    @Nullable
+    @NonNull
     ColorStateList loadColorStateList(@NonNull TypedValue value, int id, @Nullable Theme theme)
             throws NotFoundException {
         return mResourcesImpl.loadColorStateList(this, value, id, theme);
@@ -1033,7 +1034,7 @@
     /**
      * @hide
      */
-    @Nullable
+    @NonNull
     public ComplexColor loadComplexColor(@NonNull TypedValue value, int id, @Nullable Theme theme) {
         return mResourcesImpl.loadComplexColor(this, value, id, theme);
     }
@@ -1139,6 +1140,7 @@
      *         
      * @see #getXml
      */
+    @NonNull
     public XmlResourceParser getLayout(@LayoutRes int id) throws NotFoundException {
         return loadXmlResourceParser(id, "layout");
     }
@@ -1163,6 +1165,7 @@
      *         
      * @see #getXml
      */
+    @NonNull
     public XmlResourceParser getAnimation(@AnimatorRes @AnimRes int id) throws NotFoundException {
         return loadXmlResourceParser(id, "anim");
     }
@@ -1188,6 +1191,7 @@
      *         
      * @see android.util.AttributeSet
      */
+    @NonNull
     public XmlResourceParser getXml(@XmlRes int id) throws NotFoundException {
         return loadXmlResourceParser(id, "xml");
     }
@@ -1203,8 +1207,8 @@
      * @return InputStream Access to the resource data.
      *
      * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
-     * 
      */
+    @NonNull
     public InputStream openRawResource(@RawRes int id) throws NotFoundException {
         final TypedValue value = obtainTempTypedValue();
         try {
@@ -1261,6 +1265,7 @@
      *
      * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
      */
+    @NonNull
     public InputStream openRawResource(@RawRes int id, TypedValue value)
             throws NotFoundException {
         return mResourcesImpl.openRawResource(id, value);
diff --git a/core/java/android/content/res/ResourcesImpl.java b/core/java/android/content/res/ResourcesImpl.java
index 97cb78b..424fa83 100644
--- a/core/java/android/content/res/ResourcesImpl.java
+++ b/core/java/android/content/res/ResourcesImpl.java
@@ -27,9 +27,11 @@
 import android.annotation.StyleableRes;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ActivityInfo.Config;
+import android.content.res.AssetManager.AssetInputStream;
 import android.content.res.Configuration.NativeConfig;
 import android.content.res.Resources.NotFoundException;
 import android.graphics.Bitmap;
+import android.graphics.ImageDecoder;
 import android.graphics.Typeface;
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
@@ -543,7 +545,7 @@
         }
     }
 
-    @Nullable
+    @NonNull
     Drawable loadDrawable(@NonNull Resources wrapper, @NonNull TypedValue value, int id,
             int density, @Nullable Resources.Theme theme)
             throws NotFoundException {
@@ -627,7 +629,7 @@
             } else if (isColorDrawable) {
                 dr = new ColorDrawable(value.data);
             } else {
-                dr = loadDrawableForCookie(wrapper, value, id, density, null);
+                dr = loadDrawableForCookie(wrapper, value, id, density);
             }
             // DrawableContainer' constant state has drawables instances. In order to leave the
             // constant state intact in the cache, we need to create a new DrawableContainer after
@@ -752,10 +754,31 @@
     }
 
     /**
+     * Loads a Drawable from an encoded image stream, or null.
+     *
+     * This call will handle closing ais.
+     */
+    private Drawable decodeImageDrawable(@NonNull AssetInputStream ais,
+            @NonNull Resources wrapper, @NonNull TypedValue value) {
+        ImageDecoder.Source src = new ImageDecoder.AssetInputStreamSource(ais,
+                            wrapper, value);
+        try {
+            return ImageDecoder.decodeDrawable(src, (decoder, info, s) -> {
+                decoder.setAllocator(ImageDecoder.ALLOCATOR_SOFTWARE);
+            });
+        } catch (IOException ioe) {
+            // This is okay. This may be something that ImageDecoder does not
+            // support, like SVG.
+            return null;
+        }
+    }
+
+    /**
      * Loads a drawable from XML or resources stream.
      */
+    @NonNull
     private Drawable loadDrawableForCookie(@NonNull Resources wrapper, @NonNull TypedValue value,
-            int id, int density, @Nullable Resources.Theme theme) {
+            int id, int density) {
         if (value.string == null) {
             throw new NotFoundException("Resource \"" + getResourceName(id) + "\" ("
                     + Integer.toHexString(id) + ") is not a Drawable (color or path): " + value);
@@ -774,22 +797,23 @@
             }
         }
 
-        // For prelaod tracing.
+        // For preload tracing.
         long startTime = 0;
         int startBitmapCount = 0;
         long startBitmapSize = 0;
-        int startDrwableCount = 0;
+        int startDrawableCount = 0;
         if (TRACE_FOR_DETAILED_PRELOAD) {
             startTime = System.nanoTime();
             startBitmapCount = Bitmap.sPreloadTracingNumInstantiatedBitmaps;
             startBitmapSize = Bitmap.sPreloadTracingTotalBitmapsSize;
-            startDrwableCount = sPreloadTracingNumLoadedDrawables;
+            startDrawableCount = sPreloadTracingNumLoadedDrawables;
         }
 
         if (DEBUG_LOAD) {
             Log.v(TAG, "Loading drawable for cookie " + value.assetCookie + ": " + file);
         }
 
+
         final Drawable dr;
 
         Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, file);
@@ -804,13 +828,13 @@
                 if (file.endsWith(".xml")) {
                     final XmlResourceParser rp = loadXmlResourceParser(
                             file, id, value.assetCookie, "drawable");
-                    dr = Drawable.createFromXmlForDensity(wrapper, rp, density, theme);
+                    dr = Drawable.createFromXmlForDensity(wrapper, rp, density, null);
                     rp.close();
                 } else {
                     final InputStream is = mAssets.openNonAsset(
                             value.assetCookie, file, AssetManager.ACCESS_STREAMING);
-                    dr = Drawable.createFromResourceStream(wrapper, value, is, file, null);
-                    is.close();
+                    AssetInputStream ais = (AssetInputStream) is;
+                    dr = decodeImageDrawable(ais, wrapper, value);
                 }
             } finally {
                 stack.pop();
@@ -834,7 +858,7 @@
                     final long loadedBitmapSize =
                             Bitmap.sPreloadTracingTotalBitmapsSize - startBitmapSize;
                     final int loadedDrawables =
-                            sPreloadTracingNumLoadedDrawables - startDrwableCount;
+                            sPreloadTracingNumLoadedDrawables - startDrawableCount;
 
                     sPreloadTracingNumLoadedDrawables++;
 
@@ -910,6 +934,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.
      */
+    @Nullable
     private ComplexColor loadComplexColorFromName(Resources wrapper, Resources.Theme theme,
             TypedValue value, int id) {
         final long key = (((long) value.assetCookie) << 32) | value.data;
@@ -985,7 +1010,7 @@
         return complexColor;
     }
 
-    @Nullable
+    @NonNull
     ColorStateList loadColorStateList(Resources wrapper, TypedValue value, int id,
             Resources.Theme theme)
             throws NotFoundException {
@@ -1043,9 +1068,10 @@
      * 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.
      */
-    @Nullable
+    @NonNull
     private ComplexColor loadComplexColorForCookie(Resources wrapper, TypedValue value, int id,
             Resources.Theme theme) {
         if (value.string == null) {
diff --git a/core/java/android/content/res/XmlResourceParser.java b/core/java/android/content/res/XmlResourceParser.java
index 6be9b9e..86f4ba6 100644
--- a/core/java/android/content/res/XmlResourceParser.java
+++ b/core/java/android/content/res/XmlResourceParser.java
@@ -27,6 +27,8 @@
  * it is done reading the resource.
  */
 public interface XmlResourceParser extends XmlPullParser, AttributeSet, AutoCloseable {
+    String getAttributeNamespace (int index);
+
     /**
      * Close this parser. Calls on the interface are no longer valid after this call.
      */
diff --git a/core/java/android/database/sqlite/SQLiteConnectionPool.java b/core/java/android/database/sqlite/SQLiteConnectionPool.java
index b211700..dc60612 100644
--- a/core/java/android/database/sqlite/SQLiteConnectionPool.java
+++ b/core/java/android/database/sqlite/SQLiteConnectionPool.java
@@ -422,6 +422,7 @@
     }
 
     // Can't throw.
+    @GuardedBy("mLock")
     private boolean recycleConnectionLocked(SQLiteConnection connection,
             AcquiredConnectionStatus status) {
         if (status == AcquiredConnectionStatus.RECONFIGURE) {
@@ -531,6 +532,7 @@
     }
 
     // Can't throw.
+    @GuardedBy("mLock")
     private void closeAvailableConnectionsAndLogExceptionsLocked() {
         closeAvailableNonPrimaryConnectionsAndLogExceptionsLocked();
 
@@ -541,6 +543,7 @@
     }
 
     // Can't throw.
+    @GuardedBy("mLock")
     private boolean closeAvailableConnectionLocked(int connectionId) {
         final int count = mAvailableNonPrimaryConnections.size();
         for (int i = count - 1; i >= 0; i--) {
@@ -562,6 +565,7 @@
     }
 
     // Can't throw.
+    @GuardedBy("mLock")
     private void closeAvailableNonPrimaryConnectionsAndLogExceptionsLocked() {
         final int count = mAvailableNonPrimaryConnections.size();
         for (int i = 0; i < count; i++) {
@@ -581,6 +585,7 @@
     }
 
     // Can't throw.
+    @GuardedBy("mLock")
     private void closeExcessConnectionsAndLogExceptionsLocked() {
         int availableCount = mAvailableNonPrimaryConnections.size();
         while (availableCount-- > mMaxConnectionPoolSize - 1) {
@@ -591,6 +596,7 @@
     }
 
     // Can't throw.
+    @GuardedBy("mLock")
     private void closeConnectionAndLogExceptionsLocked(SQLiteConnection connection) {
         try {
             connection.close(); // might throw
@@ -609,6 +615,7 @@
     }
 
     // Can't throw.
+    @GuardedBy("mLock")
     private void reconfigureAllConnectionsLocked() {
         if (mAvailablePrimaryConnection != null) {
             try {
@@ -776,6 +783,7 @@
     }
 
     // Can't throw.
+    @GuardedBy("mLock")
     private void cancelConnectionWaiterLocked(ConnectionWaiter waiter) {
         if (waiter.mAssignedConnection != null || waiter.mException != null) {
             // Waiter is done waiting but has not woken up yet.
@@ -848,6 +856,7 @@
     }
 
     // Can't throw.
+    @GuardedBy("mLock")
     private void wakeConnectionWaitersLocked() {
         // Unpark all waiters that have requests that we can fulfill.
         // This method is designed to not throw runtime exceptions, although we might send
@@ -910,6 +919,7 @@
     }
 
     // Might throw.
+    @GuardedBy("mLock")
     private SQLiteConnection tryAcquirePrimaryConnectionLocked(int connectionFlags) {
         // If the primary connection is available, acquire it now.
         SQLiteConnection connection = mAvailablePrimaryConnection;
@@ -935,6 +945,7 @@
     }
 
     // Might throw.
+    @GuardedBy("mLock")
     private SQLiteConnection tryAcquireNonPrimaryConnectionLocked(
             String sql, int connectionFlags) {
         // Try to acquire the next connection in the queue.
@@ -974,6 +985,7 @@
     }
 
     // Might throw.
+    @GuardedBy("mLock")
     private void finishAcquireConnectionLocked(SQLiteConnection connection, int connectionFlags) {
         try {
             final boolean readOnly = (connectionFlags & CONNECTION_FLAG_READ_ONLY) != 0;
diff --git a/core/java/android/database/sqlite/SQLiteDatabase.java b/core/java/android/database/sqlite/SQLiteDatabase.java
index c1c0812..ae1f57d 100644
--- a/core/java/android/database/sqlite/SQLiteDatabase.java
+++ b/core/java/android/database/sqlite/SQLiteDatabase.java
@@ -2006,7 +2006,6 @@
      *     SQLiteDatabase db = SQLiteDatabase.openDatabase("db_filename", cursorFactory,
      *             SQLiteDatabase.CREATE_IF_NECESSARY | SQLiteDatabase.ENABLE_WRITE_AHEAD_LOGGING,
      *             myDatabaseErrorHandler);
-     *     db.enableWriteAheadLogging();
      * </pre></code>
      * </p><p>
      * Another way to enable write-ahead logging is to call {@link #enableWriteAheadLogging}
diff --git a/core/java/android/database/sqlite/SQLiteOpenHelper.java b/core/java/android/database/sqlite/SQLiteOpenHelper.java
index a2991e6..64e9e5d 100644
--- a/core/java/android/database/sqlite/SQLiteOpenHelper.java
+++ b/core/java/android/database/sqlite/SQLiteOpenHelper.java
@@ -58,7 +58,7 @@
 
     private SQLiteDatabase mDatabase;
     private boolean mIsInitializing;
-    private final SQLiteDatabase.OpenParams.Builder mOpenParamsBuilder;
+    private SQLiteDatabase.OpenParams.Builder mOpenParamsBuilder;
 
     /**
      * Create a helper object to create, open, and/or manage a database.
@@ -163,8 +163,7 @@
         mName = name;
         mNewVersion = version;
         mMinimumSupportedVersion = Math.max(0, minimumSupportedVersion);
-        mOpenParamsBuilder = openParamsBuilder;
-        mOpenParamsBuilder.addOpenFlags(SQLiteDatabase.CREATE_IF_NECESSARY);
+        setOpenParamsBuilder(openParamsBuilder);
     }
 
     /**
@@ -230,6 +229,30 @@
     }
 
     /**
+     * Sets configuration parameters that are used for opening {@link SQLiteDatabase}.
+     * <p>Please note that {@link SQLiteDatabase#CREATE_IF_NECESSARY} flag will always be set when
+     * opening the database
+     *
+     * @param openParams configuration parameters that are used for opening {@link SQLiteDatabase}.
+     * @throws IllegalStateException if the database is already open
+     */
+    public void setOpenParams(@NonNull SQLiteDatabase.OpenParams openParams) {
+        Preconditions.checkNotNull(openParams);
+        synchronized (this) {
+            if (mDatabase != null && mDatabase.isOpen()) {
+                throw new IllegalStateException(
+                        "OpenParams cannot be set after opening the database");
+            }
+            setOpenParamsBuilder(new SQLiteDatabase.OpenParams.Builder(openParams));
+        }
+    }
+
+    private void setOpenParamsBuilder(SQLiteDatabase.OpenParams.Builder openParamsBuilder) {
+        mOpenParamsBuilder = openParamsBuilder;
+        mOpenParamsBuilder.addOpenFlags(SQLiteDatabase.CREATE_IF_NECESSARY);
+    }
+
+    /**
      * Sets the maximum number of milliseconds that SQLite connection is allowed to be idle
      * before it is closed and removed from the pool.
      *
diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java
index 931b5c9..f08e1cc 100644
--- a/core/java/android/hardware/Camera.java
+++ b/core/java/android/hardware/Camera.java
@@ -242,6 +242,9 @@
 
     /**
      * Returns the number of physical cameras available on this device.
+     * The return value of this method might change dynamically if the device
+     * supports external cameras and an external camera is connected or
+     * disconnected.
      *
      * @return total number of accessible camera devices, or 0 if there are no
      *   cameras or an error was encountered enumerating them.
@@ -3542,8 +3545,8 @@
         /**
          * Gets the horizontal angle of view in degrees.
          *
-         * @return horizontal angle of view. This method will always return a
-         *         valid value.
+         * @return horizontal angle of view. Returns -1.0 when the device
+         *         doesn't report view angle information.
          */
         public float getHorizontalViewAngle() {
             return Float.parseFloat(get(KEY_HORIZONTAL_VIEW_ANGLE));
@@ -3552,8 +3555,8 @@
         /**
          * Gets the vertical angle of view in degrees.
          *
-         * @return vertical angle of view. This method will always return a
-         *         valid value.
+         * @return vertical angle of view. Returns -1.0 when the device
+         *         doesn't report view angle information.
          */
         public float getVerticalViewAngle() {
             return Float.parseFloat(get(KEY_VERTICAL_VIEW_ANGLE));
diff --git a/core/java/android/hardware/ConsumerIrManager.java b/core/java/android/hardware/ConsumerIrManager.java
index c7a33ff..6f589cd 100644
--- a/core/java/android/hardware/ConsumerIrManager.java
+++ b/core/java/android/hardware/ConsumerIrManager.java
@@ -16,8 +16,10 @@
 
 package android.hardware;
 
+import android.annotation.RequiresFeature;
 import android.annotation.SystemService;
 import android.content.Context;
+import android.content.pm.PackageManager;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.ServiceManager.ServiceNotFoundException;
@@ -27,6 +29,7 @@
  * Class that operates consumer infrared on the device.
  */
 @SystemService(Context.CONSUMER_IR_SERVICE)
+@RequiresFeature(PackageManager.FEATURE_CONSUMER_IR)
 public final class ConsumerIrManager {
     private static final String TAG = "ConsumerIr";
 
diff --git a/core/java/android/hardware/OWNERS b/core/java/android/hardware/OWNERS
new file mode 100644
index 0000000..b8fea55
--- /dev/null
+++ b/core/java/android/hardware/OWNERS
@@ -0,0 +1,7 @@
+# Camera
+per-file *Camera* = cychen@google.com
+per-file *Camera* = epeev@google.com
+per-file *Camera* = etalvala@google.com
+per-file *Camera* = shuzhenwang@google.com
+per-file *Camera* = yinchiayeh@google.com
+per-file *Camera* = zhijunhe@google.com
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index 96d043c..8502fc4 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -341,7 +341,7 @@
      */
     @SuppressWarnings({"unchecked"})
     public List<CaptureRequest.Key<?>> getAvailablePhysicalCameraRequestKeys() {
-        if (mAvailableSessionKeys == null) {
+        if (mAvailablePhysicalRequestKeys == null) {
             Object crKey = CaptureRequest.Key.class;
             Class<CaptureRequest.Key<?>> crKeyTyped = (Class<CaptureRequest.Key<?>>)crKey;
 
@@ -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>
@@ -1793,11 +1790,7 @@
      * The respective value of such request key can be obtained by calling
      * {@link CaptureRequest.Builder#getPhysicalCameraKey }. Capture requests that contain
      * individual physical device requests must be built via
-     * {@link android.hardware.camera2.CameraDevice#createCaptureRequest(int, Set)}.
-     * Such extended capture requests can be passed only to
-     * {@link CameraCaptureSession#capture } or {@link CameraCaptureSession#captureBurst } and
-     * not to {@link CameraCaptureSession#setRepeatingRequest } or
-     * {@link CameraCaptureSession#setRepeatingBurst }.</p>
+     * {@link android.hardware.camera2.CameraDevice#createCaptureRequest(int, Set)}.</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
      * <p><b>Limited capability</b> -
      * Present on all camera devices that report being at least {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED HARDWARE_LEVEL_LIMITED} devices in the
diff --git a/core/java/android/hardware/camera2/CameraDevice.java b/core/java/android/hardware/camera2/CameraDevice.java
index df64401..72db33f 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
@@ -917,11 +863,8 @@
      * request for a specific physical camera. The settings are chosen
      * to be the best options for the specific logical camera device. If
      * additional physical camera ids are passed, then they will also use the
-     * same settings template. Requests containing individual physical camera
-     * settings can be passed only to {@link CameraCaptureSession#capture} or
-     * {@link CameraCaptureSession#captureBurst} and not to
-     * {@link CameraCaptureSession#setRepeatingRequest} or
-     * {@link CameraCaptureSession#setRepeatingBurst}</p>
+     * same settings template. Clients can further modify individual camera
+     * settings by calling {@link CaptureRequest.Builder#setPhysicalCameraKey}.</p>
      *
      * <p>Individual physical camera settings will only be honored for camera session
      * that was initialiazed with corresponding physical camera id output configuration
@@ -950,8 +893,8 @@
      * @see #TEMPLATE_STILL_CAPTURE
      * @see #TEMPLATE_VIDEO_SNAPSHOT
      * @see #TEMPLATE_MANUAL
-     * @see CaptureRequest.Builder#setKey
-     * @see CaptureRequest.Builder#getKey
+     * @see CaptureRequest.Builder#setPhysicalCameraKey
+     * @see CaptureRequest.Builder#getPhysicalCameraKey
      */
     @NonNull
     public CaptureRequest.Builder createCaptureRequest(@RequestTemplate int templateType,
diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java
index e7c8961..e558b7e 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;
@@ -864,19 +829,24 @@
      * <li>{@link CameraCharacteristics#LENS_RADIAL_DISTORTION android.lens.radialDistortion}</li>
      * </ul>
      * </li>
+     * <li>The SENSOR_INFO_TIMESTAMP_SOURCE of the logical device and physical devices must be
+     *   the same.</li>
      * <li>The logical camera device must be LIMITED or higher device.</li>
      * </ul>
      * <p>Both the logical camera device and its underlying physical devices support the
      * mandatory stream combinations required for their device levels.</p>
      * <p>Additionally, for each guaranteed stream combination, the logical camera supports:</p>
      * <ul>
-     * <li>Replacing one logical {@link android.graphics.ImageFormat#YUV_420_888 YUV_420_888}
+     * <li>For each guaranteed stream combination, the logical camera supports replacing one
+     *   logical {@link android.graphics.ImageFormat#YUV_420_888 YUV_420_888}
      *   or raw stream with two physical streams of the same size and format, each from a
      *   separate physical camera, given that the size and format are supported by both
      *   physical cameras.</li>
-     * <li>Adding two raw streams, each from one physical camera, if the logical camera doesn't
-     *   advertise RAW capability, but the underlying physical cameras do. This is usually
-     *   the case when the physical cameras have different sensor sizes.</li>
+     * <li>If the logical camera doesn't advertise RAW capability, but the underlying physical
+     *   cameras do, the logical camera will support guaranteed stream combinations for RAW
+     *   capability, except that the RAW streams will be physical streams, each from a separate
+     *   physical camera. This is usually the case when the physical cameras have different
+     *   sensor sizes.</li>
      * </ul>
      * <p>Using physical streams in place of a logical stream of the same size and format will
      * not slow down the frame rate of the capture, as long as the minimum frame duration
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/hardware/camera2/OWNERS b/core/java/android/hardware/camera2/OWNERS
new file mode 100644
index 0000000..18acfee
--- /dev/null
+++ b/core/java/android/hardware/camera2/OWNERS
@@ -0,0 +1,6 @@
+cychen@google.com
+epeev@google.com
+etalvala@google.com
+shuzhenwang@google.com
+yinchiayeh@google.com
+zhijunhe@google.com
diff --git a/core/java/android/hardware/camera2/params/OutputConfiguration.java b/core/java/android/hardware/camera2/params/OutputConfiguration.java
index b205e2c..a040a09 100644
--- a/core/java/android/hardware/camera2/params/OutputConfiguration.java
+++ b/core/java/android/hardware/camera2/params/OutputConfiguration.java
@@ -82,11 +82,9 @@
  *
  * </ul>
  *
- * <p>Please note that surface sharing is currently only enabled for outputs that use the
- * {@link ImageFormat#PRIVATE} format. This includes surface sources like
- * {@link android.view.SurfaceView}, {@link android.media.MediaRecorder},
- * {@link android.graphics.SurfaceTexture} and {@link android.media.ImageReader}, configured using
- * the aforementioned format.</p>
+ * <p> As of {@link android.os.Build.VERSION_CODES#P Android P}, all formats can be used for
+ * sharing, subject to device support. On prior API levels, only {@link ImageFormat#PRIVATE}
+ * format may be used.</p>
  *
  * @see CameraDevice#createCaptureSessionByOutputConfigurations
  *
diff --git a/core/java/android/hardware/display/AmbientBrightnessDayStats.java b/core/java/android/hardware/display/AmbientBrightnessDayStats.java
index 00f3c36..1aa2557 100644
--- a/core/java/android/hardware/display/AmbientBrightnessDayStats.java
+++ b/core/java/android/hardware/display/AmbientBrightnessDayStats.java
@@ -47,6 +47,11 @@
     private final float[] mStats;
 
     /**
+     * Initialize day stats from the given state. The time spent in each of the bucket is
+     * initialized to 0.
+     *
+     * @param localDate        The date for which stats are being tracked
+     * @param bucketBoundaries Bucket boundaries used from creating the buckets from
      * @hide
      */
     public AmbientBrightnessDayStats(@NonNull LocalDate localDate,
@@ -55,6 +60,11 @@
     }
 
     /**
+     * Initialize day stats from the given state
+     *
+     * @param localDate        The date for which stats are being tracked
+     * @param bucketBoundaries Bucket boundaries used from creating the buckets from
+     * @param stats            Time spent in each of the buckets (in seconds)
      * @hide
      */
     public AmbientBrightnessDayStats(@NonNull LocalDate localDate,
@@ -81,14 +91,26 @@
         mStats = stats;
     }
 
+    /**
+     * @return The {@link LocalDate} for which brightness stats are being tracked.
+     */
     public LocalDate getLocalDate() {
         return mLocalDate;
     }
 
+    /**
+     * @return Aggregated stats of time spent (in seconds) in various buckets.
+     */
     public float[] getStats() {
         return mStats;
     }
 
+    /**
+     * Returns the bucket boundaries (in lux) used for creating buckets. For eg., if the bucket
+     * boundaries array is {b1, b2, b3}, the buckets will be [b1, b2), [b2, b3), [b3, inf).
+     *
+     * @return The list of bucket boundaries.
+     */
     public float[] getBucketBoundaries() {
         return mBucketBoundaries;
     }
@@ -169,7 +191,14 @@
         dest.writeFloatArray(mStats);
     }
 
-    /** @hide */
+    /**
+     * Updates the stats by incrementing the time spent for the appropriate bucket based on ambient
+     * brightness reading.
+     *
+     * @param ambientBrightness Ambient brightness reading (in lux)
+     * @param durationSec       Time spent with the given reading (in seconds)
+     * @hide
+     */
     public void log(float ambientBrightness, float durationSec) {
         int bucketIndex = getBucketIndex(ambientBrightness);
         if (bucketIndex >= 0) {
diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java
index 92d6bbb..bd54522 100644
--- a/core/java/android/hardware/fingerprint/FingerprintManager.java
+++ b/core/java/android/hardware/fingerprint/FingerprintManager.java
@@ -23,10 +23,12 @@
 import android.annotation.CallbackExecutor;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.RequiresFeature;
 import android.annotation.RequiresPermission;
 import android.annotation.SystemService;
 import android.app.ActivityManager;
 import android.content.Context;
+import android.content.pm.PackageManager;
 import android.hardware.biometrics.BiometricAuthenticator;
 import android.hardware.biometrics.BiometricFingerprintConstants;
 import android.os.Binder;
@@ -59,6 +61,7 @@
  */
 @Deprecated
 @SystemService(Context.FINGERPRINT_SERVICE)
+@RequiresFeature(PackageManager.FEATURE_FINGERPRINT)
 public class FingerprintManager implements BiometricFingerprintConstants {
     private static final String TAG = "FingerprintManager";
     private static final boolean DEBUG = true;
diff --git a/core/java/android/hardware/hdmi/HdmiControlManager.java b/core/java/android/hardware/hdmi/HdmiControlManager.java
index a772cbe..e34423c 100644
--- a/core/java/android/hardware/hdmi/HdmiControlManager.java
+++ b/core/java/android/hardware/hdmi/HdmiControlManager.java
@@ -17,11 +17,13 @@
 package android.hardware.hdmi;
 
 import android.annotation.Nullable;
+import android.annotation.RequiresFeature;
 import android.annotation.RequiresPermission;
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.annotation.SuppressLint;
 import android.content.Context;
+import android.content.pm.PackageManager;
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
 import android.os.RemoteException;
@@ -42,6 +44,7 @@
  */
 @SystemApi
 @SystemService(Context.HDMI_CONTROL_SERVICE)
+@RequiresFeature(PackageManager.FEATURE_HDMI_CEC)
 public final class HdmiControlManager {
     private static final String TAG = "HdmiControlManager";
 
diff --git a/core/java/android/hardware/radio/RadioManager.java b/core/java/android/hardware/radio/RadioManager.java
index e1d7edf..8fde82e 100644
--- a/core/java/android/hardware/radio/RadioManager.java
+++ b/core/java/android/hardware/radio/RadioManager.java
@@ -21,10 +21,12 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.RequiresFeature;
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
 import android.content.Context;
+import android.content.pm.PackageManager;
 import android.os.Handler;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -58,6 +60,7 @@
  */
 @SystemApi
 @SystemService(Context.RADIO_SERVICE)
+@RequiresFeature(PackageManager.FEATURE_BROADCAST_RADIO)
 public class RadioManager {
     private static final String TAG = "BroadcastRadio.manager";
 
diff --git a/core/java/android/hardware/usb/UsbDeviceConnection.java b/core/java/android/hardware/usb/UsbDeviceConnection.java
index 5b15c0d..9e5174a 100644
--- a/core/java/android/hardware/usb/UsbDeviceConnection.java
+++ b/core/java/android/hardware/usb/UsbDeviceConnection.java
@@ -222,7 +222,10 @@
      * @param endpoint the endpoint for this transaction
      * @param buffer buffer for data to send or receive; can be {@code null} to wait for next
      *               transaction without reading data
-     * @param length the length of the data to send or receive
+     * @param length the length of the data to send or receive. Before
+     *               {@value Build.VERSION_CODES#P}, a value larger than 16384 bytes
+     *               would be truncated down to 16384. In API {@value Build.VERSION_CODES#P}
+     *               and after, any value of length is valid.
      * @param timeout in milliseconds, 0 is infinite
      * @return length of data transferred (or zero) for success,
      * or negative value for failure
@@ -239,7 +242,10 @@
      * @param endpoint the endpoint for this transaction
      * @param buffer buffer for data to send or receive
      * @param offset the index of the first byte in the buffer to send or receive
-     * @param length the length of the data to send or receive
+     * @param length the length of the data to send or receive. Before
+     *               {@value Build.VERSION_CODES#P}, a value larger than 16384 bytes
+     *               would be truncated down to 16384. In API {@value Build.VERSION_CODES#P}
+     *               and after, any value of length is valid.
      * @param timeout in milliseconds, 0 is infinite
      * @return length of data transferred (or zero) for success,
      * or negative value for failure
@@ -247,6 +253,10 @@
     public int bulkTransfer(UsbEndpoint endpoint,
             byte[] buffer, int offset, int length, int timeout) {
         checkBounds(buffer, offset, length);
+        if (mContext.getApplicationInfo().targetSdkVersion < Build.VERSION_CODES.P
+                && length > UsbRequest.MAX_USBFS_BUFFER_SIZE) {
+            length = UsbRequest.MAX_USBFS_BUFFER_SIZE;
+        }
         return native_bulk_request(endpoint.getAddress(), buffer, offset, length, timeout);
     }
 
diff --git a/core/java/android/hardware/usb/UsbManager.java b/core/java/android/hardware/usb/UsbManager.java
index 8daecac..74a36df 100644
--- a/core/java/android/hardware/usb/UsbManager.java
+++ b/core/java/android/hardware/usb/UsbManager.java
@@ -19,6 +19,7 @@
 
 import android.Manifest;
 import android.annotation.Nullable;
+import android.annotation.RequiresFeature;
 import android.annotation.RequiresPermission;
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
@@ -27,6 +28,7 @@
 import android.app.PendingIntent;
 import android.content.ComponentName;
 import android.content.Context;
+import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.hardware.usb.gadget.V1_0.GadgetFunction;
 import android.os.Bundle;
@@ -382,6 +384,7 @@
      *
      * @return HashMap containing all connected USB devices.
      */
+    @RequiresFeature(PackageManager.FEATURE_USB_HOST)
     public HashMap<String,UsbDevice> getDeviceList() {
         HashMap<String,UsbDevice> result = new HashMap<String,UsbDevice>();
         if (mService == null) {
@@ -406,6 +409,7 @@
      * @param device the device to open
      * @return a {@link UsbDeviceConnection}, or {@code null} if open failed
      */
+    @RequiresFeature(PackageManager.FEATURE_USB_HOST)
     public UsbDeviceConnection openDevice(UsbDevice device) {
         try {
             String deviceName = device.getDeviceName();
@@ -430,6 +434,7 @@
      *
      * @return list of USB accessories, or null if none are attached.
      */
+    @RequiresFeature(PackageManager.FEATURE_USB_ACCESSORY)
     public UsbAccessory[] getAccessoryList() {
         if (mService == null) {
             return null;
@@ -452,6 +457,7 @@
      * @param accessory the USB accessory to open
      * @return file descriptor, or null if the accessor could not be opened.
      */
+    @RequiresFeature(PackageManager.FEATURE_USB_ACCESSORY)
     public ParcelFileDescriptor openAccessory(UsbAccessory accessory) {
         try {
             return mService.openAccessory(accessory);
@@ -472,6 +478,7 @@
      * @param device to check permissions for
      * @return true if caller has permission
      */
+    @RequiresFeature(PackageManager.FEATURE_USB_HOST)
     public boolean hasPermission(UsbDevice device) {
         if (mService == null) {
             return false;
@@ -492,6 +499,7 @@
      * @param accessory to check permissions for
      * @return true if caller has permission
      */
+    @RequiresFeature(PackageManager.FEATURE_USB_ACCESSORY)
     public boolean hasPermission(UsbAccessory accessory) {
         if (mService == null) {
             return false;
@@ -525,6 +533,7 @@
      * @param device to request permissions for
      * @param pi PendingIntent for returning result
      */
+    @RequiresFeature(PackageManager.FEATURE_USB_HOST)
     public void requestPermission(UsbDevice device, PendingIntent pi) {
         try {
             mService.requestDevicePermission(device, mContext.getPackageName(), pi);
@@ -551,6 +560,7 @@
      * @param accessory to request permissions for
      * @param pi PendingIntent for returning result
      */
+    @RequiresFeature(PackageManager.FEATURE_USB_ACCESSORY)
     public void requestPermission(UsbAccessory accessory, PendingIntent pi) {
         try {
             mService.requestAccessoryPermission(accessory, mContext.getPackageName(), pi);
diff --git a/core/java/android/hardware/usb/UsbRequest.java b/core/java/android/hardware/usb/UsbRequest.java
index 2e8f8e1..f59c87e 100644
--- a/core/java/android/hardware/usb/UsbRequest.java
+++ b/core/java/android/hardware/usb/UsbRequest.java
@@ -17,6 +17,7 @@
 package android.hardware.usb;
 
 import android.annotation.Nullable;
+import android.os.Build;
 import android.util.Log;
 
 import com.android.internal.util.Preconditions;
@@ -43,7 +44,7 @@
     private static final String TAG = "UsbRequest";
 
     // From drivers/usb/core/devio.c
-    private static final int MAX_USBFS_BUFFER_SIZE = 16384;
+    static final int MAX_USBFS_BUFFER_SIZE = 16384;
 
     // used by the JNI code
     private long mNativeContext;
@@ -175,7 +176,9 @@
      *               capacity will be ignored. Once the request
      *               {@link UsbDeviceConnection#requestWait() is processed} the position will be set
      *               to the number of bytes read/written.
-     * @param length number of bytes to read or write.
+     * @param length number of bytes to read or write. Before {@value Build.VERSION_CODES#P}, a
+     *               value larger than 16384 bytes would be truncated down to 16384. In API
+     *               {@value Build.VERSION_CODES#P} and after, any value of length is valid.
      *
      * @return true if the queueing operation succeeded
      *
@@ -186,6 +189,11 @@
         boolean out = (mEndpoint.getDirection() == UsbConstants.USB_DIR_OUT);
         boolean result;
 
+        if (mConnection.getContext().getApplicationInfo().targetSdkVersion < Build.VERSION_CODES.P
+                && length > MAX_USBFS_BUFFER_SIZE) {
+            length = MAX_USBFS_BUFFER_SIZE;
+        }
+
         synchronized (mLock) {
             // save our buffer for when the request has completed
             mBuffer = buffer;
@@ -222,7 +230,10 @@
      *               of the buffer is undefined until the request is returned by
      *               {@link UsbDeviceConnection#requestWait}. If the request failed the buffer
      *               will be unchanged; if the request succeeded the position of the buffer is
-     *               incremented by the number of bytes sent/received.
+     *               incremented by the number of bytes sent/received. Before
+     *               {@value Build.VERSION_CODES#P}, a buffer of length larger than 16384 bytes
+     *               would throw IllegalArgumentException. In API {@value Build.VERSION_CODES#P}
+     *               and after, any size buffer is valid.
      *
      * @return true if the queueing operation succeeded
      */
@@ -244,9 +255,12 @@
                 mIsUsingNewQueue = true;
                 wasQueued = native_queue(null, 0, 0);
             } else {
-                // Can only send/receive MAX_USBFS_BUFFER_SIZE bytes at once
-                Preconditions.checkArgumentInRange(buffer.remaining(), 0, MAX_USBFS_BUFFER_SIZE,
-                        "number of remaining bytes");
+                if (mConnection.getContext().getApplicationInfo().targetSdkVersion
+                        < Build.VERSION_CODES.P) {
+                    // Can only send/receive MAX_USBFS_BUFFER_SIZE bytes at once
+                    Preconditions.checkArgumentInRange(buffer.remaining(), 0, MAX_USBFS_BUFFER_SIZE,
+                            "number of remaining bytes");
+                }
 
                 // Can not receive into read-only buffers.
                 Preconditions.checkArgument(!(buffer.isReadOnly() && !isSend), "buffer can not be "
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index a817f33..017674f 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -1818,9 +1818,9 @@
     }
 
     /**
-     * Called when the input method window has been shown to the user, after
-     * previously not being visible.  This is done after all of the UI setup
-     * for the window has occurred (creating its views etc).
+     * Called immediately before the input method window is shown to the user.
+     * You could override this to prepare for the window to be shown
+     * (update view structure etc).
      */
     public void onWindowShown() {
         // Intentionally empty
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 91ba57f..fd030e2 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -112,8 +112,14 @@
      * <p/>
      * For a disconnect event, the boolean extra EXTRA_NO_CONNECTIVITY
      * is set to {@code true} if there are no connected networks at all.
+     *
+     * @deprecated apps should use the more versatile {@link #requestNetwork},
+     *             {@link #registerNetworkCallback} or {@link #registerDefaultNetworkCallback}
+     *             functions instead for faster and more detailed updates about the network
+     *             changes they care about.
      */
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    @Deprecated
     public static final String CONNECTIVITY_ACTION = "android.net.conn.CONNECTIVITY_CHANGE";
 
     /**
@@ -2663,7 +2669,7 @@
      * A {@code NetworkCallback} is registered by calling
      * {@link #requestNetwork(NetworkRequest, NetworkCallback)},
      * {@link #registerNetworkCallback(NetworkRequest, NetworkCallback)},
-     * or {@link #registerDefaultNetworkCallback(NetworkCallback). A {@code NetworkCallback} is
+     * or {@link #registerDefaultNetworkCallback(NetworkCallback)}. A {@code NetworkCallback} is
      * unregistered by calling {@link #unregisterNetworkCallback(NetworkCallback)}.
      * A {@code NetworkCallback} should be registered at most once at any time.
      * A {@code NetworkCallback} that has been unregistered can be registered again.
@@ -2692,6 +2698,32 @@
          * satisfying the request changes.
          *
          * @param network The {@link Network} of the satisfying network.
+         * @param networkCapabilities The {@link NetworkCapabilities} of the satisfying network.
+         * @param linkProperties The {@link LinkProperties} of the satisfying network.
+         * @hide
+         */
+        public void onAvailable(Network network, NetworkCapabilities networkCapabilities,
+                LinkProperties linkProperties) {
+            // Internally only this method is called when a new network is available, and
+            // it calls the callback in the same way and order that older versions used
+            // to call so as not to change the behavior.
+            onAvailable(network);
+            if (!networkCapabilities.hasCapability(
+                    NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED)) {
+                onNetworkSuspended(network);
+            }
+            onCapabilitiesChanged(network, networkCapabilities);
+            onLinkPropertiesChanged(network, linkProperties);
+        }
+
+        /**
+         * Called when the framework connects and has declared a new network ready for use.
+         * This callback may be called more than once if the {@link Network} that is
+         * satisfying the request changes. This will always immediately be followed by a
+         * call to {@link #onCapabilitiesChanged(Network, NetworkCapabilities)} then by a
+         * call to {@link #onLinkPropertiesChanged(Network, LinkProperties)}.
+         *
+         * @param network The {@link Network} of the satisfying network.
          */
         public void onAvailable(Network network) {}
 
@@ -2734,7 +2766,8 @@
          * changes capabilities but still satisfies the stated need.
          *
          * @param network The {@link Network} whose capabilities have changed.
-         * @param networkCapabilities The new {@link android.net.NetworkCapabilities} for this network.
+         * @param networkCapabilities The new {@link android.net.NetworkCapabilities} for this
+         *                            network.
          */
         public void onCapabilitiesChanged(Network network,
                 NetworkCapabilities networkCapabilities) {}
@@ -2750,7 +2783,7 @@
 
         /**
          * Called when the network the framework connected to for this request
-         * goes into {@link NetworkInfo.DetailedState.SUSPENDED}.
+         * goes into {@link NetworkInfo.State#SUSPENDED}.
          * This generally means that while the TCP connections are still live,
          * temporarily network data fails to transfer.  Specifically this is used
          * on cellular networks to mask temporary outages when driving through
@@ -2761,9 +2794,8 @@
 
         /**
          * Called when the network the framework connected to for this request
-         * returns from a {@link NetworkInfo.DetailedState.SUSPENDED} state.
-         * This should always be preceeded by a matching {@code onNetworkSuspended}
-         * call.
+         * returns from a {@link NetworkInfo.State#SUSPENDED} state. This should always be
+         * preceded by a matching {@link NetworkCallback#onNetworkSuspended} call.
          * @hide
          */
         public void onNetworkResumed(Network network) {}
@@ -2872,7 +2904,9 @@
                     break;
                 }
                 case CALLBACK_AVAILABLE: {
-                    callback.onAvailable(network);
+                    NetworkCapabilities cap = getObject(message, NetworkCapabilities.class);
+                    LinkProperties lp = getObject(message, LinkProperties.class);
+                    callback.onAvailable(network, cap, lp);
                     break;
                 }
                 case CALLBACK_LOSING: {
diff --git a/core/java/android/net/IpSecConfig.java b/core/java/android/net/IpSecConfig.java
index 6a262e2..8599f47 100644
--- a/core/java/android/net/IpSecConfig.java
+++ b/core/java/android/net/IpSecConfig.java
@@ -218,6 +218,25 @@
     @VisibleForTesting
     public IpSecConfig() {}
 
+    /** Copy constructor */
+    @VisibleForTesting
+    public IpSecConfig(IpSecConfig c) {
+        mMode = c.mMode;
+        mSourceAddress = c.mSourceAddress;
+        mDestinationAddress = c.mDestinationAddress;
+        mNetwork = c.mNetwork;
+        mSpiResourceId = c.mSpiResourceId;
+        mEncryption = c.mEncryption;
+        mAuthentication = c.mAuthentication;
+        mAuthenticatedEncryption = c.mAuthenticatedEncryption;
+        mEncapType = c.mEncapType;
+        mEncapSocketResourceId = c.mEncapSocketResourceId;
+        mEncapRemotePort = c.mEncapRemotePort;
+        mNattKeepaliveInterval = c.mNattKeepaliveInterval;
+        mMarkValue = c.mMarkValue;
+        mMarkMask = c.mMarkMask;
+    }
+
     private IpSecConfig(Parcel in) {
         mMode = in.readInt();
         mSourceAddress = in.readString();
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..60e96f9 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;
@@ -83,9 +84,11 @@
     @Retention(RetentionPolicy.SOURCE)
     public @interface EncapType {}
 
-    private IpSecTransform(Context context, IpSecConfig config) {
+    /** @hide */
+    @VisibleForTesting
+    public IpSecTransform(Context context, IpSecConfig config) {
         mContext = context;
-        mConfig = config;
+        mConfig = new IpSecConfig(config);
         mResourceId = INVALID_RESOURCE_ID;
     }
 
@@ -142,6 +145,18 @@
     }
 
     /**
+     * Equals method used for testing
+     *
+     * @hide
+     */
+    @VisibleForTesting
+    public static boolean equals(IpSecTransform lhs, IpSecTransform rhs) {
+        if (lhs == null || rhs == null) return (lhs == rhs);
+        return IpSecConfig.equals(lhs.getConfig(), rhs.getConfig())
+                && lhs.mResourceId == rhs.mResourceId;
+    }
+
+    /**
      * Deactivate this {@code IpSecTransform} and free allocated resources.
      *
      * <p>Deactivating a transform while it is still applied to a socket will result in errors on
@@ -266,6 +281,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 +324,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 +472,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/net/MacAddress.java b/core/java/android/net/MacAddress.java
index 287bdc8..74d6470 100644
--- a/core/java/android/net/MacAddress.java
+++ b/core/java/android/net/MacAddress.java
@@ -26,6 +26,7 @@
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.security.SecureRandom;
 import java.util.Arrays;
 import java.util.Random;
 
@@ -329,16 +330,34 @@
 
     /**
      * Returns a generated MAC address whose 24 least significant bits constituting the
-     * NIC part of the address are randomly selected.
+     * NIC part of the address are randomly selected and has Google OUI base.
      *
      * The locally assigned bit is always set to 1. The multicast bit is always set to 0.
      *
-     * @return a random locally assigned MacAddress.
+     * @return a random locally assigned, unicast MacAddress with Google OUI.
+     *
+     * @hide
+     */
+    public static @NonNull MacAddress createRandomUnicastAddressWithGoogleBase() {
+        return createRandomUnicastAddress(BASE_GOOGLE_MAC, new SecureRandom());
+    }
+
+    /**
+     * Returns a generated MAC address whose 46 bits, excluding the locally assigned bit and the
+     * unicast bit, are randomly selected.
+     *
+     * The locally assigned bit is always set to 1. The multicast bit is always set to 0.
+     *
+     * @return a random locally assigned, unicast MacAddress.
      *
      * @hide
      */
     public static @NonNull MacAddress createRandomUnicastAddress() {
-        return createRandomUnicastAddress(BASE_GOOGLE_MAC, new Random());
+        SecureRandom r = new SecureRandom();
+        long addr = r.nextLong() & VALID_LONG_MASK;
+        addr |= LOCALLY_ASSIGNED_MASK;
+        addr &= ~MULTICAST_MASK;
+        return new MacAddress(addr);
     }
 
     /**
@@ -355,8 +374,8 @@
      */
     public static @NonNull MacAddress createRandomUnicastAddress(MacAddress base, Random r) {
         long addr = (base.mAddr & OUI_MASK) | (NIC_MASK & r.nextLong());
-        addr = addr | LOCALLY_ASSIGNED_MASK;
-        addr = addr & ~MULTICAST_MASK;
+        addr |= LOCALLY_ASSIGNED_MASK;
+        addr &= ~MULTICAST_MASK;
         return new MacAddress(addr);
     }
 
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java
index 8e05cfa..bae373d 100644
--- a/core/java/android/net/NetworkCapabilities.java
+++ b/core/java/android/net/NetworkCapabilities.java
@@ -116,6 +116,7 @@
             NET_CAPABILITY_NOT_ROAMING,
             NET_CAPABILITY_FOREGROUND,
             NET_CAPABILITY_NOT_CONGESTED,
+            NET_CAPABILITY_NOT_SUSPENDED,
     })
     public @interface NetCapability { }
 
@@ -239,7 +240,6 @@
     /**
      * Indicates that this network is available for use by apps, and not a network that is being
      * kept up in the background to facilitate fast network switching.
-     * @hide
      */
     public static final int NET_CAPABILITY_FOREGROUND = 19;
 
@@ -252,8 +252,20 @@
      */
     public static final int NET_CAPABILITY_NOT_CONGESTED = 20;
 
+    /**
+     * Indicates that this network is not currently suspended.
+     * <p>
+     * When a network is suspended, the network's IP addresses and any connections
+     * established on the network remain valid, but the network is temporarily unable
+     * to transfer data. This can happen, for example, if a cellular network experiences
+     * a temporary loss of signal, such as when driving through a tunnel, etc.
+     * A network with this capability is not suspended, so is expected to be able to
+     * transfer data.
+     */
+    public static final int NET_CAPABILITY_NOT_SUSPENDED = 21;
+
     private static final int MIN_NET_CAPABILITY = NET_CAPABILITY_MMS;
-    private static final int MAX_NET_CAPABILITY = NET_CAPABILITY_NOT_CONGESTED;
+    private static final int MAX_NET_CAPABILITY = NET_CAPABILITY_NOT_SUSPENDED;
 
     /**
      * Network capabilities that are expected to be mutable, i.e., can change while a particular
@@ -262,12 +274,13 @@
     private static final long MUTABLE_CAPABILITIES =
             // TRUSTED can change when user explicitly connects to an untrusted network in Settings.
             // http://b/18206275
-            (1 << NET_CAPABILITY_TRUSTED) |
-            (1 << NET_CAPABILITY_VALIDATED) |
-            (1 << NET_CAPABILITY_CAPTIVE_PORTAL) |
-            (1 << NET_CAPABILITY_NOT_ROAMING) |
-            (1 << NET_CAPABILITY_FOREGROUND) |
-            (1 << NET_CAPABILITY_NOT_CONGESTED);
+            (1 << NET_CAPABILITY_TRUSTED)
+            | (1 << NET_CAPABILITY_VALIDATED)
+            | (1 << NET_CAPABILITY_CAPTIVE_PORTAL)
+            | (1 << NET_CAPABILITY_NOT_ROAMING)
+            | (1 << NET_CAPABILITY_FOREGROUND)
+            | (1 << NET_CAPABILITY_NOT_CONGESTED)
+            | (1 << NET_CAPABILITY_NOT_SUSPENDED);
 
     /**
      * Network capabilities that are not allowed in NetworkRequests. This exists because the
@@ -1299,6 +1312,7 @@
             case NET_CAPABILITY_NOT_ROAMING:    return "NOT_ROAMING";
             case NET_CAPABILITY_FOREGROUND:     return "FOREGROUND";
             case NET_CAPABILITY_NOT_CONGESTED:  return "NOT_CONGESTED";
+            case NET_CAPABILITY_NOT_SUSPENDED:  return "NOT_SUSPENDED";
             default:                            return Integer.toString(capability);
         }
     }
diff --git a/core/java/android/net/OWNERS b/core/java/android/net/OWNERS
index 3a40cf4..3cd37bf 100644
--- a/core/java/android/net/OWNERS
+++ b/core/java/android/net/OWNERS
@@ -1,3 +1,5 @@
+set noparent
+
 ek@google.com
 jsharkey@android.com
 jchalard@google.com
diff --git a/core/java/android/net/Uri.java b/core/java/android/net/Uri.java
index 5ca3a41..437153b 100644
--- a/core/java/android/net/Uri.java
+++ b/core/java/android/net/Uri.java
@@ -16,6 +16,7 @@
 
 package android.net;
 
+import android.annotation.Nullable;
 import android.content.Intent;
 import android.os.Environment;
 import android.os.Parcel;
@@ -23,6 +24,8 @@
 import android.os.StrictMode;
 import android.util.Log;
 
+import libcore.net.UriCodec;
+
 import java.io.File;
 import java.io.IOException;
 import java.io.UnsupportedEncodingException;
@@ -38,8 +41,6 @@
 import java.util.RandomAccess;
 import java.util.Set;
 
-import libcore.net.UriCodec;
-
 /**
  * Immutable URI reference. A URI reference includes a URI and a fragment, the
  * component of the URI following a '#'. Builds and parses URI references
@@ -174,6 +175,7 @@
      *
      * @return the scheme or null if this is a relative URI
      */
+    @Nullable
     public abstract String getScheme();
 
     /**
@@ -208,6 +210,7 @@
      *
      * @return the authority for this URI or null if not present
      */
+    @Nullable
     public abstract String getAuthority();
 
     /**
@@ -219,6 +222,7 @@
      *
      * @return the authority for this URI or null if not present
      */
+    @Nullable
     public abstract String getEncodedAuthority();
 
     /**
@@ -228,6 +232,7 @@
      *
      * @return the user info for this URI or null if not present
      */
+    @Nullable
     public abstract String getUserInfo();
 
     /**
@@ -237,6 +242,7 @@
      *
      * @return the user info for this URI or null if not present
      */
+    @Nullable
     public abstract String getEncodedUserInfo();
 
     /**
@@ -246,6 +252,7 @@
      *
      * @return the host for this URI or null if not present
      */
+    @Nullable
     public abstract String getHost();
 
     /**
@@ -262,6 +269,7 @@
      * @return the decoded path, or null if this is not a hierarchical URI
      * (like "mailto:nobody@google.com") or the URI is invalid
      */
+    @Nullable
     public abstract String getPath();
 
     /**
@@ -270,6 +278,7 @@
      * @return the encoded path, or null if this is not a hierarchical URI
      * (like "mailto:nobody@google.com") or the URI is invalid
      */
+    @Nullable
     public abstract String getEncodedPath();
 
     /**
@@ -280,6 +289,7 @@
      *
      * @return the decoded query or null if there isn't one
      */
+    @Nullable
     public abstract String getQuery();
 
     /**
@@ -290,6 +300,7 @@
      *
      * @return the encoded query or null if there isn't one
      */
+    @Nullable
     public abstract String getEncodedQuery();
 
     /**
@@ -297,6 +308,7 @@
      *
      * @return the decoded fragment or null if there isn't one
      */
+    @Nullable
     public abstract String getFragment();
 
     /**
@@ -304,6 +316,7 @@
      *
      * @return the encoded fragment or null if there isn't one
      */
+    @Nullable
     public abstract String getEncodedFragment();
 
     /**
@@ -318,6 +331,7 @@
      *
      * @return the decoded last segment or null if the path is empty
      */
+    @Nullable
     public abstract String getLastPathSegment();
 
     /**
@@ -1674,6 +1688,7 @@
      * @throws NullPointerException if key is null
      * @return the decoded value or null if no parameter is found
      */
+    @Nullable
     public String getQueryParameter(String key) {
         if (isOpaque()) {
             throw new UnsupportedOperationException(NOT_HIERARCHICAL);
diff --git a/core/java/android/os/BatteryManager.java b/core/java/android/os/BatteryManager.java
index a734719..8b4f02e 100644
--- a/core/java/android/os/BatteryManager.java
+++ b/core/java/android/os/BatteryManager.java
@@ -323,4 +323,16 @@
     public long getLongProperty(int id) {
         return queryProperty(id);
     }
+
+    /**
+     * Return true if the plugType given is wired
+     * @param plugType {@link #BATTERY_PLUGGED_AC}, {@link #BATTERY_PLUGGED_USB},
+     *        or {@link #BATTERY_PLUGGED_WIRELESS}
+     *
+     * @return true if plugType is wired
+     * @hide
+     */
+    public static boolean isPlugWired(int plugType) {
+        return plugType == BATTERY_PLUGGED_USB || plugType == BATTERY_PLUGGED_AC;
+    }
 }
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index fd0e5ae..7cd58e8 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -1537,6 +1537,7 @@
         public static final int STATE2_BLUETOOTH_ON_FLAG = 1<<22;
         public static final int STATE2_CAMERA_FLAG = 1<<21;
         public static final int STATE2_BLUETOOTH_SCAN_FLAG = 1 << 20;
+        public static final int STATE2_CELLULAR_HIGH_TX_POWER_FLAG = 1 << 19;
 
         public static final int MOST_INTERESTING_STATES2 =
                 STATE2_POWER_SAVE_FLAG | STATE2_WIFI_ON_FLAG | STATE2_DEVICE_IDLE_MASK
@@ -2239,12 +2240,16 @@
     public static final int DATA_CONNECTION_LTE = 13;
     public static final int DATA_CONNECTION_EHRPD = 14;
     public static final int DATA_CONNECTION_HSPAP = 15;
-    public static final int DATA_CONNECTION_OTHER = 16;
+    public static final int DATA_CONNECTION_GSM = 16;
+    public static final int DATA_CONNECTION_TD_SCDMA = 17;
+    public static final int DATA_CONNECTION_IWLAN = 18;
+    public static final int DATA_CONNECTION_LTE_CA = 19;
+    public static final int DATA_CONNECTION_OTHER = 20;
 
     static final String[] DATA_CONNECTION_NAMES = {
         "none", "gprs", "edge", "umts", "cdma", "evdo_0", "evdo_A",
         "1xrtt", "hsdpa", "hsupa", "hspa", "iden", "evdo_b", "lte",
-        "ehrpd", "hspap", "other"
+        "ehrpd", "hspap", "gsm", "td_scdma", "iwlan", "lte_ca", "other"
     };
 
     public static final int NUM_DATA_CONNECTION_TYPES = DATA_CONNECTION_OTHER+1;
@@ -2353,9 +2358,11 @@
                 WIFI_SUPPL_STATE_NAMES, WIFI_SUPPL_STATE_SHORT_NAMES),
         new BitDescription(HistoryItem.STATE2_CAMERA_FLAG, "camera", "ca"),
         new BitDescription(HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG, "ble_scan", "bles"),
+        new BitDescription(HistoryItem.STATE2_CELLULAR_HIGH_TX_POWER_FLAG,
+                "cellular_high_tx_power", "Chtp"),
         new BitDescription(HistoryItem.STATE2_GPS_SIGNAL_QUALITY_MASK,
             HistoryItem.STATE2_GPS_SIGNAL_QUALITY_SHIFT, "gps_signal_quality", "Gss",
-            new String[] { "poor", "good"}, new String[] { "poor", "good"}),
+            new String[] { "poor", "good"}, new String[] { "poor", "good"})
     };
 
     public static final String[] HISTORY_EVENT_NAMES = new String[] {
diff --git a/core/java/android/os/BestClock.java b/core/java/android/os/BestClock.java
new file mode 100644
index 0000000..aa066b6
--- /dev/null
+++ b/core/java/android/os/BestClock.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+import android.util.Log;
+
+import java.time.Clock;
+import java.time.DateTimeException;
+import java.time.ZoneId;
+import java.util.Arrays;
+
+/**
+ * Single {@link Clock} that will return the best available time from a set of
+ * prioritized {@link Clock} instances.
+ * <p>
+ * For example, when {@link SystemClock#currentNetworkTimeClock()} isn't able to
+ * provide the time, this class could use {@link Clock#systemUTC()} instead.
+ *
+ * @hide
+ */
+public class BestClock extends SimpleClock {
+    private static final String TAG = "BestClock";
+
+    private final Clock[] clocks;
+
+    public BestClock(ZoneId zone, Clock... clocks) {
+        super(zone);
+        this.clocks = clocks;
+    }
+
+    @Override
+    public long millis() {
+        for (Clock clock : clocks) {
+            try {
+                return clock.millis();
+            } catch (DateTimeException e) {
+                // Ignore and attempt the next clock
+                Log.w(TAG, e.toString());
+            }
+        }
+        throw new DateTimeException(
+                "No clocks in " + Arrays.toString(clocks) + " were able to provide time");
+    }
+}
diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java
index 682fdb7..ff7c0c6 100644
--- a/core/java/android/os/Binder.java
+++ b/core/java/android/os/Binder.java
@@ -1028,22 +1028,33 @@
      * in use, then we return the same bp.
      *
      * @param nativeData C++ pointer to (possibly still empty) BinderProxyNativeData.
-     * Takes ownership of nativeData iff <result>.mNativeData == nativeData.  Caller will usually
-     * delete nativeData if that's not the case.
+     * Takes ownership of nativeData iff <result>.mNativeData == nativeData, or if
+     * we exit via an exception.  If neither applies, it's the callers responsibility to
+     * recycle nativeData.
      * @param iBinder C++ pointer to IBinder. Does not take ownership of referenced object.
      */
     private static BinderProxy getInstance(long nativeData, long iBinder) {
-        BinderProxy result = sProxyMap.get(iBinder);
-        if (result == null) {
+        BinderProxy result;
+        try {
+            result = sProxyMap.get(iBinder);
+            if (result != null) {
+                return result;
+            }
             result = new BinderProxy(nativeData);
-            sProxyMap.set(iBinder, result);
+        } catch (Throwable e) {
+            // We're throwing an exception (probably OOME); don't drop nativeData.
+            NativeAllocationRegistry.applyFreeFunction(NoImagePreloadHolder.sNativeFinalizer,
+                    nativeData);
+            throw e;
         }
+        NoImagePreloadHolder.sRegistry.registerNativeAllocation(result, nativeData);
+        // The registry now owns nativeData, even if registration threw an exception.
+        sProxyMap.set(iBinder, result);
         return result;
     }
 
     private BinderProxy(long nativeData) {
         mNativeData = nativeData;
-        NoImagePreloadHolder.sRegistry.registerNativeAllocation(this, mNativeData);
     }
 
     /**
@@ -1057,8 +1068,9 @@
     // Use a Holder to allow static initialization of BinderProxy in the boot image, and
     // to avoid some initialization ordering issues.
     private static class NoImagePreloadHolder {
+        public static final long sNativeFinalizer = getNativeFinalizer();
         public static final NativeAllocationRegistry sRegistry = new NativeAllocationRegistry(
-                BinderProxy.class.getClassLoader(), getNativeFinalizer(), NATIVE_ALLOCATION_SIZE);
+                BinderProxy.class.getClassLoader(), sNativeFinalizer, NATIVE_ALLOCATION_SIZE);
     }
 
     public native boolean pingBinder();
diff --git a/core/java/android/os/ChildZygoteProcess.java b/core/java/android/os/ChildZygoteProcess.java
new file mode 100644
index 0000000..337a3e2
--- /dev/null
+++ b/core/java/android/os/ChildZygoteProcess.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+import android.net.LocalSocketAddress;
+
+/**
+ * Represents a connection to a child-zygote process. A child-zygote is spawend from another
+ * zygote process using {@link startChildZygote()}.
+ *
+ * {@hide}
+ */
+public class ChildZygoteProcess extends ZygoteProcess {
+    /**
+     * The PID of the child zygote process.
+     */
+    private final int mPid;
+
+    ChildZygoteProcess(LocalSocketAddress socketAddress, int pid) {
+        super(socketAddress, null);
+        mPid = pid;
+    }
+
+    /**
+     * Returns the PID of the child-zygote process.
+     */
+    public int getPid() {
+        return mPid;
+    }
+}
diff --git a/core/java/android/os/HwBinder.java b/core/java/android/os/HwBinder.java
index cdee110..228fe7a 100644
--- a/core/java/android/os/HwBinder.java
+++ b/core/java/android/os/HwBinder.java
@@ -29,7 +29,13 @@
 
     private static final NativeAllocationRegistry sNativeRegistry;
 
-    /** @hide */
+    /**
+     * Create and initialize a HwBinder object and the native objects
+     * used to allow this to participate in hwbinder transactions.
+     *
+     * @hide
+     */
+    @SystemApi
     public HwBinder() {
         native_setup();
 
@@ -44,12 +50,28 @@
             int code, HwParcel request, HwParcel reply, int flags)
         throws RemoteException;
 
-    /** @hide */
+    /**
+     * Process a hwbinder transaction.
+     *
+     * @param code interface specific code for interface.
+     * @param request parceled transaction
+     * @param reply object to parcel reply into
+     * @param flags transaction flags to be chosen by wire protocol
+     *
+     * @hide
+     */
+    @SystemApi
     public abstract void onTransact(
             int code, HwParcel request, HwParcel reply, int flags)
         throws RemoteException;
 
-    /** @hide */
+    /**
+     * Registers this service with the hwservicemanager.
+     *
+     * @param serviceName instance name of the service
+     * @hide
+     */
+    @SystemApi
     public native final void registerService(String serviceName)
         throws RemoteException;
 
diff --git a/core/java/android/os/IHwBinder.java b/core/java/android/os/IHwBinder.java
index a565dee..fbdf27e 100644
--- a/core/java/android/os/IHwBinder.java
+++ b/core/java/android/os/IHwBinder.java
@@ -21,12 +21,6 @@
 /** @hide */
 @SystemApi
 public interface IHwBinder {
-    // These MUST match their corresponding libhwbinder/IBinder.h definition !!!
-    /** @hide */
-    public static final int FIRST_CALL_TRANSACTION = 1;
-    /** @hide */
-    public static final int FLAG_ONEWAY = 1;
-
     /**
      * Process a hwbinder transaction.
      *
diff --git a/core/java/android/os/IStatsCompanionService.aidl b/core/java/android/os/IStatsCompanionService.aidl
index 8a27700..eae5217 100644
--- a/core/java/android/os/IStatsCompanionService.aidl
+++ b/core/java/android/os/IStatsCompanionService.aidl
@@ -55,9 +55,8 @@
     /** Pull the specified data. Results will be sent to statsd when complete. */
     StatsLogEventWrapper[] pullData(int pullCode);
 
-    /** Send a broadcast to the specified pkg and class that it should getData now. */
-    // TODO: Rename this and use a pending intent instead.
-    oneway void sendBroadcast(String pkg, String cls);
+    /** Send a broadcast to the specified PendingIntent's as IBinder that it should getData now. */
+    oneway void sendDataBroadcast(in IBinder intentSender);
 
     /**
      * Requests StatsCompanionService to send a broadcast using the given intentSender
diff --git a/core/java/android/os/IStatsManager.aidl b/core/java/android/os/IStatsManager.aidl
index 679b49d..682a24f1 100644
--- a/core/java/android/os/IStatsManager.aidl
+++ b/core/java/android/os/IStatsManager.aidl
@@ -81,12 +81,26 @@
     /**
      * Sets a configuration with the specified config key and subscribes to updates for this
      * configuration key. Broadcasts will be sent if this configuration needs to be collected.
-     * The configuration must be a wire-encoded StatsdConfig. The caller specifies the name of the
-     * package and class that should receive these broadcasts.
+     * The configuration must be a wire-encoded StatsDConfig. The receiver for this data is
+     * registered in a separate function.
      *
      * Returns if this configuration was correctly registered.
      */
-    boolean addConfiguration(in long configKey, in byte[] config, in String pkg, in String cls);
+    boolean addConfiguration(in long configKey, in byte[] config);
+
+    /**
+     * Registers the given pending intent for this config key. This intent is invoked when the
+     * memory consumed by the metrics for this configuration approach the pre-defined limits. There
+     * can be at most one listener per config key.
+     *
+     * Returns if this listener was correctly registered.
+     */
+    boolean setDataFetchOperation(long configKey, in IBinder intentSender);
+
+    /**
+     * Removes the data fetch operation for the specified configuration.
+     */
+    boolean removeDataFetchOperation(long configKey);
 
     /**
      * Removes the configuration with the matching config key. No-op if this config key does not
diff --git a/core/java/android/os/IUserManager.aidl b/core/java/android/os/IUserManager.aidl
index 65e9473..5e23932 100644
--- a/core/java/android/os/IUserManager.aidl
+++ b/core/java/android/os/IUserManager.aidl
@@ -71,6 +71,7 @@
     Bundle getUserRestrictions(int userHandle);
     boolean hasBaseUserRestriction(String restrictionKey, int userHandle);
     boolean hasUserRestriction(in String restrictionKey, int userHandle);
+    boolean hasUserRestrictionOnAnyUser(in String restrictionKey);
     void setUserRestriction(String key, boolean value, int userHandle);
     void setApplicationRestrictions(in String packageName, in Bundle restrictions,
             int userHandle);
diff --git a/core/java/android/os/SimpleClock.java b/core/java/android/os/SimpleClock.java
new file mode 100644
index 0000000..efc271f54
--- /dev/null
+++ b/core/java/android/os/SimpleClock.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+import java.time.Clock;
+import java.time.Instant;
+import java.time.ZoneId;
+
+/** {@hide} */
+public abstract class SimpleClock extends Clock {
+    private final ZoneId zone;
+
+    public SimpleClock(ZoneId zone) {
+        this.zone = zone;
+    }
+
+    @Override
+    public ZoneId getZone() {
+        return zone;
+    }
+
+    @Override
+    public Clock withZone(ZoneId zone) {
+        return new SimpleClock(zone) {
+            @Override
+            public long millis() {
+                return SimpleClock.this.millis();
+            }
+        };
+    }
+
+    @Override
+    public abstract long millis();
+
+    @Override
+    public Instant instant() {
+        return Instant.ofEpochMilli(millis());
+    }
+}
diff --git a/core/java/android/os/SystemClock.java b/core/java/android/os/SystemClock.java
index c52c22d..0f70427 100644
--- a/core/java/android/os/SystemClock.java
+++ b/core/java/android/os/SystemClock.java
@@ -24,8 +24,7 @@
 import dalvik.annotation.optimization.CriticalNative;
 
 import java.time.Clock;
-import java.time.Instant;
-import java.time.ZoneId;
+import java.time.DateTimeException;
 import java.time.ZoneOffset;
 
 /**
@@ -148,8 +147,8 @@
      * @return if the clock was successfully set to the specified time.
      */
     public static boolean setCurrentTimeMillis(long millis) {
-        IBinder b = ServiceManager.getService(Context.ALARM_SERVICE);
-        IAlarmManager mgr = IAlarmManager.Stub.asInterface(b);
+        final IAlarmManager mgr = IAlarmManager.Stub
+                .asInterface(ServiceManager.getService(Context.ALARM_SERVICE));
         if (mgr == null) {
             return false;
         }
@@ -174,27 +173,25 @@
     native public static long uptimeMillis();
 
     /**
+     * @removed
+     */
+    @Deprecated
+    public static @NonNull Clock uptimeMillisClock() {
+        return uptimeClock();
+    }
+
+    /**
      * Return {@link Clock} that starts at system boot, not counting time spent
      * in deep sleep.
+     *
+     * @removed
      */
-    public static @NonNull Clock uptimeMillisClock() {
-        return new Clock() {
-            @Override
-            public ZoneId getZone() {
-                return ZoneOffset.UTC;
-            }
-            @Override
-            public Clock withZone(ZoneId zone) {
-                throw new UnsupportedOperationException();
-            }
+    public static @NonNull Clock uptimeClock() {
+        return new SimpleClock(ZoneOffset.UTC) {
             @Override
             public long millis() {
                 return SystemClock.uptimeMillis();
             }
-            @Override
-            public Instant instant() {
-                return Instant.ofEpochMilli(millis());
-            }
         };
     }
 
@@ -209,25 +206,15 @@
     /**
      * Return {@link Clock} that starts at system boot, including time spent in
      * sleep.
+     *
+     * @removed
      */
     public static @NonNull Clock elapsedRealtimeClock() {
-        return new Clock() {
-            @Override
-            public ZoneId getZone() {
-                return ZoneOffset.UTC;
-            }
-            @Override
-            public Clock withZone(ZoneId zone) {
-                throw new UnsupportedOperationException();
-            }
+        return new SimpleClock(ZoneOffset.UTC) {
             @Override
             public long millis() {
                 return SystemClock.elapsedRealtime();
             }
-            @Override
-            public Instant instant() {
-                return Instant.ofEpochMilli(millis());
-            }
         };
     }
 
@@ -266,4 +253,62 @@
      */
     @CriticalNative
     public static native long currentTimeMicro();
+
+    /**
+     * Returns milliseconds since January 1, 1970 00:00:00.0 UTC, synchronized
+     * using a remote network source outside the device.
+     * <p>
+     * While the time returned by {@link System#currentTimeMillis()} can be
+     * adjusted by the user, the time returned by this method cannot be adjusted
+     * by the user. Note that synchronization may occur using an insecure
+     * network protocol, so the returned time should not be used for security
+     * purposes.
+     * <p>
+     * This performs no blocking network operations and returns values based on
+     * a recent successful synchronization event; it will either return a valid
+     * time or throw.
+     *
+     * @throws DateTimeException when no accurate network time can be provided.
+     */
+    public static long currentNetworkTimeMillis() {
+        final IAlarmManager mgr = IAlarmManager.Stub
+                .asInterface(ServiceManager.getService(Context.ALARM_SERVICE));
+        if (mgr != null) {
+            try {
+                return mgr.currentNetworkTimeMillis();
+            } catch (ParcelableException e) {
+                e.maybeRethrow(DateTimeException.class);
+                throw new RuntimeException(e);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        } else {
+            throw new RuntimeException(new DeadSystemException());
+        }
+    }
+
+    /**
+     * Returns a {@link Clock} that starts at January 1, 1970 00:00:00.0 UTC,
+     * synchronized using a remote network source outside the device.
+     * <p>
+     * While the time returned by {@link System#currentTimeMillis()} can be
+     * adjusted by the user, the time returned by this method cannot be adjusted
+     * by the user. Note that synchronization may occur using an insecure
+     * network protocol, so the returned time should not be used for security
+     * purposes.
+     * <p>
+     * This performs no blocking network operations and returns values based on
+     * a recent successful synchronization event; it will either return a valid
+     * time or throw.
+     *
+     * @throws DateTimeException when no accurate network time can be provided.
+     */
+    public static @NonNull Clock currentNetworkTimeClock() {
+        return new SimpleClock(ZoneOffset.UTC) {
+            @Override
+            public long millis() {
+                return SystemClock.currentNetworkTimeMillis();
+            }
+        };
+    }
 }
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/os/UserManager.java b/core/java/android/os/UserManager.java
index 2093cec..1856200 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -943,6 +943,20 @@
      * @see #getUserRestrictions()
      */
     public static final String DISALLOW_SHARE_INTO_MANAGED_PROFILE = "no_sharing_into_profile";
+
+    /**
+     * Specifies whether the user is allowed to print.
+     *
+     * This restriction can be set by device or profile owner.
+     *
+     * The default value is {@code false}.
+     *
+     * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
+     * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
+     * @see #getUserRestrictions()
+     */
+    public static final String DISALLOW_PRINTING = "no_printing";
+
     /**
      * Application restriction key that is used to indicate the pending arrival
      * of real restrictions for the app.
@@ -1664,6 +1678,18 @@
     }
 
     /**
+     * @hide
+     * Returns whether any user on the device has the given user restriction set.
+     */
+    public boolean hasUserRestrictionOnAnyUser(String restrictionKey) {
+        try {
+            return mService.hasUserRestrictionOnAnyUser(restrictionKey);
+        } catch (RemoteException re) {
+            throw re.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Return the serial number for a user.  This is a device-unique
      * number assigned to that user; if the user is deleted and then a new
      * user created, the new users will not be given the same serial number.
diff --git a/core/java/android/os/VibrationEffect.java b/core/java/android/os/VibrationEffect.java
index b6f16a7..e9b4853 100644
--- a/core/java/android/os/VibrationEffect.java
+++ b/core/java/android/os/VibrationEffect.java
@@ -16,10 +16,15 @@
 
 package android.os;
 
-import android.hardware.vibrator.V1_0.Constants.EffectStrength;
-import android.hardware.vibrator.V1_1.Constants.Effect_1_1;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.hardware.vibrator.V1_0.EffectStrength;
+import android.hardware.vibrator.V1_2.Effect;
+import android.net.Uri;
 import android.util.MathUtils;
 
+import com.android.internal.annotations.VisibleForTesting;
+
 import java.util.Arrays;
 
 /**
@@ -49,7 +54,7 @@
      * @see #get(int)
      * @hide
      */
-    public static final int EFFECT_CLICK = Effect_1_1.CLICK;
+    public static final int EFFECT_CLICK = Effect.CLICK;
 
     /**
      * A double click effect.
@@ -57,14 +62,62 @@
      * @see #get(int)
      * @hide
      */
-    public static final int EFFECT_DOUBLE_CLICK = Effect_1_1.DOUBLE_CLICK;
+    public static final int EFFECT_DOUBLE_CLICK = Effect.DOUBLE_CLICK;
 
     /**
      * A tick effect.
      * @see #get(int)
      * @hide
      */
-    public static final int EFFECT_TICK = Effect_1_1.TICK;
+    public static final int EFFECT_TICK = Effect.TICK;
+
+    /**
+     * A thud effect.
+     * @see #get(int)
+     * @hide
+     */
+    public static final int EFFECT_THUD = Effect.THUD;
+
+    /**
+     * A pop effect.
+     * @see #get(int)
+     * @hide
+     */
+    public static final int EFFECT_POP = Effect.POP;
+
+    /**
+     * A heavy click effect.
+     * @see #get(int)
+     * @hide
+     */
+    public static final int EFFECT_HEAVY_CLICK = Effect.HEAVY_CLICK;
+
+
+    /**
+     * Ringtone patterns. They may correspond with the device's ringtone audio, or may just be a
+     * pattern that can be played as a ringtone with any audio, depending on the device.
+     *
+     * @see #get(Uri, Context)
+     * @hide
+     */
+    @VisibleForTesting
+    public static final int[] RINGTONES = {
+        Effect.RINGTONE_1,
+        Effect.RINGTONE_2,
+        Effect.RINGTONE_3,
+        Effect.RINGTONE_4,
+        Effect.RINGTONE_5,
+        Effect.RINGTONE_6,
+        Effect.RINGTONE_7,
+        Effect.RINGTONE_8,
+        Effect.RINGTONE_9,
+        Effect.RINGTONE_10,
+        Effect.RINGTONE_11,
+        Effect.RINGTONE_12,
+        Effect.RINGTONE_13,
+        Effect.RINGTONE_14,
+        Effect.RINGTONE_15
+    };
 
     /** @hide to prevent subclassing from outside of the framework */
     public VibrationEffect() { }
@@ -198,6 +251,37 @@
         return effect;
     }
 
+    /**
+     * Get a predefined vibration effect associated with a given URI.
+     *
+     * Predefined effects are a set of common vibration effects that should be identical, regardless
+     * of the app they come from, in order to provide a cohesive experience for users across
+     * the entire device. They also may be custom tailored to the device hardware in order to
+     * provide a better experience than you could otherwise build using the generic building
+     * blocks.
+     *
+     * @param uri The URI associated with the haptic effect.
+     * @param context The context used to get the URI to haptic effect association.
+     *
+     * @return The desired effect, or {@code null} if there's no associated effect.
+     *
+     * @hide
+     */
+    @Nullable
+    public static VibrationEffect get(Uri uri, Context context) {
+        String[] uris = context.getResources().getStringArray(
+                com.android.internal.R.array.config_ringtoneEffectUris);
+        for (int i = 0; i < uris.length && i < RINGTONES.length; i++) {
+            if (uris[i] == null) {
+                continue;
+            }
+            if (Uri.parse(uris[i]).equals(uri)) {
+                return get(RINGTONES[i]);
+            }
+        }
+        return null;
+    }
+
     @Override
     public int describeContents() {
         return 0;
@@ -548,10 +632,15 @@
                 case EFFECT_CLICK:
                 case EFFECT_DOUBLE_CLICK:
                 case EFFECT_TICK:
+                case EFFECT_THUD:
+                case EFFECT_POP:
+                case EFFECT_HEAVY_CLICK:
                     break;
                 default:
-                    throw new IllegalArgumentException(
-                            "Unknown prebaked effect type (value=" + mEffectId + ")");
+                    if (mEffectId < RINGTONES[0] || mEffectId > RINGTONES[RINGTONES.length - 1]) {
+                        throw new IllegalArgumentException(
+                                "Unknown prebaked effect type (value=" + mEffectId + ")");
+                    }
             }
             if (!isValidEffectStrength(mEffectStrength)) {
                 throw new IllegalArgumentException(
diff --git a/core/java/android/os/VintfObject.java b/core/java/android/os/VintfObject.java
index 12a495b..fb22194 100644
--- a/core/java/android/os/VintfObject.java
+++ b/core/java/android/os/VintfObject.java
@@ -80,4 +80,11 @@
      *  ("28", ["libjpeg.so", "libbase.so"])]
      */
     public static native Map<String, String[]> getVndkSnapshots();
+
+    /**
+     * @return target FCM version, a number specified in the device manifest
+     * indicating the FCM version that the device manifest implements. Null if
+     * device manifest doesn't specify this number (for legacy devices).
+     */
+    public static native Long getTargetFrameworkCompatibilityMatrixVersion();
 }
diff --git a/core/java/android/os/ZygoteProcess.java b/core/java/android/os/ZygoteProcess.java
index 670f794..57418c8 100644
--- a/core/java/android/os/ZygoteProcess.java
+++ b/core/java/android/os/ZygoteProcess.java
@@ -33,6 +33,7 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
+import java.util.UUID;
 
 /*package*/ class ZygoteStartFailedEx extends Exception {
     ZygoteStartFailedEx(String s) {
@@ -61,18 +62,27 @@
     /**
      * The name of the socket used to communicate with the primary zygote.
      */
-    private final String mSocket;
+    private final LocalSocketAddress mSocket;
 
     /**
      * The name of the secondary (alternate ABI) zygote socket.
      */
-    private final String mSecondarySocket;
+    private final LocalSocketAddress mSecondarySocket;
 
     public ZygoteProcess(String primarySocket, String secondarySocket) {
+        this(new LocalSocketAddress(primarySocket, LocalSocketAddress.Namespace.RESERVED),
+                new LocalSocketAddress(secondarySocket, LocalSocketAddress.Namespace.RESERVED));
+    }
+
+    public ZygoteProcess(LocalSocketAddress primarySocket, LocalSocketAddress secondarySocket) {
         mSocket = primarySocket;
         mSecondarySocket = secondarySocket;
     }
 
+    public LocalSocketAddress getPrimarySocketAddress() {
+        return mSocket;
+    }
+
     /**
      * State for communicating with the zygote process.
      */
@@ -92,14 +102,13 @@
             this.abiList = abiList;
         }
 
-        public static ZygoteState connect(String socketAddress) throws IOException {
+        public static ZygoteState connect(LocalSocketAddress address) throws IOException {
             DataInputStream zygoteInputStream = null;
             BufferedWriter zygoteWriter = null;
             final LocalSocket zygoteSocket = new LocalSocket();
 
             try {
-                zygoteSocket.connect(new LocalSocketAddress(socketAddress,
-                        LocalSocketAddress.Namespace.RESERVED));
+                zygoteSocket.connect(address);
 
                 zygoteInputStream = new DataInputStream(zygoteSocket.getInputStream());
 
@@ -115,8 +124,8 @@
             }
 
             String abiListString = getAbiList(zygoteWriter, zygoteInputStream);
-            Log.i("Zygote", "Process: zygote socket " + socketAddress + " opened, supported ABIS: "
-                    + abiListString);
+            Log.i("Zygote", "Process: zygote socket " + address.getNamespace() + "/"
+                    + address.getName() + " opened, supported ABIS: " + abiListString);
 
             return new ZygoteState(zygoteSocket, zygoteInputStream, zygoteWriter,
                     Arrays.asList(abiListString.split(",")));
@@ -209,7 +218,8 @@
         try {
             return startViaZygote(processClass, niceName, uid, gid, gids,
                     runtimeFlags, mountExternal, targetSdkVersion, seInfo,
-                    abi, instructionSet, appDataDir, invokeWith, zygoteArgs);
+                    abi, instructionSet, appDataDir, invokeWith, false /* startChildZygote */,
+                    zygoteArgs);
         } catch (ZygoteStartFailedEx ex) {
             Log.e(LOG_TAG,
                     "Starting VM process through Zygote failed");
@@ -325,6 +335,8 @@
      * @param abi the ABI the process should use.
      * @param instructionSet null-ok the instruction set to use.
      * @param appDataDir null-ok the data directory of the app.
+     * @param startChildZygote Start a sub-zygote. This creates a new zygote process
+     * that has its state cloned from this zygote process.
      * @param extraArgs Additional arguments to supply to the zygote process.
      * @return An object that describes the result of the attempt to start the process.
      * @throws ZygoteStartFailedEx if process start failed for any reason
@@ -340,6 +352,7 @@
                                                       String instructionSet,
                                                       String appDataDir,
                                                       String invokeWith,
+                                                      boolean startChildZygote,
                                                       String[] extraArgs)
                                                       throws ZygoteStartFailedEx {
         ArrayList<String> argsForZygote = new ArrayList<String>();
@@ -396,6 +409,10 @@
             argsForZygote.add(invokeWith);
         }
 
+        if (startChildZygote) {
+            argsForZygote.add("--start-child-zygote");
+        }
+
         argsForZygote.add(processClass);
 
         if (extraArgs != null) {
@@ -410,6 +427,18 @@
     }
 
     /**
+     * Closes the connections to the zygote, if they exist.
+     */
+    public void close() {
+        if (primaryZygoteState != null) {
+            primaryZygoteState.close();
+        }
+        if (secondaryZygoteState != null) {
+            secondaryZygoteState.close();
+        }
+    }
+
+    /**
      * Tries to establish a connection to the zygote that handles a given {@code abi}. Might block
      * and retry if the zygote is unresponsive. This method is a no-op if a connection is
      * already open.
@@ -514,9 +543,19 @@
      * @param socketName The name of the socket to connect to.
      */
     public static void waitForConnectionToZygote(String socketName) {
+        final LocalSocketAddress address =
+                new LocalSocketAddress(socketName, LocalSocketAddress.Namespace.RESERVED);
+        waitForConnectionToZygote(address);
+    }
+
+    /**
+     * Try connecting to the Zygote over and over again until we hit a time-out.
+     * @param address The name of the socket to connect to.
+     */
+    public static void waitForConnectionToZygote(LocalSocketAddress address) {
         for (int n = 20; n >= 0; n--) {
             try {
-                final ZygoteState zs = ZygoteState.connect(socketName);
+                final ZygoteState zs = ZygoteState.connect(address);
                 zs.close();
                 return;
             } catch (IOException ioe) {
@@ -529,6 +568,38 @@
             } catch (InterruptedException ie) {
             }
         }
-        Slog.wtf(LOG_TAG, "Failed to connect to Zygote through socket " + socketName);
+        Slog.wtf(LOG_TAG, "Failed to connect to Zygote through socket " + address.getName());
+    }
+
+    /**
+     * Starts a new zygote process as a child of this zygote. This is used to create
+     * secondary zygotes that inherit data from the zygote that this object
+     * communicates with. This returns a new ZygoteProcess representing a connection
+     * to the newly created zygote. Throws an exception if the zygote cannot be started.
+     */
+    public ChildZygoteProcess startChildZygote(final String processClass,
+                                               final String niceName,
+                                               int uid, int gid, int[] gids,
+                                               int runtimeFlags,
+                                               String seInfo,
+                                               String abi,
+                                               String instructionSet) {
+        // Create an unguessable address in the global abstract namespace.
+        final LocalSocketAddress serverAddress = new LocalSocketAddress(
+                processClass + "/" + UUID.randomUUID().toString());
+
+        final String[] extraArgs = {Zygote.CHILD_ZYGOTE_SOCKET_NAME_ARG + serverAddress.getName()};
+
+        Process.ProcessStartResult result;
+        try {
+            result = startViaZygote(processClass, niceName, uid, gid,
+                    gids, runtimeFlags, 0 /* mountExternal */, 0 /* targetSdkVersion */, seInfo,
+                    abi, instructionSet, null /* appDataDir */, null /* invokeWith */,
+                    true /* startChildZygote */, extraArgs);
+        } catch (ZygoteStartFailedEx ex) {
+            throw new RuntimeException("Starting child-zygote through Zygote failed", ex);
+        }
+
+        return new ChildZygoteProcess(serverAddress, result.pid);
     }
 }
diff --git a/core/java/android/os/storage/StorageResultCode.java b/core/java/android/os/storage/StorageResultCode.java
deleted file mode 100644
index c843887..0000000
--- a/core/java/android/os/storage/StorageResultCode.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.os.storage;
-
-/**
- * Class that provides access to constants returned from StorageManager
- * and lower level StorageManagerService APIs.
- * 
- * @hide
- */
-public class StorageResultCode
-{
-    /**
-     * Operation succeeded.
-     * @see android.os.storage.StorageManager
-     */
-    public static final int OperationSucceeded               =  0;
-
-    /**
-     * Operation failed: Internal error.
-     * @see android.os.storage.StorageManager
-     */
-    public static final int OperationFailedInternalError     = -1;
-
-    /**
-     * Operation failed: Missing media.
-     * @see android.os.storage.StorageManager
-     */
-    public static final int OperationFailedNoMedia           = -2;
-
-    /**
-     * Operation failed: Media is blank.
-     * @see android.os.storage.StorageManager
-     */
-    public static final int OperationFailedMediaBlank        = -3;
-
-    /**
-     * Operation failed: Media is corrupt.
-     * @see android.os.storage.StorageManager
-     */
-    public static final int OperationFailedMediaCorrupt      = -4;
-
-    /**
-     * Operation failed: Storage not mounted.
-     * @see android.os.storage.StorageManager
-     */
-    public static final int OperationFailedStorageNotMounted  = -5;
-
-    /**
-     * Operation failed: Storage is mounted.
-     * @see android.os.storage.StorageManager
-     */
-    public static final int OperationFailedStorageMounted     = -6;
-
-    /**
-     * Operation failed: Storage is busy.
-     * @see android.os.storage.StorageManager
-     */
-    public static final int OperationFailedStorageBusy        = -7;
-
-}
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/print/PrintManager.java b/core/java/android/print/PrintManager.java
index 51b7798..e436bc6 100644
--- a/core/java/android/print/PrintManager.java
+++ b/core/java/android/print/PrintManager.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.RequiresFeature;
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
@@ -27,6 +28,7 @@
 import android.content.Context;
 import android.content.IntentSender;
 import android.content.IntentSender.SendIntentException;
+import android.content.pm.PackageManager;
 import android.graphics.drawable.Icon;
 import android.os.Bundle;
 import android.os.CancellationSignal;
@@ -104,6 +106,7 @@
  * @see PrintJobInfo
  */
 @SystemService(Context.PRINT_SERVICE)
+@RequiresFeature(PackageManager.FEATURE_PRINTING)
 public final class PrintManager {
 
     private static final String LOG_TAG = "PrintManager";
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index e709c53..2ec9009e 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -3692,18 +3692,15 @@
                 new SettingsValidators.InclusiveIntegerRangeValidator(0, 3);
 
         /**
-         * User-selected RTT mode
+         * User-selected RTT mode. When on, outgoing and incoming calls will be answered as RTT
+         * calls when supported by the device and carrier. Boolean value.
          * 0 = OFF
-         * 1 = FULL
-         * 2 = VCO
-         * 3 = HCO
-         * Uses the same constants as TTY (e.g. {@link android.telecom.TelecomManager#TTY_MODE_OFF})
-         * @hide
+         * 1 = ON
          */
         public static final String RTT_CALLING_MODE = "rtt_calling_mode";
 
         /** @hide */
-        public static final Validator RTT_CALLING_MODE_VALIDATOR = TTY_MODE_VALIDATOR;
+        public static final Validator RTT_CALLING_MODE_VALIDATOR = BOOLEAN_VALIDATOR;
 
         /**
          * Whether the sounds effects (key clicks, lid open ...) are enabled. The value is
@@ -5385,6 +5382,17 @@
                 "autofill_user_data_max_field_classification_size";
 
         /**
+         * Defines value returned by
+         * {@link android.service.autofill.UserData#getMaxCategoryCount()}.
+         *
+         * @hide
+         */
+        @SystemApi
+        @TestApi
+        public static final String AUTOFILL_USER_DATA_MAX_CATEGORY_COUNT =
+                "autofill_user_data_max_category_count";
+
+        /**
          * Defines value returned by {@link android.service.autofill.UserData#getMaxValueLength()}.
          *
          * @hide
@@ -5443,32 +5451,6 @@
          */
         public static final String ENABLED_INPUT_METHODS = "enabled_input_methods";
 
-        private static final Validator ENABLED_INPUT_METHODS_VALIDATOR = new Validator() {
-            @Override
-            public boolean validate(String value) {
-                if (value == null) {
-                    return false;
-                }
-                String[] inputMethods = value.split(":");
-                boolean valid = true;
-                for (String inputMethod : inputMethods) {
-                    if (inputMethod.length() == 0) {
-                        return false;
-                    }
-                    String[] subparts = inputMethod.split(";");
-                    for (String subpart : subparts) {
-                        // allow either a non negative integer or a ComponentName
-                        valid |= (NON_NEGATIVE_INTEGER_VALIDATOR.validate(subpart)
-                                || COMPONENT_NAME_VALIDATOR.validate(subpart));
-                    }
-                    if (!valid) {
-                        return false;
-                    }
-                }
-                return valid;
-            }
-        };
-
         /**
          * List of system input methods that are currently disabled.  This is a string
          * containing the IDs of all disabled input methods, each ID separated
@@ -7396,7 +7378,8 @@
          */
         public static final String NIGHT_DISPLAY_AUTO_MODE = "night_display_auto_mode";
 
-        private static final Validator NIGHT_DISPLAY_AUTO_MODE_VALIDATOR = BOOLEAN_VALIDATOR;
+        private static final Validator NIGHT_DISPLAY_AUTO_MODE_VALIDATOR =
+                new SettingsValidators.InclusiveIntegerRangeValidator(0, 2);
 
         /**
          * Control the color temperature of Night Display, represented in Kelvin.
@@ -7679,6 +7662,24 @@
          */
         public static final String BACKUP_MANAGER_CONSTANTS = "backup_manager_constants";
 
+
+        /**
+         * Local transport parameters so we can configure it for tests.
+         * This is encoded as a key=value list, separated by commas.
+         *
+         * The following keys are supported:
+         *
+         * <pre>
+         * fake_encryption_flag  (boolean)
+         * </pre>
+         *
+         * <p>
+         * Type: string
+         * @hide
+         */
+        public static final String BACKUP_LOCAL_TRANSPORT_PARAMETERS =
+                "backup_local_transport_parameters";
+
         /**
          * Flag to set if the system should predictively attempt to re-enable Bluetooth while
          * the user is driving.
@@ -7708,7 +7709,6 @@
             ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE,
             ENABLED_ACCESSIBILITY_SERVICES,
             ENABLED_VR_LISTENERS,
-            ENABLED_INPUT_METHODS,
             TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES,
             TOUCH_EXPLORATION_ENABLED,
             ACCESSIBILITY_ENABLED,
@@ -7814,7 +7814,6 @@
             VALIDATORS.put(ENABLED_ACCESSIBILITY_SERVICES,
                     ENABLED_ACCESSIBILITY_SERVICES_VALIDATOR);
             VALIDATORS.put(ENABLED_VR_LISTENERS, ENABLED_VR_LISTENERS_VALIDATOR);
-            VALIDATORS.put(ENABLED_INPUT_METHODS, ENABLED_INPUT_METHODS_VALIDATOR);
             VALIDATORS.put(TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES,
                     TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES_VALIDATOR);
             VALIDATORS.put(TOUCH_EXPLORATION_ENABLED, TOUCH_EXPLORATION_ENABLED_VALIDATOR);
@@ -8389,10 +8388,10 @@
         private static final Validator POWER_SOUNDS_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR;
 
         /**
-         * URI for the "wireless charging started" sound.
+         * URI for the "wireless charging started" and "wired charging started" sound.
          * @hide
          */
-        public static final String WIRELESS_CHARGING_STARTED_SOUND =
+        public static final String CHARGING_STARTED_SOUND =
                 "wireless_charging_started_sound";
 
         /**
@@ -8562,9 +8561,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";
 
         /**
@@ -8780,6 +8778,7 @@
        /** {@hide} */
        public static final String NETSTATS_POLL_INTERVAL = "netstats_poll_interval";
        /** {@hide} */
+       @Deprecated
        public static final String NETSTATS_TIME_CACHE_MAX_AGE = "netstats_time_cache_max_age";
        /** {@hide} */
        public static final String NETSTATS_GLOBAL_ALERT_BYTES = "netstats_global_alert_bytes";
@@ -10477,6 +10476,9 @@
          * <pre>
          * smart_selection_dark_launch              (boolean)
          * smart_selection_enabled_for_edit_text    (boolean)
+         * suggest_selection_max_range_length       (int)
+         * classify_text_max_range_length           (int)
+         * generate_links_max_text_length           (int)
          * </pre>
          *
          * <p>
@@ -10495,6 +10497,7 @@
          * track_cpu_times_by_proc_state (boolean)
          * track_cpu_active_cluster_time (boolean)
          * read_binary_cpu_time          (boolean)
+         * proc_state_cpu_times_read_delay_ms (long)
          * </pre>
          *
          * <p>
@@ -10505,6 +10508,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)
@@ -11372,15 +11385,25 @@
                 "chained_battery_attribution_enabled";
 
         /**
-         * The packages whitelisted to be run in autofill compatibility mode.
+         * The packages whitelisted to be run in autofill compatibility mode. The list
+         * of packages is ":" colon delimited.
          *
          * @hide
          */
         @SystemApi
+        @TestApi
         public static final String AUTOFILL_COMPAT_ALLOWED_PACKAGES =
                 "autofill_compat_allowed_packages";
 
         /**
+         * Exemptions to the hidden API blacklist.
+         *
+         * @hide
+         */
+        public static final String HIDDEN_API_BLACKLIST_EXEMPTIONS =
+                "hidden_api_blacklist_exemptions";
+
+        /**
          * Settings to backup. This is here so that it's in the same place as the settings
          * keys and easy to update.
          *
@@ -12079,6 +12102,28 @@
                 "enable_gnss_raw_meas_full_tracking";
 
         /**
+         * Whether the notification should be ongoing (persistent) when a carrier app install is
+         * required.
+         *
+         * The value is a boolean (1 or 0).
+         * @hide
+         */
+        @SystemApi
+        public static final String INSTALL_CARRIER_APP_NOTIFICATION_PERSISTENT =
+                "install_carrier_app_notification_persistent";
+
+        /**
+         * The amount of time (ms) to hide the install carrier app notification after the user has
+         * ignored it. After this time passes, the notification will be shown again
+         *
+         * The value is a long
+         * @hide
+         */
+        @SystemApi
+        public static final String INSTALL_CARRIER_APP_NOTIFICATION_SLEEP_MILLIS =
+                "install_carrier_app_notification_sleep_millis";
+
+        /**
          * Whether we've enabled zram on this device. Takes effect on
          * reboot. The value "1" enables zram; "0" disables it, and
          * everything else is unspecified.
@@ -12088,11 +12133,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.
@@ -12113,6 +12169,12 @@
          * @hide
          */
         public static final String SHOW_MUTE_IN_CRASH_DIALOG = "show_mute_in_crash_dialog";
+
+        /**
+         * If nonzero, will show the zen upgrade notification when the user toggles DND on/off.
+         * @hide
+         */
+        public static final String SHOW_ZEN_UPGRADE_NOTIFICATION = "show_zen_upgrade_notification";
     }
 
     /**
diff --git a/core/java/android/provider/SettingsSlicesContract.java b/core/java/android/provider/SettingsSlicesContract.java
index f79d852..7dc9488 100644
--- a/core/java/android/provider/SettingsSlicesContract.java
+++ b/core/java/android/provider/SettingsSlicesContract.java
@@ -31,12 +31,12 @@
  * <p>
  * {@link Uri} builder example:
  * <pre>
- * Uri wifiActionUri = AUTHORITY_URI
+ * Uri wifiActionUri = BASE_URI
  *         .buildUpon()
  *         .appendPath(PATH_SETTING_ACTION)
  *         .appendPath(KEY_WIFI)
  *         .build();
- * Uri bluetoothIntentUri = AUTHORITY_URI
+ * Uri bluetoothIntentUri = BASE_URI
  *         .buildUpon()
  *         .appendPath(PATH_SETTING_INTENT)
  *         .appendPath(KEY_BLUETOOTH)
diff --git a/core/java/android/security/IConfirmationPromptCallback.aidl b/core/java/android/security/IConfirmationPromptCallback.aidl
deleted file mode 100644
index 96a1a04..0000000
--- a/core/java/android/security/IConfirmationPromptCallback.aidl
+++ /dev/null
@@ -1,27 +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.security;
-
-/**
- * This must be kept manually in sync with system/security/keystore until AIDL
- * can generate both Java and C++ bindings.
- *
- * @hide
- */
-interface IConfirmationPromptCallback {
-    oneway void onConfirmationPromptCompleted(in int result, in byte[] dataThatWasConfirmed);
-}
diff --git a/core/java/android/security/IKeystoreService.aidl b/core/java/android/security/IKeystoreService.aidl
deleted file mode 100644
index 738eb68..0000000
--- a/core/java/android/security/IKeystoreService.aidl
+++ /dev/null
@@ -1,87 +0,0 @@
-/**
- * Copyright (c) 2015, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.security;
-
-import android.security.keymaster.ExportResult;
-import android.security.keymaster.KeyCharacteristics;
-import android.security.keymaster.KeymasterArguments;
-import android.security.keymaster.KeymasterCertificateChain;
-import android.security.keymaster.KeymasterBlob;
-import android.security.keymaster.OperationResult;
-import android.security.KeystoreArguments;
-
-/**
- * This must be kept manually in sync with system/security/keystore until AIDL
- * can generate both Java and C++ bindings.
- *
- * @hide
- */
-interface IKeystoreService {
-    int getState(int userId);
-    byte[] get(String name, int uid);
-    int insert(String name, in byte[] item, int uid, int flags);
-    int del(String name, int uid);
-    int exist(String name, int uid);
-    String[] list(String namePrefix, int uid);
-    int reset();
-    int onUserPasswordChanged(int userId, String newPassword);
-    int lock(int userId);
-    int unlock(int userId, String userPassword);
-    int isEmpty(int userId);
-    int generate(String name, int uid, int keyType, int keySize, int flags,
-        in KeystoreArguments args);
-    int import_key(String name, in byte[] data, int uid, int flags);
-    byte[] sign(String name, in byte[] data);
-    int verify(String name, in byte[] data, in byte[] signature);
-    byte[] get_pubkey(String name);
-    String grant(String name, int granteeUid);
-    int ungrant(String name, int granteeUid);
-    long getmtime(String name, int uid);
-    int is_hardware_backed(String string);
-    int clear_uid(long uid);
-
-    // Keymaster 0.4 methods
-    int addRngEntropy(in byte[] data, int flags);
-    int generateKey(String alias, in KeymasterArguments arguments, in byte[] entropy, int uid,
-        int flags, out KeyCharacteristics characteristics);
-    int getKeyCharacteristics(String alias, in KeymasterBlob clientId, in KeymasterBlob appId,
-        int uid, out KeyCharacteristics characteristics);
-    int importKey(String alias, in KeymasterArguments arguments, int format,
-        in byte[] keyData, int uid, int flags, out KeyCharacteristics characteristics);
-    ExportResult exportKey(String alias, int format, in KeymasterBlob clientId,
-        in KeymasterBlob appId, int uid);
-    OperationResult begin(IBinder appToken, String alias, int purpose, boolean pruneable,
-        in KeymasterArguments params, in byte[] entropy, int uid);
-    OperationResult update(IBinder token, in KeymasterArguments params, in byte[] input);
-    OperationResult finish(IBinder token, in KeymasterArguments params, in byte[] signature,
-        in byte[] entropy);
-    int abort(IBinder handle);
-    boolean isOperationAuthorized(IBinder token);
-    int addAuthToken(in byte[] authToken);
-    int onUserAdded(int userId, int parentId);
-    int onUserRemoved(int userId);
-    int attestKey(String alias, in KeymasterArguments params, out KeymasterCertificateChain chain);
-    int attestDeviceIds(in KeymasterArguments params, out KeymasterCertificateChain chain);
-    int onDeviceOffBody();
-    int importWrappedKey(in String wrappedKeyAlias, in byte[] wrappedKey,
-        in String wrappingKeyAlias, in byte[] maskingKey, in KeymasterArguments arguments,
-        in long rootSid, in long fingerprintSid,
-        out KeyCharacteristics characteristics);
-    int presentConfirmationPrompt(IBinder listener, String promptText, in byte[] extraData,
-        in String locale, in int uiOptionsAsFlags);
-    int cancelConfirmationPrompt(IBinder listener);
-}
diff --git a/core/java/android/security/KeystoreArguments.aidl b/core/java/android/security/KeystoreArguments.aidl
deleted file mode 100644
index dc8ed50..0000000
--- a/core/java/android/security/KeystoreArguments.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/**
- * Copyright (c) 2015, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.security;
-
-/* @hide */
-parcelable KeystoreArguments cpp_header "keystore/KeystoreArguments.h";
diff --git a/core/java/android/security/keymaster/ExportResult.aidl b/core/java/android/security/keymaster/ExportResult.aidl
deleted file mode 100644
index 1748653..0000000
--- a/core/java/android/security/keymaster/ExportResult.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.security.keymaster;
-
-/* @hide */
-parcelable ExportResult cpp_header "keystore/ExportResult.h";
diff --git a/core/java/android/security/keymaster/KeyCharacteristics.aidl b/core/java/android/security/keymaster/KeyCharacteristics.aidl
deleted file mode 100644
index 32e75ad..0000000
--- a/core/java/android/security/keymaster/KeyCharacteristics.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.security.keymaster;
-
-/* @hide */
-parcelable KeyCharacteristics cpp_header "keystore/KeyCharacteristics.h";
diff --git a/core/java/android/security/keymaster/KeymasterArguments.aidl b/core/java/android/security/keymaster/KeymasterArguments.aidl
deleted file mode 100644
index 44d9f09..0000000
--- a/core/java/android/security/keymaster/KeymasterArguments.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.security.keymaster;
-
-/* @hide */
-parcelable KeymasterArguments cpp_header "keystore/KeymasterArguments.h";
diff --git a/core/java/android/security/keymaster/KeymasterBlob.aidl b/core/java/android/security/keymaster/KeymasterBlob.aidl
deleted file mode 100644
index 5c5db9e..0000000
--- a/core/java/android/security/keymaster/KeymasterBlob.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.security.keymaster;
-
-/* @hide */
-parcelable KeymasterBlob cpp_header "keystore/KeymasterBlob.h";
diff --git a/core/java/android/security/keymaster/KeymasterCertificateChain.aidl b/core/java/android/security/keymaster/KeymasterCertificateChain.aidl
deleted file mode 100644
index ddb5cae..0000000
--- a/core/java/android/security/keymaster/KeymasterCertificateChain.aidl
+++ /dev/null
@@ -1,20 +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 android.security.keymaster;
-
-/* @hide */
-parcelable KeymasterCertificateChain cpp_header "keystore/KeymasterCertificateChain.h";
diff --git a/core/java/android/security/keymaster/KeymasterDefs.java b/core/java/android/security/keymaster/KeymasterDefs.java
index 1d13335..f4dcce1 100644
--- a/core/java/android/security/keymaster/KeymasterDefs.java
+++ b/core/java/android/security/keymaster/KeymasterDefs.java
@@ -75,6 +75,7 @@
     public static final int KM_TAG_ALLOW_WHILE_ON_BODY = KM_BOOL | 506;
     public static final int KM_TAG_TRUSTED_USER_PRESENCE_REQUIRED = KM_BOOL | 507;
     public static final int KM_TAG_TRUSTED_CONFIRMATION_REQUIRED = KM_BOOL | 508;
+    public static final int KM_TAG_UNLOCKED_DEVICE_REQUIRED = KM_BOOL | 509;
 
     public static final int KM_TAG_ALL_APPLICATIONS = KM_BOOL | 600;
     public static final int KM_TAG_APPLICATION_ID = KM_BYTES | 601;
@@ -216,6 +217,7 @@
     public static final int KM_ERROR_MISSING_MIN_MAC_LENGTH = -58;
     public static final int KM_ERROR_UNSUPPORTED_MIN_MAC_LENGTH = -59;
     public static final int KM_ERROR_CANNOT_ATTEST_IDS = -66;
+    public static final int KM_ERROR_DEVICE_LOCKED = -72;
     public static final int KM_ERROR_UNIMPLEMENTED = -100;
     public static final int KM_ERROR_VERSION_MISMATCH = -101;
     public static final int KM_ERROR_UNKNOWN_ERROR = -1000;
@@ -262,6 +264,7 @@
         sErrorCodeToString.put(KM_ERROR_INVALID_MAC_LENGTH,
                 "Invalid MAC or authentication tag length");
         sErrorCodeToString.put(KM_ERROR_CANNOT_ATTEST_IDS, "Unable to attest device ids");
+        sErrorCodeToString.put(KM_ERROR_DEVICE_LOCKED, "Device locked");
         sErrorCodeToString.put(KM_ERROR_UNIMPLEMENTED, "Not implemented");
         sErrorCodeToString.put(KM_ERROR_UNKNOWN_ERROR, "Unknown error");
     }
diff --git a/core/java/android/security/keymaster/OperationResult.aidl b/core/java/android/security/keymaster/OperationResult.aidl
deleted file mode 100644
index db689d4..0000000
--- a/core/java/android/security/keymaster/OperationResult.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.security.keymaster;
-
-/* @hide */
-parcelable OperationResult cpp_header "keystore/OperationResult.h";
diff --git a/core/java/android/security/keystore/OWNERS b/core/java/android/security/keystore/OWNERS
new file mode 100644
index 0000000..bb487fb
--- /dev/null
+++ b/core/java/android/security/keystore/OWNERS
@@ -0,0 +1,4 @@
+aseemk@google.com
+bozhu@google.com
+dementyev@google.com
+robertberry@google.com
diff --git a/core/java/android/service/autofill/AutofillServiceInfo.java b/core/java/android/service/autofill/AutofillServiceInfo.java
index 29c6cea..70c4ec0 100644
--- a/core/java/android/service/autofill/AutofillServiceInfo.java
+++ b/core/java/android/service/autofill/AutofillServiceInfo.java
@@ -32,19 +32,19 @@
 import android.util.ArrayMap;
 import android.util.AttributeSet;
 import android.util.Log;
+import android.util.Pair;
 import android.util.Xml;
 
 import com.android.internal.R;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-
 import com.android.internal.util.XmlUtils;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
 import java.io.IOException;
-import java.util.Map;
+import java.io.PrintWriter;
 
 /**
  * {@link ServiceInfo} and meta-data about an {@link AutofillService}.
@@ -79,7 +79,7 @@
     private final String mSettingsActivity;
 
     @Nullable
-    private final Map<String, Long> mCompatibilityPackages;
+    private final ArrayMap<String, Pair<Long, String>> mCompatibilityPackages;
 
     public AutofillServiceInfo(Context context, ComponentName comp, int userHandle)
             throws PackageManager.NameNotFoundException {
@@ -117,7 +117,7 @@
         }
 
         String settingsActivity = null;
-        Map<String, Long> compatibilityPackages = null;
+        ArrayMap<String, Pair<Long, String>> compatibilityPackages = null;
 
         try {
             final Resources resources = context.getPackageManager().getResourcesForApplication(
@@ -153,9 +153,10 @@
         mCompatibilityPackages = compatibilityPackages;
     }
 
-    private Map<String, Long> parseCompatibilityPackages(XmlPullParser parser, Resources resources)
+    private ArrayMap<String, Pair<Long, String>> parseCompatibilityPackages(XmlPullParser parser,
+            Resources resources)
             throws IOException, XmlPullParserException {
-        Map<String, Long> compatibilityPackages = null;
+        ArrayMap<String, Pair<Long, String>> compatibilityPackages = null;
 
         final int outerDepth = parser.getDepth();
         int type;
@@ -199,11 +200,13 @@
                     } else {
                         maxVersionCode = Long.MAX_VALUE;
                     }
+                    final String urlBarResourceId = cpAttributes.getString(
+                            R.styleable.AutofillService_CompatibilityPackage_urlBarResourceId);
 
                     if (compatibilityPackages == null) {
                         compatibilityPackages = new ArrayMap<>();
                     }
-                    compatibilityPackages.put(name, maxVersionCode);
+                    compatibilityPackages.put(name, new Pair<>(maxVersionCode, urlBarResourceId));
                 } finally {
                     XmlUtils.skipCurrentTag(parser);
                     if (cpAttributes != null) {
@@ -225,16 +228,21 @@
         return mSettingsActivity;
     }
 
+    public ArrayMap<String, Pair<Long, String>> getCompatibilityPackages() {
+        return mCompatibilityPackages;
+    }
+
+    /**
+     * Gets the resource id of the URL bar for a package. Used in compat mode
+     */
+    // TODO: return a list of strings instead
     @Nullable
-    public boolean isCompatibilityModeRequested(String packageName, long versionCode) {
+    public String getUrlBarResourceId(String packageName) {
         if (mCompatibilityPackages == null) {
-            return false;
+            return null;
         }
-        final Long maxVersionCode = mCompatibilityPackages.get(packageName);
-        if (maxVersionCode == null) {
-            return false;
-        }
-        return versionCode <= maxVersionCode;
+        final Pair<Long, String> pair = mCompatibilityPackages.get(packageName);
+        return pair == null ? null : pair.second;
     }
 
     @Override
@@ -247,4 +255,13 @@
                 && !mCompatibilityPackages.isEmpty()).append("]");
         return builder.toString();
     }
+
+    /**
+     * Dumps it!
+     */
+    public void dump(String prefix, PrintWriter pw) {
+        pw.print(prefix); pw.print("Component: "); pw.println(getServiceInfo().getComponentName());
+        pw.print(prefix); pw.print("Settings: "); pw.println(mSettingsActivity);
+        pw.print(prefix); pw.print("Compat packages: "); pw.println(mCompatibilityPackages);
+    }
 }
diff --git a/core/java/android/service/autofill/DateTransformation.java b/core/java/android/service/autofill/DateTransformation.java
index 4e1425d..ec24a09 100644
--- a/core/java/android/service/autofill/DateTransformation.java
+++ b/core/java/android/service/autofill/DateTransformation.java
@@ -20,6 +20,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.TestApi;
+import android.icu.text.DateFormat;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.Log;
@@ -30,7 +31,6 @@
 
 import com.android.internal.util.Preconditions;
 
-import java.text.DateFormat;
 import java.util.Date;
 
 /**
diff --git a/core/java/android/service/autofill/DateValueSanitizer.java b/core/java/android/service/autofill/DateValueSanitizer.java
index 0f7b540..4f797f4 100644
--- a/core/java/android/service/autofill/DateValueSanitizer.java
+++ b/core/java/android/service/autofill/DateValueSanitizer.java
@@ -21,6 +21,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.TestApi;
+import android.icu.text.DateFormat;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.Log;
@@ -28,7 +29,6 @@
 
 import com.android.internal.util.Preconditions;
 
-import java.text.DateFormat;
 import java.util.Date;
 
 /**
diff --git a/core/java/android/service/autofill/FieldClassification.java b/core/java/android/service/autofill/FieldClassification.java
index cd1efd6..5bf56cb9 100644
--- a/core/java/android/service/autofill/FieldClassification.java
+++ b/core/java/android/service/autofill/FieldClassification.java
@@ -108,21 +108,21 @@
      */
     public static final class Match {
 
-        private final String mRemoteId;
+        private final String mCategoryId;
         private final float mScore;
 
         /** @hide */
-        public Match(String remoteId, float score) {
-            mRemoteId = Preconditions.checkNotNull(remoteId);
+        public Match(String categoryId, float score) {
+            mCategoryId = Preconditions.checkNotNull(categoryId);
             mScore = score;
         }
 
         /**
-         * Gets the remote id of the {@link UserData} entry.
+         * Gets the category id of the {@link UserData} entry.
          */
         @NonNull
-        public String getRemoteId() {
-            return mRemoteId;
+        public String getCategoryId() {
+            return mCategoryId;
         }
 
         /**
@@ -149,13 +149,13 @@
         public String toString() {
             if (!sDebug) return super.toString();
 
-            final StringBuilder string = new StringBuilder("Match: remoteId=");
-            Helper.appendRedacted(string, mRemoteId);
+            final StringBuilder string = new StringBuilder("Match: categoryId=");
+            Helper.appendRedacted(string, mCategoryId);
             return string.append(", score=").append(mScore).toString();
         }
 
         private void writeToParcel(@NonNull Parcel parcel) {
-            parcel.writeString(mRemoteId);
+            parcel.writeString(mCategoryId);
             parcel.writeFloat(mScore);
         }
 
diff --git a/core/java/android/service/autofill/FillContext.java b/core/java/android/service/autofill/FillContext.java
index cda2f4a..535c00b 100644
--- a/core/java/android/service/autofill/FillContext.java
+++ b/core/java/android/service/autofill/FillContext.java
@@ -177,30 +177,6 @@
         return foundNodes;
     }
 
-    /**
-     * Finds the {@link ViewNode} that has the requested {@code id}, if any.
-     *
-     * @hide
-     */
-    @Nullable public ViewNode findViewNodeByAutofillId(@NonNull AutofillId id) {
-        final LinkedList<ViewNode> nodesToProcess = new LinkedList<>();
-        final int numWindowNodes = mStructure.getWindowNodeCount();
-        for (int i = 0; i < numWindowNodes; i++) {
-            nodesToProcess.add(mStructure.getWindowNodeAt(i).getRootViewNode());
-        }
-        while (!nodesToProcess.isEmpty()) {
-            final ViewNode node = nodesToProcess.removeFirst();
-            if (id.equals(node.getAutofillId())) {
-                return node;
-            }
-            for (int i = 0; i < node.getChildCount(); i++) {
-                nodesToProcess.addLast(node.getChildAt(i));
-            }
-        }
-
-        return null;
-    }
-
     public static final Parcelable.Creator<FillContext> CREATOR =
             new Parcelable.Creator<FillContext>() {
         @Override
diff --git a/core/java/android/service/autofill/UserData.java b/core/java/android/service/autofill/UserData.java
index 6bab6aa..a1dd1f8 100644
--- a/core/java/android/service/autofill/UserData.java
+++ b/core/java/android/service/autofill/UserData.java
@@ -15,6 +15,7 @@
  */
 package android.service.autofill;
 
+import static android.provider.Settings.Secure.AUTOFILL_USER_DATA_MAX_CATEGORY_COUNT;
 import static android.provider.Settings.Secure.AUTOFILL_USER_DATA_MAX_FIELD_CLASSIFICATION_IDS_SIZE;
 import static android.provider.Settings.Secure.AUTOFILL_USER_DATA_MAX_USER_DATA_SIZE;
 import static android.provider.Settings.Secure.AUTOFILL_USER_DATA_MAX_VALUE_LENGTH;
@@ -31,6 +32,7 @@
 import android.provider.Settings;
 import android.service.autofill.FieldClassification.Match;
 import android.text.TextUtils;
+import android.util.ArraySet;
 import android.util.Log;
 import android.view.autofill.AutofillManager;
 import android.view.autofill.Helper;
@@ -48,23 +50,24 @@
 
     private static final String TAG = "UserData";
 
-    private static final int DEFAULT_MAX_USER_DATA_SIZE = 10;
+    private static final int DEFAULT_MAX_USER_DATA_SIZE = 50;
+    private static final int DEFAULT_MAX_CATEGORY_COUNT = 10;
     private static final int DEFAULT_MAX_FIELD_CLASSIFICATION_IDS_SIZE = 10;
-    private static final int DEFAULT_MIN_VALUE_LENGTH = 5;
+    private static final int DEFAULT_MIN_VALUE_LENGTH = 3;
     private static final int DEFAULT_MAX_VALUE_LENGTH = 100;
 
     private final String mId;
     private final String mAlgorithm;
     private final Bundle mAlgorithmArgs;
-    private final String[] mRemoteIds;
+    private final String[] mCategoryIds;
     private final String[] mValues;
 
     private UserData(Builder builder) {
         mId = builder.mId;
         mAlgorithm = builder.mAlgorithm;
         mAlgorithmArgs = builder.mAlgorithmArgs;
-        mRemoteIds = new String[builder.mRemoteIds.size()];
-        builder.mRemoteIds.toArray(mRemoteIds);
+        mCategoryIds = new String[builder.mCategoryIds.size()];
+        builder.mCategoryIds.toArray(mCategoryIds);
         mValues = new String[builder.mValues.size()];
         builder.mValues.toArray(mValues);
     }
@@ -91,8 +94,8 @@
     }
 
     /** @hide */
-    public String[] getRemoteIds() {
-        return mRemoteIds;
+    public String[] getCategoryIds() {
+        return mCategoryIds;
     }
 
     /** @hide */
@@ -106,11 +109,11 @@
         pw.print(prefix); pw.print("Algorithm: "); pw.print(mAlgorithm);
         pw.print(" Args: "); pw.println(mAlgorithmArgs);
 
-        // Cannot disclose remote ids or values because they could contain PII
-        pw.print(prefix); pw.print("Remote ids size: "); pw.println(mRemoteIds.length);
-        for (int i = 0; i < mRemoteIds.length; i++) {
+        // Cannot disclose field ids or values because they could contain PII
+        pw.print(prefix); pw.print("Field ids size: "); pw.println(mCategoryIds.length);
+        for (int i = 0; i < mCategoryIds.length; i++) {
             pw.print(prefix); pw.print(prefix); pw.print(i); pw.print(": ");
-            pw.println(Helper.getRedacted(mRemoteIds[i]));
+            pw.println(Helper.getRedacted(mCategoryIds[i]));
         }
         pw.print(prefix); pw.print("Values size: "); pw.println(mValues.length);
         for (int i = 0; i < mValues.length; i++) {
@@ -124,6 +127,7 @@
         pw.print(prefix); pw.print("maxUserDataSize: "); pw.println(getMaxUserDataSize());
         pw.print(prefix); pw.print("maxFieldClassificationIdsSize: ");
         pw.println(getMaxFieldClassificationIdsSize());
+        pw.print(prefix); pw.print("maxCategoryCount: "); pw.println(getMaxCategoryCount());
         pw.print(prefix); pw.print("minValueLength: "); pw.println(getMinValueLength());
         pw.print(prefix); pw.print("maxValueLength: "); pw.println(getMaxValueLength());
     }
@@ -133,44 +137,59 @@
      */
     public static final class Builder {
         private final String mId;
-        private final ArrayList<String> mRemoteIds;
+        private final ArrayList<String> mCategoryIds;
         private final ArrayList<String> mValues;
         private String mAlgorithm;
         private Bundle mAlgorithmArgs;
         private boolean mDestroyed;
 
+        // Non-persistent array used to limit the number of unique ids.
+        private final ArraySet<String> mUniqueCategoryIds;
+
         /**
          * Creates a new builder for the user data used for <a href="#FieldClassification">field
          * classification</a>.
          *
-         * <p>The user data must contain at least one pair of {@code remoteId} -> {@code value}, and
-         * more pairs can be added through the {@link #add(String, String)} method.
+         * <p>The user data must contain at least one pair of {@code value} -> {@code categoryId},
+         * and more pairs can be added through the {@link #add(String, String)} method. For example:
+         *
+         * <pre class="prettyprint">
+         * new UserData.Builder("v1", "Bart Simpson", "name")
+         *   .add("bart.simpson@example.com", "email")
+         *   .add("el_barto@example.com", "email")
+         *   .build();
+         * </pre>
          *
          * @param id id used to identify the whole {@link UserData} object. This id is also returned
          * by {@link AutofillManager#getUserDataId()}, which can be used to check if the
          * {@link UserData} is up-to-date without fetching the whole object (through
          * {@link AutofillManager#getUserData()}).
-         * @param remoteId unique string used to identify a user data value.
+         *
          * @param value value of the user data.
+         * @param categoryId string used to identify the category the value is associated with.
          *
          * @throws IllegalArgumentException if any of the following occurs:
          * <ol>
-         *   <li>{@code id} is empty
-         *   <li>{@code remoteId} is empty
-         *   <li>{@code value} is empty
-         *   <li>the length of {@code value} is lower than {@link UserData#getMinValueLength()}
-         *   <li>the length of {@code value} is higher than {@link UserData#getMaxValueLength()}
+         *   <li>{@code id} is empty</li>
+         *   <li>{@code categoryId} is empty</li>
+         *   <li>{@code value} is empty</li>
+         *   <li>the length of {@code value} is lower than {@link UserData#getMinValueLength()}</li>
+         *   <li>the length of {@code value} is higher than
+         *       {@link UserData#getMaxValueLength()}</li>
          * </ol>
+         *
          */
-        public Builder(@NonNull String id, @NonNull String remoteId, @NonNull String value) {
+        // TODO(b/70407264): ignore entry instead of throwing exception when settings changed
+        public Builder(@NonNull String id, @NonNull String value, @NonNull String categoryId) {
             mId = checkNotEmpty("id", id);
-            checkNotEmpty("remoteId", remoteId);
+            checkNotEmpty("categoryId", categoryId);
             checkValidValue(value);
-            final int capacity = getMaxUserDataSize();
-            mRemoteIds = new ArrayList<>(capacity);
-            mValues = new ArrayList<>(capacity);
-            mRemoteIds.add(remoteId);
-            mValues.add(value);
+            final int maxUserDataSize = getMaxUserDataSize();
+            mCategoryIds = new ArrayList<>(maxUserDataSize);
+            mValues = new ArrayList<>(maxUserDataSize);
+            mUniqueCategoryIds = new ArraySet<>(getMaxCategoryCount());
+
+            addMapping(value, categoryId);
         }
 
         /**
@@ -190,6 +209,7 @@
          */
         public Builder setFieldClassificationAlgorithm(@Nullable String name,
                 @Nullable Bundle args) {
+            throwIfDestroyed();
             mAlgorithm = name;
             mAlgorithmArgs = args;
             return this;
@@ -198,37 +218,58 @@
         /**
          * Adds a new value for user data.
          *
-         * @param remoteId unique string used to identify the user data.
          * @param value value of the user data.
+         * @param categoryId string used to identify the category the value is associated with.
          *
-         * @throws IllegalStateException if {@link #build()} or
-         * {@link #add(String, String)} with the same {@code remoteId} has already
-         * been called, or if the number of values add (i.e., calls made to this method plus
-         * constructor) is more than {@link UserData#getMaxUserDataSize()}.
+         * @throws IllegalStateException if:
+         * <ol>
+         *   <li>{@link #build()} already called</li>
+         *   <li>the {@code value} has already been added</li>
+         *   <li>the number of unique {@code categoryId} values added so far is more than
+         *       {@link UserData#getMaxCategoryCount()}</li>
+         *   <li>the number of {@code values} added so far is is more than
+         *       {@link UserData#getMaxUserDataSize()}</li>
+         * </ol>
          *
-         * @throws IllegalArgumentException if {@code remoteId} or {@code value} are empty or if the
-         * length of {@code value} is lower than {@link UserData#getMinValueLength()}
-         * or higher than {@link UserData#getMaxValueLength()}.
+         * @throws IllegalArgumentException if any of the following occurs:
+         * <ol>
+         *   <li>{@code id} is empty</li>
+         *   <li>{@code categoryId} is empty</li>
+         *   <li>{@code value} is empty</li>
+         *   <li>the length of {@code value} is lower than {@link UserData#getMinValueLength()}</li>
+         *   <li>the length of {@code value} is higher than
+         *       {@link UserData#getMaxValueLength()}</li>
+         * </ol>
          */
-        public Builder add(@NonNull String remoteId, @NonNull String value) {
+        // TODO(b/70407264): ignore entry instead of throwing exception when settings changed
+        public Builder add(@NonNull String value, @NonNull String categoryId) {
             throwIfDestroyed();
-            checkNotEmpty("remoteId", remoteId);
+            checkNotEmpty("categoryId", categoryId);
             checkValidValue(value);
 
-            Preconditions.checkState(!mRemoteIds.contains(remoteId),
-                    // Don't include remoteId on message because it could contain PII
-                    "already has entry with same remoteId");
+            if (!mUniqueCategoryIds.contains(categoryId)) {
+                // New category - check size
+                Preconditions.checkState(mUniqueCategoryIds.size() < getMaxCategoryCount(),
+                        "already added " + mUniqueCategoryIds.size() + " unique category ids");
+
+            }
+
             Preconditions.checkState(!mValues.contains(value),
-                    // Don't include remoteId on message because it could contain PII
+                    // Don't include value on message because it could contain PII
                     "already has entry with same value");
-            Preconditions.checkState(mRemoteIds.size() < getMaxUserDataSize(),
-                    "already added " + mRemoteIds.size() + " elements");
-            mRemoteIds.add(remoteId);
-            mValues.add(value);
+            Preconditions.checkState(mValues.size() < getMaxUserDataSize(),
+                    "already added " + mValues.size() + " elements");
+            addMapping(value, categoryId);
 
             return this;
         }
 
+        private void addMapping(@NonNull String value, @NonNull String categoryId) {
+            mCategoryIds.add(categoryId);
+            mValues.add(value);
+            mUniqueCategoryIds.add(categoryId);
+        }
+
         private String checkNotEmpty(@NonNull String name, @Nullable String value) {
             Preconditions.checkNotNull(value);
             Preconditions.checkArgument(!TextUtils.isEmpty(value), "%s cannot be empty", name);
@@ -273,9 +314,9 @@
 
         final StringBuilder builder = new StringBuilder("UserData: [id=").append(mId)
                 .append(", algorithm=").append(mAlgorithm);
-        // Cannot disclose remote ids or values because they could contain PII
-        builder.append(", remoteIds=");
-        Helper.appendRedacted(builder, mRemoteIds);
+        // Cannot disclose category ids or values because they could contain PII
+        builder.append(", categoryIds=");
+        Helper.appendRedacted(builder, mCategoryIds);
         builder.append(", values=");
         Helper.appendRedacted(builder, mValues);
         return builder.append("]").toString();
@@ -293,7 +334,7 @@
     @Override
     public void writeToParcel(Parcel parcel, int flags) {
         parcel.writeString(mId);
-        parcel.writeStringArray(mRemoteIds);
+        parcel.writeStringArray(mCategoryIds);
         parcel.writeStringArray(mValues);
         parcel.writeString(mAlgorithm);
         parcel.writeBundle(mAlgorithmArgs);
@@ -307,12 +348,12 @@
             // the system obeys the contract of the builder to avoid attacks
             // using specially crafted parcels.
             final String id = parcel.readString();
-            final String[] remoteIds = parcel.readStringArray();
+            final String[] categoryIds = parcel.readStringArray();
             final String[] values = parcel.readStringArray();
-            final Builder builder = new Builder(id, remoteIds[0], values[0])
+            final Builder builder = new Builder(id, values[0], categoryIds[0])
                     .setFieldClassificationAlgorithm(parcel.readString(), parcel.readBundle());
-            for (int i = 1; i < remoteIds.length; i++) {
-                builder.add(remoteIds[i], values[i]);
+            for (int i = 1; i < categoryIds.length; i++) {
+                builder.add(values[i], categoryIds[i]);
             }
             return builder.build();
         }
@@ -340,6 +381,14 @@
     }
 
     /**
+     * Gets the maximum number of unique category ids that can be passed to
+     * the builder's constructor and {@link Builder#add(String, String)}.
+     */
+    public static int getMaxCategoryCount() {
+        return getInt(AUTOFILL_USER_DATA_MAX_CATEGORY_COUNT, DEFAULT_MAX_CATEGORY_COUNT);
+    }
+
+    /**
      * Gets the minimum length of values passed to the builder's constructor or
      * or {@link Builder#add(String, String)}.
      */
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/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index b7b2b2d..422e36b 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -1343,6 +1343,7 @@
     /**
      * @hide
      */
+    @GuardedBy("mLock")
     public final void applyUpdateLocked(NotificationRankingUpdate update) {
         mRankingMap = new RankingMap(update);
     }
diff --git a/core/java/android/service/notification/ZenModeConfig.java b/core/java/android/service/notification/ZenModeConfig.java
index d66322c..171d4d9 100644
--- a/core/java/android/service/notification/ZenModeConfig.java
+++ b/core/java/android/service/notification/ZenModeConfig.java
@@ -94,7 +94,7 @@
     private static final boolean DEFAULT_ALLOW_SCREEN_OFF = true;
     private static final boolean DEFAULT_ALLOW_SCREEN_ON = true;
 
-    private static final int XML_VERSION = 2;
+    public static final int XML_VERSION = 3;
     public static final String ZEN_TAG = "zen";
     private static final String ZEN_ATT_VERSION = "version";
     private static final String ZEN_ATT_USER = "user";
@@ -145,6 +145,7 @@
     public int user = UserHandle.USER_SYSTEM;
     public boolean allowWhenScreenOff = DEFAULT_ALLOW_SCREEN_OFF;
     public boolean allowWhenScreenOn = DEFAULT_ALLOW_SCREEN_ON;
+    public int version;
 
     public ZenRule manualRule;
     public ArrayMap<String, ZenRule> automaticRules = new ArrayMap<>();
@@ -431,6 +432,7 @@
         String tag = parser.getName();
         if (!ZEN_TAG.equals(tag)) return null;
         final ZenModeConfig rt = new ZenModeConfig();
+        rt.version = safeInt(parser, ZEN_ATT_VERSION, XML_VERSION);
         rt.user = safeInt(parser, ZEN_ATT_USER, rt.user);
         while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) {
             tag = parser.getName();
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/OWNERS b/core/java/android/text/OWNERS
index 0f85e1f..e561371 100644
--- a/core/java/android/text/OWNERS
+++ b/core/java/android/text/OWNERS
@@ -1,4 +1,5 @@
+set noparent
+
 siyamed@google.com
 nona@google.com
 clarabayarri@google.com
-toki@google.com
diff --git a/core/java/android/text/style/TypefaceSpan.java b/core/java/android/text/style/TypefaceSpan.java
index 1622812..908de29 100644
--- a/core/java/android/text/style/TypefaceSpan.java
+++ b/core/java/android/text/style/TypefaceSpan.java
@@ -17,6 +17,8 @@
 package android.text.style;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.graphics.LeakyTypefaceStorage;
 import android.graphics.Paint;
 import android.graphics.Typeface;
 import android.os.Parcel;
@@ -25,33 +27,69 @@
 import android.text.TextUtils;
 
 /**
- * Changes the typeface family of the text to which the span is attached. Examples of typeface
- * family include "monospace", "serif", and "sans-serif".
+ * Span that updates the typeface of the text it's attached to. The <code>TypefaceSpan</code> can
+ * be constructed either based on a font family or based on a <code>Typeface</code>. When
+ * {@link #TypefaceSpan(String)} is used, the previous style of the <code>TextView</code> is kept.
+ * When {@link #TypefaceSpan(Typeface)} is used, the <code>Typeface</code> style replaces the
+ * <code>TextView</code>'s style.
  * <p>
- * For example, change the typeface of a text to "monospace" like this:
+ * For example, let's consider a <code>TextView</code> with
+ * <code>android:textStyle="italic"</code> and a typeface created based on a font from resources,
+ * with a bold style. When applying a <code>TypefaceSpan</code> based the typeface, the text will
+ * only keep the bold style, overriding the <code>TextView</code>'s textStyle. When applying a
+ * <code>TypefaceSpan</code> based on a font family: "monospace", the resulted text will keep the
+ * italic style.
  * <pre>
- * SpannableString string = new SpannableString("Text with typeface span");
- * string.setSpan(new TypefaceSpan("monospace"), 10, 18, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ * Typeface myTypeface = Typeface.create(ResourcesCompat.getFont(context, R.font.acme),
+ * Typeface.BOLD);
+ * SpannableString string = new SpannableString("Text with typeface span.");
+ * string.setSpan(new TypefaceSpan(myTypeface), 10, 18, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+ * string.setSpan(new TypefaceSpan("monospace"), 19, 22, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
  * </pre>
  * <img src="{@docRoot}reference/android/images/text/style/typefacespan.png" />
- * <figcaption>Text with "monospace" typeface family.</figcaption>
+ * <figcaption>Text with <code>TypefaceSpan</code>s constructed based on a font from resource and
+ * from a font family.</figcaption>
  */
 public class TypefaceSpan extends MetricAffectingSpan implements ParcelableSpan {
 
+    @Nullable
     private final String mFamily;
 
+    @Nullable
+    private final Typeface mTypeface;
+
     /**
-     * Constructs a {@link TypefaceSpan} based on a font family.
+     * Constructs a {@link TypefaceSpan} based on the font family. The previous style of the
+     * TextPaint is kept. If the font family is null, the text paint is not modified.
      *
-     * @param family The font family for this typeface. Examples include
-     *               "monospace", "serif", and "sans-serif".
+     * @param family The font family for this typeface.  Examples include
+     *               "monospace", "serif", and "sans-serif"
      */
-    public TypefaceSpan(String family) {
-        mFamily = family;
+    public TypefaceSpan(@Nullable String family) {
+        this(family, null);
     }
 
+    /**
+     * Constructs a {@link TypefaceSpan} from a {@link Typeface}. The previous style of the
+     * TextPaint is overridden and the style of the typeface is used.
+     *
+     * @param typeface the typeface
+     */
+    public TypefaceSpan(@NonNull Typeface typeface) {
+        this(null, typeface);
+    }
+
+    /**
+     * Constructs a {@link TypefaceSpan} from a  parcel.
+     */
     public TypefaceSpan(@NonNull Parcel src) {
         mFamily = src.readString();
+        mTypeface = LeakyTypefaceStorage.readTypefaceFromParcel(src);
+    }
+
+    private TypefaceSpan(@Nullable String family, @Nullable Typeface typeface) {
+        mFamily = family;
+        mTypeface = typeface;
     }
 
     @Override
@@ -79,37 +117,59 @@
     @Override
     public void writeToParcelInternal(@NonNull Parcel dest, int flags) {
         dest.writeString(mFamily);
+        LeakyTypefaceStorage.writeTypefaceToParcel(mTypeface, dest);
     }
 
     /**
-     * Returns the font family name.
+     * Returns the font family name set in the span.
+     *
+     * @return the font family name
+     * @see #TypefaceSpan(String)
      */
+    @Nullable
     public String getFamily() {
         return mFamily;
     }
 
-    @Override
-    public void updateDrawState(@NonNull TextPaint textPaint) {
-        apply(textPaint, mFamily);
+    /**
+     * Returns the typeface set in the span.
+     *
+     * @return the typeface set
+     * @see #TypefaceSpan(Typeface)
+     */
+    @Nullable
+    public Typeface getTypeface() {
+        return mTypeface;
     }
 
     @Override
-    public void updateMeasureState(@NonNull TextPaint textPaint) {
-        apply(textPaint, mFamily);
+    public void updateDrawState(@NonNull TextPaint ds) {
+        updateTypeface(ds);
     }
 
-    private static void apply(@NonNull Paint paint, String family) {
-        int oldStyle;
+    @Override
+    public void updateMeasureState(@NonNull TextPaint paint) {
+        updateTypeface(paint);
+    }
 
+    private void updateTypeface(@NonNull Paint paint) {
+        if (mTypeface != null) {
+            paint.setTypeface(mTypeface);
+        } else if (mFamily != null) {
+            applyFontFamily(paint, mFamily);
+        }
+    }
+
+    private void applyFontFamily(@NonNull Paint paint, @NonNull String family) {
+        int style;
         Typeface old = paint.getTypeface();
         if (old == null) {
-            oldStyle = 0;
+            style = Typeface.NORMAL;
         } else {
-            oldStyle = old.getStyle();
+            style = old.getStyle();
         }
-
-        Typeface tf = Typeface.create(family, oldStyle);
-        int fake = oldStyle & ~tf.getStyle();
+        final Typeface styledTypeface = Typeface.create(family, style);
+        int fake = style & ~styledTypeface.getStyle();
 
         if ((fake & Typeface.BOLD) != 0) {
             paint.setFakeBoldText(true);
@@ -118,7 +178,6 @@
         if ((fake & Typeface.ITALIC) != 0) {
             paint.setTextSkewX(-0.25f);
         }
-
-        paint.setTypeface(tf);
+        paint.setTypeface(styledTypeface);
     }
 }
diff --git a/core/java/android/text/util/Linkify.java b/core/java/android/text/util/Linkify.java
index d973d4a..3a22db2 100644
--- a/core/java/android/text/util/Linkify.java
+++ b/core/java/android/text/util/Linkify.java
@@ -644,7 +644,13 @@
             @Nullable Runnable modifyTextView) {
         Preconditions.checkNotNull(text);
         Preconditions.checkNotNull(classifier);
-        final Supplier<TextLinks> supplier = () -> classifier.generateLinks(text, options);
+
+        // The input text may exceed the maximum length the text classifier can handle. In such
+        // cases, we process the text up to the maximum length.
+        final CharSequence truncatedText = text.subSequence(
+                0, Math.min(text.length(), classifier.getMaxGenerateLinksTextLength()));
+
+        final Supplier<TextLinks> supplier = () -> classifier.generateLinks(truncatedText, options);
         final Consumer<TextLinks> consumer = links -> {
             if (links.getLinks().isEmpty()) {
                 if (callback != null) {
@@ -653,7 +659,8 @@
                 return;
             }
 
-            final TextLinkSpan[] old = text.getSpans(0, text.length(), TextLinkSpan.class);
+            // Remove spans only for the part of the text we generated links for.
+            final TextLinkSpan[] old = text.getSpans(0, truncatedText.length(), TextLinkSpan.class);
             for (int i = old.length - 1; i >= 0; i--) {
                 text.removeSpan(old[i]);
             }
@@ -662,7 +669,8 @@
                     ? null : options.getSpanFactory();
             final @TextLinks.ApplyStrategy int applyStrategy = (options == null)
                     ? TextLinks.APPLY_STRATEGY_IGNORE : options.getApplyStrategy();
-            final @TextLinks.Status int result =  links.apply(text, applyStrategy, spanFactory);
+            final @TextLinks.Status int result = links.apply(text, applyStrategy, spanFactory,
+                    true /*allowPrefix*/);
             if (result == TextLinks.STATUS_LINKS_APPLIED) {
                 if (modifyTextView != null) {
                     modifyTextView.run();
diff --git a/core/java/android/transition/ArcMotion.java b/core/java/android/transition/ArcMotion.java
index da14834..172c837 100644
--- a/core/java/android/transition/ArcMotion.java
+++ b/core/java/android/transition/ArcMotion.java
@@ -216,7 +216,13 @@
 
         boolean isMovingUpwards = startY > endY;
 
-        if ((Math.abs(deltaX) < Math.abs(deltaY))) {
+        if (deltaY == 0) {
+            ex = dx;
+            ey = dy + (Math.abs(deltaX) * 0.5f * mMinimumHorizontalTangent);
+        } else if (deltaX == 0) {
+            ex = dx + (Math.abs(deltaY) * 0.5f * mMinimumVerticalTangent);
+            ey = dy;
+        } else if ((Math.abs(deltaX) < Math.abs(deltaY))) {
             // Similar triangles bfa and bde mean that (ab/fb = eb/bd)
             // Therefore, eb = ab * bd / fb
             // ab = hypotenuse
@@ -254,7 +260,7 @@
         float maximumArcDist2 = midDist2 * mMaximumTangent * mMaximumTangent;
 
         float newArcDistance2 = 0;
-        if (arcDist2 < minimumArcDist2) {
+        if (arcDist2 != 0 && arcDist2 < minimumArcDist2) {
             newArcDistance2 = minimumArcDist2;
         } else if (arcDist2 > maximumArcDist2) {
             newArcDistance2 = maximumArcDist2;
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/AttributeSet.java b/core/java/android/util/AttributeSet.java
index eb8c168..7f327c7 100644
--- a/core/java/android/util/AttributeSet.java
+++ b/core/java/android/util/AttributeSet.java
@@ -17,6 +17,8 @@
 package android.util;
 
 
+import org.xmlpull.v1.XmlPullParser;
+
 /**
  * A collection of attributes, as found associated with a tag in an XML
  * document.  Often you will not want to use this interface directly, instead
@@ -54,18 +56,42 @@
  * compiled XML resource that is not available in a normal XML file, such
  * as {@link #getAttributeNameResource(int)} which returns the resource
  * identifier associated with a particular XML attribute name.
+ *
+ * @see XmlPullParser
  */
 public interface AttributeSet {
     /**
      * Returns the number of attributes available in the set.
-     * 
+     *
+     * <p>See also {@link XmlPullParser#getAttributeCount XmlPullParser.getAttributeCount()},
+     * which this method corresponds to when parsing a compiled XML file.</p>
+     *
      * @return A positive integer, or 0 if the set is empty.
      */
     public int getAttributeCount();
 
     /**
+     * Returns the namespace of the specified attribute.
+     *
+     * <p>See also {@link XmlPullParser#getAttributeNamespace XmlPullParser.getAttributeNamespace()},
+     * which this method corresponds to when parsing a compiled XML file.</p>
+     *
+     * @param index Index of the desired attribute, 0...count-1.
+     *
+     * @return A String containing the namespace of the attribute, or null if th
+     *         attribute cannot be found.
+     */
+    default String getAttributeNamespace (int index) {
+        // This is a new method since the first interface definition, so add stub impl.
+        return null;
+    }
+
+    /**
      * Returns the name of the specified attribute.
-     * 
+     *
+     * <p>See also {@link XmlPullParser#getAttributeName XmlPullParser.getAttributeName()},
+     * which this method corresponds to when parsing a compiled XML file.</p>
+     *
      * @param index Index of the desired attribute, 0...count-1.
      * 
      * @return A String containing the name of the attribute, or null if the
diff --git a/core/java/android/util/ByteStringUtils.java b/core/java/android/util/ByteStringUtils.java
index 333208d..f6460ad 100644
--- a/core/java/android/util/ByteStringUtils.java
+++ b/core/java/android/util/ByteStringUtils.java
@@ -22,61 +22,63 @@
  * @hide
  */
 public final class ByteStringUtils {
-  private final static char[] HEX_ARRAY = "0123456789ABCDEF".toCharArray();
+    private static final char[] HEX_LOWERCASE_ARRAY = "0123456789abcdef".toCharArray();
+    private static final char[] HEX_UPPERCASE_ARRAY = "0123456789ABCDEF".toCharArray();
 
-  private ByteStringUtils() {
+    private ByteStringUtils() {
     /* hide constructor */
-  }
-
-  /**
-   * Returns the hex encoded string representation of bytes.
-   * @param bytes Byte array to encode.
-   * @return Hex encoded string representation of bytes.
-   */
-  public static String toHexString(byte[] bytes) {
-    if (bytes == null || bytes.length == 0 || bytes.length % 2 != 0) {
-      return null;
     }
 
-    final int byteLength = bytes.length;
-    final int charCount = 2 * byteLength;
-    final char[] chars = new char[charCount];
+    /**
+     * Returns the hex encoded string representation of bytes.
+     * @param bytes Byte array to encode.
+     * @return Hex encoded string representation of bytes.
+     */
+    public static String toHexString(byte[] bytes) {
+        if (bytes == null || bytes.length == 0 || bytes.length % 2 != 0) {
+            return null;
+        }
 
-    for (int i = 0; i < byteLength; i++) {
-      final int byteHex = bytes[i] & 0xFF;
-      chars[i * 2] = HEX_ARRAY[byteHex >>> 4];
-      chars[i * 2 + 1] = HEX_ARRAY[byteHex & 0x0F];
-    }
-    return new String(chars);
-  }
+        final int byteLength = bytes.length;
+        final int charCount = 2 * byteLength;
+        final char[] chars = new char[charCount];
 
-  /**
-   * Returns the decoded byte array representation of str.
-   * @param str Hex encoded string to decode.
-   * @return Decoded byte array representation of str.
-   */
-  public static byte[] fromHexToByteArray(String str) {
-    if (str == null || str.length() == 0 || str.length() % 2 != 0) {
-      return null;
+        for (int i = 0; i < byteLength; i++) {
+            final int byteHex = bytes[i] & 0xFF;
+            chars[i * 2] = HEX_UPPERCASE_ARRAY[byteHex >>> 4];
+            chars[i * 2 + 1] = HEX_UPPERCASE_ARRAY[byteHex & 0x0F];
+        }
+        return new String(chars);
     }
 
-    final char[] chars = str.toCharArray();
-    final int charLength = chars.length;
-    final byte[] bytes = new byte[charLength / 2];
+    /**
+     * Returns the decoded byte array representation of str.
+     * @param str Hex encoded string to decode.
+     * @return Decoded byte array representation of str.
+     */
+    public static byte[] fromHexToByteArray(String str) {
+        if (str == null || str.length() == 0 || str.length() % 2 != 0) {
+            return null;
+        }
 
-    for (int i = 0; i < bytes.length; i++) {
-      bytes[i] =
-          (byte)(((getIndex(chars[i * 2]) << 4) & 0xF0) | (getIndex(chars[i * 2 + 1]) & 0x0F));
-    }
-    return bytes;
-  }
+        final char[] chars = str.toCharArray();
+        final int charLength = chars.length;
+        final byte[] bytes = new byte[charLength / 2];
 
-  private static int getIndex(char c) {
-    for (int i = 0; i < HEX_ARRAY.length; i++) {
-      if (HEX_ARRAY[i] == c) {
-        return i;
-      }
+        for (int i = 0; i < bytes.length; i++) {
+            bytes[i] =
+                    (byte) (((getIndex(chars[i * 2]) << 4) & 0xF0)
+                            | (getIndex(chars[i * 2 + 1]) & 0x0F));
+        }
+        return bytes;
     }
-    return -1;
-  }
+
+    private static int getIndex(char c) {
+        for (int i = 0; i < HEX_UPPERCASE_ARRAY.length; i++) {
+            if (HEX_UPPERCASE_ARRAY[i] == c || HEX_LOWERCASE_ARRAY[i] == c) {
+                return i;
+            }
+        }
+        return -1;
+    }
 }
diff --git a/core/java/android/util/ExceptionUtils.java b/core/java/android/util/ExceptionUtils.java
index da7387f..1a397b3 100644
--- a/core/java/android/util/ExceptionUtils.java
+++ b/core/java/android/util/ExceptionUtils.java
@@ -86,4 +86,16 @@
         while (t.getCause() != null) t = t.getCause();
         return t;
     }
-}
+
+    /**
+     * Appends {@code cause} at the end of the causal chain of {@code t}
+     *
+     * @return {@code t} for convenience
+     */
+    public static @NonNull Throwable appendCause(@NonNull Throwable t, @Nullable Throwable cause) {
+        if (cause != null) {
+            getRootCause(t).initCause(cause);
+        }
+        return t;
+    }
+}
\ No newline at end of file
diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java
index 410cdc6..1ead0b4 100644
--- a/core/java/android/util/FeatureFlagUtils.java
+++ b/core/java/android/util/FeatureFlagUtils.java
@@ -37,13 +37,13 @@
     private static final Map<String, String> DEFAULT_FLAGS;
     static {
         DEFAULT_FLAGS = new HashMap<>();
-        DEFAULT_FLAGS.put("device_info_v2", "true");
         DEFAULT_FLAGS.put("settings_connected_device_v2", "true");
         DEFAULT_FLAGS.put("settings_battery_v2", "true");
         DEFAULT_FLAGS.put("settings_battery_display_app_list", "false");
         DEFAULT_FLAGS.put("settings_zone_picker_v2", "true");
-        DEFAULT_FLAGS.put("settings_about_phone_v2", "false");
+        DEFAULT_FLAGS.put("settings_about_phone_v2", "true");
         DEFAULT_FLAGS.put("settings_bluetooth_while_driving", "false");
+        DEFAULT_FLAGS.put("settings_data_usage_v2", "false");
     }
 
     /**
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/util/OWNERS b/core/java/android/util/OWNERS
new file mode 100644
index 0000000..86ed122
--- /dev/null
+++ b/core/java/android/util/OWNERS
@@ -0,0 +1,2 @@
+per-file FeatureFlagUtils.java = sbasi@google.com
+per-file FeatureFlagUtils.java = zhfan@google.com
diff --git a/core/java/android/util/StatsLog.java b/core/java/android/util/StatsLog.java
index 4805318..3350f3e 100644
--- a/core/java/android/util/StatsLog.java
+++ b/core/java/android/util/StatsLog.java
@@ -34,7 +34,7 @@
      */
     public static boolean logStart(int label) {
         if (label >= 0 && label < 16) {
-            StatsLog.write(APP_HOOK, label, APP_HOOK__STATE__START);
+            StatsLog.write(APP_BREADCRUMB_REPORTED, label, APP_BREADCRUMB_REPORTED__STATE__START);
             return true;
         }
         return false;
@@ -48,7 +48,7 @@
      */
     public static boolean logStop(int label) {
         if (label >= 0 && label < 16) {
-            StatsLog.write(APP_HOOK, label, APP_HOOK__STATE__STOP);
+            StatsLog.write(APP_BREADCRUMB_REPORTED, label, APP_BREADCRUMB_REPORTED__STATE__STOP);
             return true;
         }
         return false;
@@ -62,7 +62,8 @@
      */
     public static boolean logEvent(int label) {
         if (label >= 0 && label < 16) {
-            StatsLog.write(APP_HOOK, label, APP_HOOK__STATE__UNSPECIFIED);
+            StatsLog.write(APP_BREADCRUMB_REPORTED, label,
+                    APP_BREADCRUMB_REPORTED__STATE__UNSPECIFIED);
             return true;
         }
         return false;
diff --git a/core/java/android/util/StatsManager.java b/core/java/android/util/StatsManager.java
deleted file mode 100644
index 51fb18a..0000000
--- a/core/java/android/util/StatsManager.java
+++ /dev/null
@@ -1,239 +0,0 @@
-/*
- * Copyright 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.util;
-
-import android.Manifest;
-import android.annotation.RequiresPermission;
-import android.os.IBinder;
-import android.os.IStatsManager;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-
-
-/*
- *
- *
- *
- *
- * THIS ENTIRE FILE IS ONLY TEMPORARY TO PREVENT BREAKAGES OF DEPENDENCIES ON OLD APIS.
- * The new StatsManager is to be found in android.app.StatsManager.
- * TODO: Delete this file!
- *
- *
- *
- *
- */
-
-
-/**
- * API for StatsD clients to send configurations and retrieve data.
- *
- * @hide
- */
-public class StatsManager {
-    IStatsManager mService;
-    private static final String TAG = "StatsManager";
-
-    /**
-     * Constructor for StatsManagerClient.
-     *
-     * @hide
-     */
-    public StatsManager() {
-    }
-
-    /**
-     * Temporary to prevent build failures. Will be deleted.
-     */
-    @RequiresPermission(Manifest.permission.DUMP)
-    public boolean addConfiguration(String configKey, byte[] config, String pkg, String cls) {
-        synchronized (this) {
-            try {
-                IStatsManager service = getIStatsManagerLocked();
-                if (service == null) {
-                    Slog.d(TAG, "Failed to find statsd when adding configuration");
-                    return false;
-                }
-                return service.addConfiguration(Long.parseLong(configKey), config, pkg, cls);
-            } catch (RemoteException e) {
-                Slog.d(TAG, "Failed to connect to statsd when adding configuration");
-                return false;
-            }
-        }
-    }
-
-    /**
-     * Clients can send a configuration and simultaneously registers the name of a broadcast
-     * receiver that listens for when it should request data.
-     *
-     * @param configKey An arbitrary integer that allows clients to track the configuration.
-     * @param config    Wire-encoded StatsDConfig proto that specifies metrics (and all
-     *                  dependencies eg, conditions and matchers).
-     * @param pkg       The package name to receive the broadcast.
-     * @param cls       The name of the class that receives the broadcast.
-     * @return true if successful
-     */
-    @RequiresPermission(Manifest.permission.DUMP)
-    public boolean addConfiguration(long configKey, byte[] config, String pkg, String cls) {
-        synchronized (this) {
-            try {
-                IStatsManager service = getIStatsManagerLocked();
-                if (service == null) {
-                    Slog.d(TAG, "Failed to find statsd when adding configuration");
-                    return false;
-                }
-                return service.addConfiguration(configKey, config, pkg, cls);
-            } catch (RemoteException e) {
-                Slog.d(TAG, "Failed to connect to statsd when adding configuration");
-                return false;
-            }
-        }
-    }
-
-    /**
-     * Temporary to prevent build failures. Will be deleted.
-     */
-    @RequiresPermission(Manifest.permission.DUMP)
-    public boolean removeConfiguration(String configKey) {
-        // To prevent breakages of old dependencies.
-        synchronized (this) {
-            try {
-                IStatsManager service = getIStatsManagerLocked();
-                if (service == null) {
-                    Slog.d(TAG, "Failed to find statsd when removing configuration");
-                    return false;
-                }
-                return service.removeConfiguration(Long.parseLong(configKey));
-            } catch (RemoteException e) {
-                Slog.d(TAG, "Failed to connect to statsd when removing configuration");
-                return false;
-            }
-        }
-    }
-
-    /**
-     * Remove a configuration from logging.
-     *
-     * @param configKey Configuration key to remove.
-     * @return true if successful
-     */
-    @RequiresPermission(Manifest.permission.DUMP)
-    public boolean removeConfiguration(long configKey) {
-        synchronized (this) {
-            try {
-                IStatsManager service = getIStatsManagerLocked();
-                if (service == null) {
-                    Slog.d(TAG, "Failed to find statsd when removing configuration");
-                    return false;
-                }
-                return service.removeConfiguration(configKey);
-            } catch (RemoteException e) {
-                Slog.d(TAG, "Failed to connect to statsd when removing configuration");
-                return false;
-            }
-        }
-    }
-
-    /**
-     * Temporary to prevent build failures. Will be deleted.
-     */
-    @RequiresPermission(Manifest.permission.DUMP)
-    public byte[] getData(String configKey) {
-        // TODO: remove this and all other methods with String-based config keys.
-        // To prevent build breakages of dependencies.
-        synchronized (this) {
-            try {
-                IStatsManager service = getIStatsManagerLocked();
-                if (service == null) {
-                    Slog.d(TAG, "Failed to find statsd when getting data");
-                    return null;
-                }
-                return service.getData(Long.parseLong(configKey));
-            } catch (RemoteException e) {
-                Slog.d(TAG, "Failed to connecto statsd when getting data");
-                return null;
-            }
-        }
-    }
-
-    /**
-     * Clients can request data with a binder call. This getter is destructive and also clears
-     * the retrieved metrics from statsd memory.
-     *
-     * @param configKey Configuration key to retrieve data from.
-     * @return Serialized ConfigMetricsReportList proto. Returns null on failure.
-     */
-    @RequiresPermission(Manifest.permission.DUMP)
-    public byte[] getData(long configKey) {
-        synchronized (this) {
-            try {
-                IStatsManager service = getIStatsManagerLocked();
-                if (service == null) {
-                    Slog.d(TAG, "Failed to find statsd when getting data");
-                    return null;
-                }
-                return service.getData(configKey);
-            } catch (RemoteException e) {
-                Slog.d(TAG, "Failed to connecto statsd when getting data");
-                return null;
-            }
-        }
-    }
-
-    /**
-     * Clients can request metadata for statsd. Will contain stats across all configurations but not
-     * the actual metrics themselves (metrics must be collected via {@link #getData(String)}.
-     * This getter is not destructive and will not reset any metrics/counters.
-     *
-     * @return Serialized StatsdStatsReport proto. Returns null on failure.
-     */
-    @RequiresPermission(Manifest.permission.DUMP)
-    public byte[] getMetadata() {
-        synchronized (this) {
-            try {
-                IStatsManager service = getIStatsManagerLocked();
-                if (service == null) {
-                    Slog.d(TAG, "Failed to find statsd when getting metadata");
-                    return null;
-                }
-                return service.getMetadata();
-            } catch (RemoteException e) {
-                Slog.d(TAG, "Failed to connecto statsd when getting metadata");
-                return null;
-            }
-        }
-    }
-
-    private class StatsdDeathRecipient implements IBinder.DeathRecipient {
-        @Override
-        public void binderDied() {
-            synchronized (this) {
-                mService = null;
-            }
-        }
-    }
-
-    private IStatsManager getIStatsManagerLocked() throws RemoteException {
-        if (mService != null) {
-            return mService;
-        }
-        mService = IStatsManager.Stub.asInterface(ServiceManager.getService("stats"));
-        if (mService != null) {
-            mService.asBinder().linkToDeath(new StatsdDeathRecipient(), 0);
-        }
-        return mService;
-    }
-}
diff --git a/core/java/android/util/XmlPullAttributes.java b/core/java/android/util/XmlPullAttributes.java
index 6c8bb39..cb35eb5 100644
--- a/core/java/android/util/XmlPullAttributes.java
+++ b/core/java/android/util/XmlPullAttributes.java
@@ -34,6 +34,10 @@
         return mParser.getAttributeCount();
     }
 
+    public String getAttributeNamespace (int index) {
+        return mParser.getAttributeNamespace(index);
+    }
+
     public String getAttributeName(int index) {
         return mParser.getAttributeName(index);
     }
diff --git a/core/java/android/view/DisplayCutout.java b/core/java/android/view/DisplayCutout.java
index a61c8c1..0b72c22 100644
--- a/core/java/android/view/DisplayCutout.java
+++ b/core/java/android/view/DisplayCutout.java
@@ -52,6 +52,16 @@
     private static final String TAG = "DisplayCutout";
     private static final String DP_MARKER = "@dp";
 
+    /**
+     * Category for overlays that allow emulating a display cutout on devices that don't have
+     * one.
+     *
+     * @see android.content.om.IOverlayManager
+     * @hide
+     */
+    public static final String EMULATION_OVERLAY_CATEGORY =
+            "com.android.internal.display_cutout_emulation";
+
     private static final Rect ZERO_RECT = new Rect();
     private static final Region EMPTY_REGION = new Region();
 
diff --git a/core/java/android/view/DisplayInfo.java b/core/java/android/view/DisplayInfo.java
index 37e9815..7251b71 100644
--- a/core/java/android/view/DisplayInfo.java
+++ b/core/java/android/view/DisplayInfo.java
@@ -20,6 +20,7 @@
 import static android.view.DisplayInfoProto.APP_WIDTH;
 import static android.view.DisplayInfoProto.LOGICAL_HEIGHT;
 import static android.view.DisplayInfoProto.LOGICAL_WIDTH;
+import static android.view.DisplayInfoProto.NAME;
 
 import android.content.res.CompatibilityInfo;
 import android.content.res.Configuration;
@@ -685,6 +686,7 @@
         protoOutputStream.write(LOGICAL_HEIGHT, logicalHeight);
         protoOutputStream.write(APP_WIDTH, appWidth);
         protoOutputStream.write(APP_HEIGHT, appHeight);
+        protoOutputStream.write(NAME, name);
         protoOutputStream.end(token);
     }
 
diff --git a/core/java/android/view/IRecentsAnimationRunner.aidl b/core/java/android/view/IRecentsAnimationRunner.aidl
index ea6226b..69973e6 100644
--- a/core/java/android/view/IRecentsAnimationRunner.aidl
+++ b/core/java/android/view/IRecentsAnimationRunner.aidl
@@ -16,6 +16,7 @@
 
 package android.view;
 
+import android.graphics.Rect;
 import android.view.RemoteAnimationTarget;
 import android.view.IRecentsAnimationController;
 
@@ -28,15 +29,26 @@
 oneway interface IRecentsAnimationRunner {
 
     /**
-     * Called when the system is ready for the handler to start animating all the visible tasks.
+     * Deprecated, to be removed once Launcher updates
      */
     void onAnimationStart(in IRecentsAnimationController controller,
-            in RemoteAnimationTarget[] apps);
+            in RemoteAnimationTarget[] apps) = 0;
 
     /**
      * Called when the system needs to cancel the current animation. This can be due to the
      * wallpaper not drawing in time, or the handler not finishing the animation within a predefined
      * amount of time.
      */
-    void onAnimationCanceled();
+    void onAnimationCanceled() = 1;
+
+    /**
+     * Called when the system is ready for the handler to start animating all the visible tasks.
+     *
+     * @param homeContentInsets The current home app content insets
+     * @param minimizedHomeBounds Specifies the bounds of the minimized home app, will be
+     *                            {@code null} if the device is not currently in split screen
+     */
+    void onAnimationStart_New(in IRecentsAnimationController controller,
+            in RemoteAnimationTarget[] apps, in Rect homeContentInsets,
+            in Rect minimizedHomeBounds) = 2;
 }
diff --git a/core/java/android/view/RemoteAnimationTarget.java b/core/java/android/view/RemoteAnimationTarget.java
index c28c389..facf575 100644
--- a/core/java/android/view/RemoteAnimationTarget.java
+++ b/core/java/android/view/RemoteAnimationTarget.java
@@ -79,6 +79,11 @@
     public final Rect clipRect;
 
     /**
+     * The insets of the main app window.
+     */
+    public final Rect contentInsets;
+
+    /**
      * The index of the element in the tree in prefix order. This should be used for z-layering
      * to preserve original z-layer order in the hierarchy tree assuming no "boosting" needs to
      * happen.
@@ -105,13 +110,14 @@
     public final WindowConfiguration windowConfiguration;
 
     public RemoteAnimationTarget(int taskId, int mode, SurfaceControl leash, boolean isTranslucent,
-            Rect clipRect, int prefixOrderIndex, Point position, Rect sourceContainerBounds,
-            WindowConfiguration windowConfig) {
+            Rect clipRect, Rect contentInsets, int prefixOrderIndex, Point position,
+            Rect sourceContainerBounds, WindowConfiguration windowConfig) {
         this.mode = mode;
         this.taskId = taskId;
         this.leash = leash;
         this.isTranslucent = isTranslucent;
         this.clipRect = new Rect(clipRect);
+        this.contentInsets = new Rect(contentInsets);
         this.prefixOrderIndex = prefixOrderIndex;
         this.position = new Point(position);
         this.sourceContainerBounds = new Rect(sourceContainerBounds);
@@ -124,6 +130,7 @@
         leash = in.readParcelable(null);
         isTranslucent = in.readBoolean();
         clipRect = in.readParcelable(null);
+        contentInsets = in.readParcelable(null);
         prefixOrderIndex = in.readInt();
         position = in.readParcelable(null);
         sourceContainerBounds = in.readParcelable(null);
@@ -142,6 +149,7 @@
         dest.writeParcelable(leash, 0 /* flags */);
         dest.writeBoolean(isTranslucent);
         dest.writeParcelable(clipRect, 0 /* flags */);
+        dest.writeParcelable(contentInsets, 0 /* flags */);
         dest.writeInt(prefixOrderIndex);
         dest.writeParcelable(position, 0 /* flags */);
         dest.writeParcelable(sourceContainerBounds, 0 /* flags */);
diff --git a/core/java/android/view/RenderNodeAnimator.java b/core/java/android/view/RenderNodeAnimator.java
index c4a7160..d26a2f6 100644
--- a/core/java/android/view/RenderNodeAnimator.java
+++ b/core/java/android/view/RenderNodeAnimator.java
@@ -158,7 +158,7 @@
     }
 
     private void applyInterpolator() {
-        if (mInterpolator == null) return;
+        if (mInterpolator == null || mNativePtr == null) return;
 
         long ni;
         if (isNativeInterpolator(mInterpolator)) {
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index 370c97e..e50d40e 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -331,6 +331,7 @@
 
     private static final int FLAG_DUMP_FRAMESTATS   = 1 << 0;
     private static final int FLAG_DUMP_RESET        = 1 << 1;
+    private static final int FLAG_DUMP_ALL          = FLAG_DUMP_FRAMESTATS;
 
     @IntDef(flag = true, prefix = { "FLAG_DUMP_" }, value = {
             FLAG_DUMP_FRAMESTATS,
@@ -636,7 +637,10 @@
      */
     void dumpGfxInfo(PrintWriter pw, FileDescriptor fd, String[] args) {
         pw.flush();
-        int flags = 0;
+        // If there's no arguments, eg 'dumpsys gfxinfo', then dump everything.
+        // If there's a targetted package, eg 'dumpsys gfxinfo com.android.systemui', then only
+        // dump the summary information
+        int flags = (args == null || args.length == 0) ? FLAG_DUMP_ALL : 0;
         for (int i = 0; i < args.length; i++) {
             switch (args[i]) {
                 case "framestats":
@@ -645,6 +649,9 @@
                 case "reset":
                     flags |= FLAG_DUMP_RESET;
                     break;
+                case "-a": // magic option passed when dumping a bugreport.
+                    flags = FLAG_DUMP_ALL;
+                    break;
             }
         }
         nDumpProfileInfo(mNativeProxy, fd, flags);
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 79fc134..3ff3c97 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -17,6 +17,7 @@
 package android.view;
 
 import static android.view.accessibility.AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED;
+
 import static java.lang.Math.max;
 
 import android.animation.AnimatorInflater;
@@ -906,6 +907,13 @@
      */
     private static boolean sThrowOnInvalidFloatProperties;
 
+    /**
+     * Prior to P, {@code #startDragAndDrop} accepts a builder which produces an empty drag shadow.
+     * Currently zero size SurfaceControl cannot be created thus we create a dummy 1x1 surface
+     * instead.
+     */
+    private static boolean sAcceptZeroSizeDragShadow;
+
     /** @hide */
     @IntDef({NOT_FOCUSABLE, FOCUSABLE, FOCUSABLE_AUTO})
     @Retention(RetentionPolicy.SOURCE)
@@ -4798,6 +4806,7 @@
 
             Canvas.sCompatibilityRestore = targetSdkVersion < Build.VERSION_CODES.M;
             Canvas.sCompatibilitySetBitmap = targetSdkVersion < Build.VERSION_CODES.O;
+            Canvas.setCompatibilityVersion(targetSdkVersion);
 
             // In M and newer, our widgets can pass a "hint" value in the size
             // for UNSPECIFIED MeasureSpecs. This lets child views of scrolling containers
@@ -4840,6 +4849,8 @@
 
             sAlwaysAssignFocus = targetSdkVersion < Build.VERSION_CODES.P;
 
+            sAcceptZeroSizeDragShadow = targetSdkVersion < Build.VERSION_CODES.P;
+
             sCompatibilityDone = true;
         }
     }
@@ -7261,7 +7272,7 @@
                         // becomes true where it should issue notifyViewEntered().
                         afm.notifyViewEntered(this);
                     }
-                } else if (!isFocused()) {
+                } else if (!enter && !isFocused()) {
                     afm.notifyViewExited(this);
                 }
             }
@@ -7297,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
@@ -7860,6 +7875,7 @@
                 structure.setAutofillHints(getAutofillHints());
                 structure.setAutofillValue(getAutofillValue());
             }
+            structure.setImportantForAutofill(getImportantForAutofill());
         }
 
         int ignoredParentLeft = 0;
@@ -7994,6 +8010,9 @@
      *   <li>Call {@link
      *    android.view.autofill.AutofillManager#notifyViewVisibilityChanged(View, int, boolean)}
      *       when the visibility of a virtual child changed.
+     *   <li>Call
+     *    {@link android.view.autofill.AutofillManager#notifyViewClicked(View, int)} when a virtual
+     *       child is clicked.
      *   <li>Call {@link AutofillManager#commit()} when the autofill context of the view structure
      *       changed and the current context should be committed (for example, when the user tapped
      *       a {@code SUBMIT} button in an HTML page).
@@ -8355,6 +8374,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;
     }
@@ -8378,7 +8402,7 @@
             AccessibilityNodeProvider provider, AccessibilityNodeInfo info,
             boolean forAutofill) {
         structure.setId(AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId()),
-                null, null, null);
+                null, null, info.getViewIdResourceName());
         Rect rect = structure.getTempRect();
         info.getBoundsInParent(rect);
         structure.setDimens(rect.left, rect.top, 0, 0, rect.width(), rect.height());
@@ -8418,6 +8442,13 @@
         CharSequence cname = info.getClassName();
         structure.setClassName(cname != null ? cname.toString() : null);
         structure.setContentDescription(info.getContentDescription());
+        if (forAutofill) {
+            final int maxTextLength = info.getMaxTextLength();
+            if (maxTextLength != -1) {
+                structure.setMaxTextLength(maxTextLength);
+            }
+            structure.setHint(info.getHintText());
+        }
         if ((info.getText() != null || info.getError() != null)) {
             structure.setText(info.getText(), info.getTextSelectionStart(),
                     info.getTextSelectionEnd());
@@ -8428,7 +8459,8 @@
                     final AutofillValue autofillValue = AutofillValue.forText(structure.getText());
                     structure.setAutofillValue(autofillValue);
                     if (info.isPassword()) {
-                        structure.setInputType(InputType.TYPE_TEXT_VARIATION_PASSWORD);
+                        structure.setInputType(InputType.TYPE_CLASS_TEXT
+                                | InputType.TYPE_TEXT_VARIATION_PASSWORD);
                     }
                 } else {
                     structure.setDataIsSensitive(false);
@@ -8778,6 +8810,9 @@
     /**
      * Computes whether this virtual autofill view is visible to the user.
      *
+     * <p><b>Note: </b>By default it returns {@code true}, but views providing a virtual hierarchy
+     * view must override it.
+     *
      * @return Whether the view is visible on the screen.
      */
     public boolean isVisibleToUserForAutofill(int virtualId) {
@@ -8790,7 +8825,7 @@
                 }
             }
         }
-        return false;
+        return true;
     }
 
     /**
@@ -11612,7 +11647,7 @@
         return mode == IMPORTANT_FOR_ACCESSIBILITY_YES || isActionableForAccessibility()
                 || hasListenersForAccessibility() || getAccessibilityNodeProvider() != null
                 || getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE
-                || (mAccessibilityPaneTitle != null);
+                || isAccessibilityPane();
     }
 
     /**
@@ -11709,18 +11744,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;
             }
         }
 
@@ -14010,6 +14053,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) {
@@ -23619,8 +23667,7 @@
          * constructor variant is only useful when the {@link #onProvideShadowMetrics(Point, Point)}
          * and {@link #onDrawShadow(Canvas)} methods are also overridden in order
          * to supply the drag shadow's dimensions and appearance without
-         * reference to any View object. If they are not overridden, then the result is an
-         * invisible drag shadow.
+         * reference to any View object.
          */
         public DragShadowBuilder() {
             mView = new WeakReference<View>(null);
@@ -23774,6 +23821,9 @@
         // Create 1x1 surface when zero surface size is specified because SurfaceControl.Builder
         // does not accept zero size surface.
         if (shadowSize.x == 0  || shadowSize.y == 0) {
+            if (!sAcceptZeroSizeDragShadow) {
+                throw new IllegalStateException("Drag shadow dimensions must be positive");
+            }
             shadowSize.x = 1;
             shadowSize.y = 1;
         }
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/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 273f097..8e60a72 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -3971,15 +3971,7 @@
     }
 
     /**
-     * Layout debugging code which draws rectangles around layout params.
-     *
-     * <p>This function is called automatically when the developer setting is enabled.<p/>
-     *
-     * <p>It is strongly advised to only call this function from debug builds as there is
-     * a risk of leaking unwanted layout information.<p/>
-     *
-     * @param canvas the canvas on which to draw
-     * @param paint the paint used to draw through
+     * @hide
      */
     protected void onDebugDrawMargins(Canvas canvas, Paint paint) {
         for (int i = 0; i < getChildCount(); i++) {
@@ -3989,19 +3981,7 @@
     }
 
     /**
-     * Layout debugging code which draws rectangles around:
-     * <ul>
-     *     <li>optical bounds<li/>
-     *     <li>margins<li/>
-     *     <li>clip bounds<li/>
-     * <ul/>
-     *
-     * <p>This function is called automatically when the developer setting is enabled.<p/>
-     *
-     * <p>It is strongly advised to only call this function from debug builds as there is
-     * a risk of leaking unwanted layout information.<p/>
-     *
-     * @param canvas the canvas on which to draw
+     * @hide
      */
     protected void onDebugDraw(Canvas canvas) {
         Paint paint = getDebugPaint();
@@ -7732,14 +7712,10 @@
         /**
          * Use {@code canvas} to draw suitable debugging annotations for these LayoutParameters.
          *
-         * <p>This function is called automatically when the developer setting is enabled.<p/>
-         *
-         * <p>It is strongly advised to only call this function from debug builds as there is
-         * a risk of leaking unwanted layout information.<p/>
-         *
          * @param view the view that contains these layout parameters
          * @param canvas the canvas on which to draw
-         * @param paint the paint used to draw through
+         *
+         * @hide
          */
         public void onDebugDraw(View view, Canvas canvas, Paint paint) {
         }
@@ -8243,6 +8219,9 @@
             return ((mMarginFlags & LAYOUT_DIRECTION_MASK) == View.LAYOUT_DIRECTION_RTL);
         }
 
+        /**
+         * @hide
+         */
         @Override
         public void onDebugDraw(View view, Canvas canvas, Paint paint) {
             Insets oi = isLayoutModeOptical(view.mParent) ? view.getOpticalInsets() : Insets.NONE;
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/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java
index 191c270..dee267d 100644
--- a/core/java/android/view/accessibility/AccessibilityManager.java
+++ b/core/java/android/view/accessibility/AccessibilityManager.java
@@ -774,8 +774,9 @@
      */
     public void removeAccessibilityServicesStateChangeListener(
             @NonNull AccessibilityServicesStateChangeListener listener) {
-        // Final CopyOnWriteArrayList - no lock needed.
-        mServicesStateChangeListeners.remove(listener);
+        synchronized (mLock) {
+            mServicesStateChangeListeners.remove(listener);
+        }
     }
 
     /**
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index 23e7d61..417a725 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -3173,6 +3173,15 @@
      */
     @Override
     public void writeToParcel(Parcel parcel, int flags) {
+        writeToParcelNoRecycle(parcel, flags);
+        // Since instances of this class are fetched via synchronous i.e. blocking
+        // calls in IPCs we always recycle as soon as the instance is marshaled.
+        recycle();
+    }
+
+    /** @hide */
+    @TestApi
+    public void writeToParcelNoRecycle(Parcel parcel, int flags) {
         // Write bit set of indices of fields with values differing from default
         long nonDefaultFields = 0;
         int fieldIndex = 0; // index of the current field
@@ -3406,10 +3415,6 @@
                         + " vs " + fieldIndex);
             }
         }
-
-        // Since instances of this class are fetched via synchronous i.e. blocking
-        // calls in IPCs we always recycle as soon as the instance is marshaled.
-        recycle();
     }
 
     /**
@@ -3557,7 +3562,7 @@
         if (isBitSet(nonDefaultFields, fieldIndex++)) {
             mContentDescription = parcel.readCharSequence();
         }
-        if (isBitSet(nonDefaultFields, fieldIndex++)) mPaneTitle = parcel.readString();
+        if (isBitSet(nonDefaultFields, fieldIndex++)) mPaneTitle = parcel.readCharSequence();
         if (isBitSet(nonDefaultFields, fieldIndex++)) mTooltipText = parcel.readCharSequence();
         if (isBitSet(nonDefaultFields, fieldIndex++)) mViewIdResourceName = parcel.readString();
 
diff --git a/core/java/android/view/animation/AnimationUtils.java b/core/java/android/view/animation/AnimationUtils.java
index 990fbdb..29f8442 100644
--- a/core/java/android/view/animation/AnimationUtils.java
+++ b/core/java/android/view/animation/AnimationUtils.java
@@ -18,6 +18,7 @@
 
 import android.annotation.AnimRes;
 import android.annotation.InterpolatorRes;
+import android.annotation.TestApi;
 import android.content.Context;
 import android.content.res.Resources;
 import android.content.res.Resources.NotFoundException;
@@ -58,14 +59,43 @@
         }
     };
 
-    /** @hide */
+    /**
+     * Locks AnimationUtils{@link #currentAnimationTimeMillis()} to a fixed value for the current
+     * thread. This is used by {@link android.view.Choreographer} to ensure that all accesses
+     * during a vsync update are synchronized to the timestamp of the vsync.
+     *
+     * It is also exposed to tests to allow for rapid, flake-free headless testing.
+     *
+     * Must be followed by a call to {@link #unlockAnimationClock()} to allow time to
+     * progress. Failing to do this will result in stuck animations, scrolls, and flings.
+     *
+     * Note that time is not allowed to "rewind" and must perpetually flow forward. So the
+     * lock may fail if the time is in the past from a previously returned value, however
+     * time will be frozen for the duration of the lock. The clock is a thread-local, so
+     * ensure that {@link #lockAnimationClock(long)}, {@link #unlockAnimationClock()}, and
+     * {@link #currentAnimationTimeMillis()} are all called on the same thread.
+     *
+     * This is also not reference counted in any way. Any call to {@link #unlockAnimationClock()}
+     * will unlock the clock for everyone on the same thread. It is therefore recommended
+     * for tests to use their own thread to ensure that there is no collision with any existing
+     * {@link android.view.Choreographer} instance.
+     *
+     * @hide
+     * */
+    @TestApi
     public static void lockAnimationClock(long vsyncMillis) {
         AnimationState state = sAnimationState.get();
         state.animationClockLocked = true;
         state.currentVsyncTimeMillis = vsyncMillis;
     }
 
-    /** @hide */
+    /**
+     * Frees the time lock set in place by {@link #lockAnimationClock(long)}. Must be called
+     * to allow the animation clock to self-update.
+     *
+     * @hide
+     */
+    @TestApi
     public static void unlockAnimationClock() {
         sAnimationState.get().animationClockLocked = false;
     }
diff --git a/core/java/android/view/autofill/AutofillId.java b/core/java/android/view/autofill/AutofillId.java
index 5ce2421..cb1d89c 100644
--- a/core/java/android/view/autofill/AutofillId.java
+++ b/core/java/android/view/autofill/AutofillId.java
@@ -38,6 +38,7 @@
     }
 
     /** @hide */
+    @TestApi
     public AutofillId(AutofillId parent, int virtualChildId) {
         mVirtual = true;
         mViewId = parent.mViewId;
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index 63a9990..7792fa6 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -16,10 +16,15 @@
 
 package android.view.autofill;
 
+import static android.service.autofill.FillRequest.FLAG_MANUAL_REQUEST;
+import static android.view.autofill.Helper.sDebug;
+import static android.view.autofill.Helper.sVerbose;
+
 import android.accessibilityservice.AccessibilityServiceInfo;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.RequiresFeature;
 import android.annotation.SystemService;
 import android.content.ComponentName;
 import android.content.Context;
@@ -47,13 +52,14 @@
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.view.accessibility.AccessibilityNodeProvider;
 import android.view.accessibility.AccessibilityWindowInfo;
+
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.Preconditions;
+
 import org.xmlpull.v1.XmlPullParserException;
-import sun.misc.Cleaner;
 
 import java.io.IOException;
 import java.io.PrintWriter;
@@ -66,11 +72,8 @@
 import java.util.List;
 import java.util.Objects;
 
-import static android.service.autofill.FillRequest.FLAG_MANUAL_REQUEST;
-import static android.view.autofill.Helper.sDebug;
-import static android.view.autofill.Helper.sVerbose;
-
-// TODO: use java.lang.ref.Cleaner once Android supports Java 9
+//TODO: use java.lang.ref.Cleaner once Android supports Java 9
+import sun.misc.Cleaner;
 
 /**
  * The {@link AutofillManager} provides ways for apps and custom views to integrate with the
@@ -133,6 +136,7 @@
  * <p>It is safe to call into its methods from any thread.
  */
 @SystemService(Context.AUTOFILL_MANAGER_SERVICE)
+@RequiresFeature(PackageManager.FEATURE_AUTOFILL)
 public final class AutofillManager {
 
     private static final String TAG = "AutofillManager";
@@ -353,6 +357,13 @@
     @GuardedBy("mLock")
     @Nullable private ArraySet<AutofillId> mFillableIds;
 
+    /**
+     * Views that were already "entered" - if they're entered again when the session is not active,
+     * they're ignored
+     * */
+    @GuardedBy("mLock")
+    @Nullable private ArraySet<AutofillId> mEnteredIds;
+
     /** If set, session is commited when the field is clicked. */
     @GuardedBy("mLock")
     @Nullable private AutofillId mSaveTriggerId;
@@ -616,10 +627,9 @@
     /**
      * @hide
      */
-    public boolean isCompatibilityModeEnabled() {
-        synchronized (mLock) {
-            return mCompatibilityBridge != null;
-        }
+    @GuardedBy("mLock")
+    public boolean isCompatibilityModeEnabledLocked() {
+        return mCompatibilityBridge != null;
     }
 
     /**
@@ -708,17 +718,30 @@
         notifyViewEntered(view, 0);
     }
 
-    private boolean shouldIgnoreViewEnteredLocked(@NonNull View view, int flags) {
+    @GuardedBy("mLock")
+    private boolean shouldIgnoreViewEnteredLocked(@NonNull AutofillId id, int flags) {
         if (isDisabledByServiceLocked()) {
             if (sVerbose) {
-                Log.v(TAG, "ignoring notifyViewEntered(flags=" + flags + ", view=" + view
-                        + ") on state " + getStateAsStringLocked());
+                Log.v(TAG, "ignoring notifyViewEntered(flags=" + flags + ", view=" + id
+                        + ") on state " + getStateAsStringLocked() + " because disabled by svc");
             }
             return true;
         }
-        if (sVerbose && isFinishedLocked()) {
-            Log.v(TAG, "not ignoring notifyViewEntered(flags=" + flags + ", view=" + view
-                    + ") on state " + getStateAsStringLocked());
+        if (isFinishedLocked()) {
+            // Session already finished: ignore if automatic request and view already entered
+            if ((flags & FLAG_MANUAL_REQUEST) == 0 && mEnteredIds != null
+                    && mEnteredIds.contains(id)) {
+                if (sVerbose) {
+                    Log.v(TAG, "ignoring notifyViewEntered(flags=" + flags + ", view=" + id
+                            + ") on state " + getStateAsStringLocked()
+                            + " because view was already entered: " + mEnteredIds);
+                }
+                return true;
+            }
+        }
+        if (sVerbose) {
+            Log.v(TAG, "not ignoring notifyViewEntered(flags=" + flags + ", view=" + id
+                    + ", state " + getStateAsStringLocked() + ", enteredIds=" + mEnteredIds);
         }
         return false;
     }
@@ -748,8 +771,10 @@
     }
 
     /** Returns AutofillCallback if need fire EVENT_INPUT_UNAVAILABLE */
+    @GuardedBy("mLock")
     private AutofillCallback notifyViewEnteredLocked(@NonNull View view, int flags) {
-        if (shouldIgnoreViewEnteredLocked(view, flags)) return null;
+        final AutofillId id = getAutofillId(view);
+        if (shouldIgnoreViewEnteredLocked(id, flags)) return null;
 
         AutofillCallback callback = null;
 
@@ -762,7 +787,6 @@
         } else {
             // don't notify entered when Activity is already in background
             if (!isClientDisablingEnterExitEvent()) {
-                final AutofillId id = getAutofillId(view);
                 final AutofillValue value = view.getAutofillValue();
 
                 if (!isActiveLocked()) {
@@ -772,6 +796,7 @@
                     // Update focus on existing session.
                     updateSessionLocked(id, null, value, ACTION_VIEW_ENTERED, flags);
                 }
+                addEnteredIdLocked(id);
             }
         }
         return callback;
@@ -791,6 +816,7 @@
         }
     }
 
+    @GuardedBy("mLock")
     void notifyViewExitedLocked(@NonNull View view) {
         ensureServiceClientAddedIfNeededLocked();
 
@@ -892,10 +918,12 @@
     }
 
     /** Returns AutofillCallback if need fire EVENT_INPUT_UNAVAILABLE */
+    @GuardedBy("mLock")
     private AutofillCallback notifyViewEnteredLocked(View view, int virtualId, Rect bounds,
                                                      int flags) {
+        final AutofillId id = getAutofillId(view, virtualId);
         AutofillCallback callback = null;
-        if (shouldIgnoreViewEnteredLocked(view, flags)) return callback;
+        if (shouldIgnoreViewEnteredLocked(id, flags)) return callback;
 
         ensureServiceClientAddedIfNeededLocked();
 
@@ -906,8 +934,6 @@
         } else {
             // don't notify entered when Activity is already in background
             if (!isClientDisablingEnterExitEvent()) {
-                final AutofillId id = getAutofillId(view, virtualId);
-
                 if (!isActiveLocked()) {
                     // Starts new session.
                     startSessionLocked(id, bounds, null, flags);
@@ -915,11 +941,20 @@
                     // Update focus on existing session.
                     updateSessionLocked(id, bounds, null, ACTION_VIEW_ENTERED, flags);
                 }
+                addEnteredIdLocked(id);
             }
         }
         return callback;
     }
 
+    @GuardedBy("mLock")
+    private void addEnteredIdLocked(@NonNull AutofillId id) {
+        if (mEnteredIds == null) {
+            mEnteredIds = new ArraySet<>(1);
+        }
+        mEnteredIds.add(id);
+    }
+
     /**
      * Called when a virtual view that supports autofill is exited.
      *
@@ -935,6 +970,7 @@
         }
     }
 
+    @GuardedBy("mLock")
     private void notifyViewExitedLocked(@NonNull View view, int virtualId) {
         ensureServiceClientAddedIfNeededLocked();
 
@@ -985,9 +1021,9 @@
             }
 
             if (!mEnabled || !isActiveLocked()) {
-                if (sVerbose && mEnabled) {
-                    Log.v(TAG, "notifyValueChanged(" + view + "): ignoring on state "
-                            + getStateAsStringLocked());
+                if (sVerbose) {
+                    Log.v(TAG, "notifyValueChanged(" + view.getAutofillId()
+                            + "): ignoring on state " + getStateAsStringLocked());
                 }
                 return;
             }
@@ -1017,6 +1053,10 @@
         }
         synchronized (mLock) {
             if (!mEnabled || !isActiveLocked()) {
+                if (sVerbose) {
+                    Log.v(TAG, "notifyValueChanged(" + view.getAutofillId() + ":" + virtualId
+                            + "): ignoring on state " + getStateAsStringLocked());
+                }
                 return;
             }
 
@@ -1025,18 +1065,35 @@
         }
     }
 
+    /**
+     * Called to indicate a {@link View} is clicked.
+     *
+     * @param view view that has been clicked.
+     */
+    public void notifyViewClicked(@NonNull View view) {
+        notifyViewClicked(view.getAutofillId());
+    }
 
     /**
-     * Called when a {@link View} is clicked. Currently only used by views that should trigger save.
+     * Called to indicate a virtual view has been clicked.
      *
-     * @hide
+     * @param view the virtual view parent.
+     * @param virtualId id identifying the virtual child inside the parent view.
      */
-    public void notifyViewClicked(View view) {
-        final AutofillId id = view.getAutofillId();
+    public void notifyViewClicked(@NonNull View view, int virtualId) {
+        notifyViewClicked(getAutofillId(view, virtualId));
+    }
 
+    private void notifyViewClicked(AutofillId id) {
+        if (!hasAutofillFeature()) {
+            return;
+        }
         if (sVerbose) Log.v(TAG, "notifyViewClicked(): id=" + id + ", trigger=" + mSaveTriggerId);
 
         synchronized (mLock) {
+            if (!mEnabled || !isActiveLocked()) {
+                return;
+            }
             if (mSaveTriggerId != null && mSaveTriggerId.equals(id)) {
                 if (sDebug) Log.d(TAG, "triggering commit by click of " + id);
                 commitLocked();
@@ -1051,16 +1108,16 @@
      *
      * @hide
      */
-    public void onActivityFinished() {
+    public void onActivityFinishing() {
         if (!hasAutofillFeature()) {
             return;
         }
         synchronized (mLock) {
             if (mSaveOnFinish) {
-                if (sDebug) Log.d(TAG, "Committing session on finish() as requested by service");
+                if (sDebug) Log.d(TAG, "onActivityFinishing(): calling commitLocked()");
                 commitLocked();
             } else {
-                if (sDebug) Log.d(TAG, "Cancelling session on finish() as requested by service");
+                if (sDebug) Log.d(TAG, "onActivityFinishing(): calling cancelLocked()");
                 cancelLocked();
             }
         }
@@ -1081,11 +1138,13 @@
         if (!hasAutofillFeature()) {
             return;
         }
+        if (sVerbose) Log.v(TAG, "commit() called by app");
         synchronized (mLock) {
             commitLocked();
         }
     }
 
+    @GuardedBy("mLock")
     private void commitLocked() {
         if (!mEnabled && !isActiveLocked()) {
             return;
@@ -1114,6 +1173,7 @@
         }
     }
 
+    @GuardedBy("mLock")
     private void cancelLocked() {
         if (!mEnabled && !isActiveLocked()) {
             return;
@@ -1377,11 +1437,14 @@
         return new AutofillId(parent.getAutofillViewId(), virtualId);
     }
 
+    @GuardedBy("mLock")
     private void startSessionLocked(@NonNull AutofillId id, @NonNull Rect bounds,
             @NonNull AutofillValue value, int flags) {
         if (sVerbose) {
             Log.v(TAG, "startSessionLocked(): id=" + id + ", bounds=" + bounds + ", value=" + value
-                    + ", flags=" + flags + ", state=" + getStateAsStringLocked());
+                    + ", flags=" + flags + ", state=" + getStateAsStringLocked()
+                    + ", compatMode=" + isCompatibilityModeEnabledLocked()
+                    + ", enteredIds=" + mEnteredIds);
         }
         if (mState != STATE_UNKNOWN && !isFinishedLocked() && (flags & FLAG_MANUAL_REQUEST) == 0) {
             if (sVerbose) {
@@ -1392,11 +1455,12 @@
         }
         try {
             final AutofillClient client = getClient();
-            if (client == null) return; // NOTE: getClient() already logd it..
+            if (client == null) return; // NOTE: getClient() already logged it..
 
             mSessionId = mService.startSession(client.autofillClientGetActivityToken(),
                     mServiceClient.asBinder(), id, bounds, value, mContext.getUserId(),
-                    mCallback != null, flags, client.autofillClientGetComponentName());
+                    mCallback != null, flags, client.autofillClientGetComponentName(),
+                    isCompatibilityModeEnabledLocked());
             if (mSessionId != NO_SESSION) {
                 mState = STATE_ACTIVE;
             }
@@ -1406,6 +1470,7 @@
         }
     }
 
+    @GuardedBy("mLock")
     private void finishSessionLocked() {
         if (sVerbose) Log.v(TAG, "finishSessionLocked(): " + getStateAsStringLocked());
 
@@ -1417,9 +1482,10 @@
             throw e.rethrowFromSystemServer();
         }
 
-        resetSessionLocked();
+        resetSessionLocked(/* resetEnteredIds= */ true);
     }
 
+    @GuardedBy("mLock")
     private void cancelSessionLocked() {
         if (sVerbose) Log.v(TAG, "cancelSessionLocked(): " + getStateAsStringLocked());
 
@@ -1431,20 +1497,25 @@
             throw e.rethrowFromSystemServer();
         }
 
-        resetSessionLocked();
+        resetSessionLocked(/* resetEnteredIds= */ true);
     }
 
-    private void resetSessionLocked() {
+    @GuardedBy("mLock")
+    private void resetSessionLocked(boolean resetEnteredIds) {
         mSessionId = NO_SESSION;
         mState = STATE_UNKNOWN;
         mTrackedViews = null;
         mFillableIds = null;
         mSaveTriggerId = null;
+        if (resetEnteredIds) {
+            mEnteredIds = null;
+        }
     }
 
+    @GuardedBy("mLock")
     private void updateSessionLocked(AutofillId id, Rect bounds, AutofillValue value, int action,
             int flags) {
-        if (sVerbose && action != ACTION_VIEW_EXITED) {
+        if (sVerbose) {
             Log.v(TAG, "updateSessionLocked(): id=" + id + ", bounds=" + bounds
                     + ", value=" + value + ", action=" + action + ", flags=" + flags);
         }
@@ -1459,7 +1530,7 @@
                         client.autofillClientGetActivityToken(),
                         mServiceClient.asBinder(), id, bounds, value, mContext.getUserId(),
                         mCallback != null, flags, client.autofillClientGetComponentName(),
-                        mSessionId, action);
+                        mSessionId, action, isCompatibilityModeEnabledLocked());
                 if (newId != mSessionId) {
                     if (sDebug) Log.d(TAG, "Session restarted: " + mSessionId + "=>" + newId);
                     mSessionId = newId;
@@ -1476,6 +1547,7 @@
         }
     }
 
+    @GuardedBy("mLock")
     private void ensureServiceClientAddedIfNeededLocked() {
         if (getClient() == null) {
             return;
@@ -1613,7 +1685,7 @@
             mEnabled = (flags & SET_STATE_FLAG_ENABLED) != 0;
             if (!mEnabled || (flags & SET_STATE_FLAG_RESET_SESSION) != 0) {
                 // Reset the session state
-                resetSessionLocked();
+                resetSessionLocked(/* resetEnteredIds= */ true);
             }
             if ((flags & SET_STATE_FLAG_RESET_CLIENT) != 0) {
                 // Reset connection to system
@@ -1809,7 +1881,7 @@
     private void setSessionFinished(int newState) {
         synchronized (mLock) {
             if (sVerbose) Log.v(TAG, "setSessionFinished(): from " + mState + " to " + newState);
-            resetSessionLocked();
+            resetSessionLocked(/* resetEnteredIds= */ false);
             mState = newState;
         }
     }
@@ -1937,13 +2009,16 @@
             pw.print(pfx2); pw.print("invisible:"); pw.println(mTrackedViews.mInvisibleTrackedIds);
         }
         pw.print(pfx); pw.print("fillable ids: "); pw.println(mFillableIds);
+        pw.print(pfx); pw.print("entered ids: "); pw.println(mEnteredIds);
         pw.print(pfx); pw.print("save trigger id: "); pw.println(mSaveTriggerId);
         pw.print(pfx); pw.print("save on finish(): "); pw.println(mSaveOnFinish);
-        pw.print(pfx); pw.print("compat mode enabled: "); pw.println(isCompatibilityModeEnabled());
+        pw.print(pfx); pw.print("compat mode enabled: "); pw.println(
+                isCompatibilityModeEnabledLocked());
         pw.print(pfx); pw.print("debug: "); pw.print(sDebug);
         pw.print(" verbose: "); pw.println(sVerbose);
     }
 
+    @GuardedBy("mLock")
     private String getStateAsStringLocked() {
         switch (mState) {
             case STATE_UNKNOWN:
@@ -1961,14 +2036,17 @@
         }
     }
 
+    @GuardedBy("mLock")
     private boolean isActiveLocked() {
         return mState == STATE_ACTIVE;
     }
 
+    @GuardedBy("mLock")
     private boolean isDisabledByServiceLocked() {
         return mState == STATE_DISABLED_BY_SERVICE;
     }
 
+    @GuardedBy("mLock")
     private boolean isFinishedLocked() {
         return mState == STATE_FINISHED;
     }
@@ -2164,6 +2242,7 @@
                     AutofillValue.forText(node.getText()));
         }
 
+        @GuardedBy("mLock")
         private void updateTrackedViewsLocked() {
             if (mTrackedViews != null) {
                 mTrackedViews.onVisibleForAutofillChangedLocked();
@@ -2273,6 +2352,7 @@
                 final boolean[] isVisible;
 
                 if (client.autofillClientIsVisibleForAutofill()) {
+                    if (sVerbose) Log.v(TAG, "client is visible, check tracked ids");
                     isVisible = client.autofillClientGetViewVisibility(trackedIds);
                 } else {
                     // All false
@@ -2292,7 +2372,7 @@
             }
 
             if (sVerbose) {
-                Log.v(TAG, "TrackedViews(trackedIds=" + trackedIds + "): "
+                Log.v(TAG, "TrackedViews(trackedIds=" + Arrays.toString(trackedIds) + "): "
                         + " mVisibleTrackedIds=" + mVisibleTrackedIds
                         + " mInvisibleTrackedIds=" + mInvisibleTrackedIds);
             }
@@ -2308,6 +2388,7 @@
          * @param id the id of the view/virtual view whose visibility changed.
          * @param isVisible visible if the view is visible in the view hierarchy.
          */
+        @GuardedBy("mLock")
         void notifyViewVisibilityChangedLocked(@NonNull AutofillId id, boolean isVisible) {
             if (sDebug) {
                 Log.d(TAG, "notifyViewVisibilityChangedLocked(): id=" + id + " isVisible="
@@ -2341,6 +2422,7 @@
          *
          * @see AutofillClient#autofillClientIsVisibleForAutofill()
          */
+        @GuardedBy("mLock")
         void onVisibleForAutofillChangedLocked() {
             // The visibility of the views might have changed while the client was not be visible,
             // hence update the visibility state for all views.
@@ -2396,6 +2478,9 @@
             }
 
             if (mVisibleTrackedIds == null) {
+                if (sVerbose) {
+                    Log.v(TAG, "onVisibleForAutofillChangedLocked(): no more visible ids");
+                }
                 finishSessionLocked();
             }
         }
diff --git a/core/java/android/view/autofill/AutofillPopupWindow.java b/core/java/android/view/autofill/AutofillPopupWindow.java
index e80fdd9..1da998d 100644
--- a/core/java/android/view/autofill/AutofillPopupWindow.java
+++ b/core/java/android/view/autofill/AutofillPopupWindow.java
@@ -46,6 +46,7 @@
 
     private final WindowPresenter mWindowPresenter;
     private WindowManager.LayoutParams mWindowLayoutParams;
+    private boolean mFullScreen;
 
     private final View.OnAttachStateChangeListener mOnAttachStateChangeListener =
             new View.OnAttachStateChangeListener() {
@@ -104,12 +105,17 @@
      */
     public void update(View anchor, int offsetX, int offsetY, int width, int height,
             Rect virtualBounds) {
+        mFullScreen = width == LayoutParams.MATCH_PARENT && height == LayoutParams.MATCH_PARENT;
         // If we are showing the popup for a virtual view we use a fake view which
         // delegates to the anchor but present itself with the same bounds as the
         // virtual view. This ensures that the location logic in popup works
         // symmetrically when the dropdown is below and above the anchor.
         final View actualAnchor;
-        if (virtualBounds != null) {
+        if (mFullScreen) {
+            offsetX = 0;
+            offsetY = 0;
+            actualAnchor = anchor;
+        } else if (virtualBounds != null) {
             final int[] mLocationOnScreen = new int[] {virtualBounds.left, virtualBounds.top};
             actualAnchor = new View(anchor.getContext()) {
                 @Override
@@ -209,6 +215,17 @@
     }
 
     @Override
+    protected boolean findDropDownPosition(View anchor, LayoutParams outParams,
+            int xOffset, int yOffset, int width, int height, int gravity, boolean allowScroll) {
+        if (mFullScreen) {
+            // Do not patch LayoutParams if force full screen
+            return false;
+        }
+        return super.findDropDownPosition(anchor, outParams, xOffset, yOffset,
+                width, height, gravity, allowScroll);
+    }
+
+    @Override
     public void showAsDropDown(View anchor, int xoff, int yoff, int gravity) {
         if (sVerbose) {
             Log.v(TAG, "showAsDropDown(): anchor=" + anchor + ", xoff=" + xoff + ", yoff=" + yoff
diff --git a/core/java/android/view/autofill/IAutoFillManager.aidl b/core/java/android/view/autofill/IAutoFillManager.aidl
index 0018547..56f79ab 100644
--- a/core/java/android/view/autofill/IAutoFillManager.aidl
+++ b/core/java/android/view/autofill/IAutoFillManager.aidl
@@ -38,7 +38,7 @@
     void removeClient(in IAutoFillManagerClient client, int userId);
     int startSession(IBinder activityToken, in IBinder appCallback, in AutofillId autoFillId,
             in Rect bounds, in AutofillValue value, int userId, boolean hasCallback, int flags,
-            in ComponentName componentName);
+            in ComponentName componentName, boolean compatMode);
     FillEventHistory getFillEventHistory();
     boolean restoreSession(int sessionId, in IBinder activityToken, in IBinder appCallback);
     void updateSession(int sessionId, in AutofillId id, in Rect bounds,
@@ -46,7 +46,7 @@
     int updateOrRestartSession(IBinder activityToken, in IBinder appCallback,
             in AutofillId autoFillId, in Rect bounds, in AutofillValue value, int userId,
             boolean hasCallback, int flags, in ComponentName componentName, int sessionId,
-            int action);
+            int action, boolean compatMode);
     void finishSession(int sessionId, int userId);
     void cancelSession(int sessionId, int userId);
     void setAuthenticationResult(in Bundle data, int sessionId, int authenticationId, int userId);
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 9de26a8..a2280a4 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -20,10 +20,12 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.RequiresFeature;
 import android.annotation.RequiresPermission;
 import android.annotation.SystemService;
 import android.annotation.TestApi;
 import android.content.Context;
+import android.content.pm.PackageManager;
 import android.graphics.Rect;
 import android.inputmethodservice.InputMethodService;
 import android.net.Uri;
@@ -213,6 +215,7 @@
  * </ul>
  */
 @SystemService(Context.INPUT_METHOD_SERVICE)
+@RequiresFeature(PackageManager.FEATURE_INPUT_METHODS)
 public final class InputMethodManager {
     static final boolean DEBUG = false;
     static final String TAG = "InputMethodManager";
diff --git a/core/java/android/view/textclassifier/SmartSelection.java b/core/java/android/view/textclassifier/SmartSelection.java
index 8edf97e..69c38ee 100644
--- a/core/java/android/view/textclassifier/SmartSelection.java
+++ b/core/java/android/view/textclassifier/SmartSelection.java
@@ -108,9 +108,9 @@
     }
 
     /**
-     * Returns the language of the model.
+     * Returns a comma separated list of locales supported by the model as BCP 47 tags.
      */
-    public static String getLanguage(int fd) {
+    public static String getLanguages(int fd) {
         return nativeGetLanguage(fd);
     }
 
diff --git a/core/java/android/view/textclassifier/SystemTextClassifier.java b/core/java/android/view/textclassifier/SystemTextClassifier.java
index af55dcd..cbc3828 100644
--- a/core/java/android/view/textclassifier/SystemTextClassifier.java
+++ b/core/java/android/view/textclassifier/SystemTextClassifier.java
@@ -121,6 +121,15 @@
         return mFallback.generateLinks(text, options);
     }
 
+    /**
+     * @inheritDoc
+     */
+    @Override
+    public int getMaxGenerateLinksTextLength() {
+        // TODO: retrieve this from the bound service.
+        return mFallback.getMaxGenerateLinksTextLength();
+    }
+
     private static final class TextSelectionCallback extends ITextSelectionCallback.Stub {
 
         final ResponseReceiver<TextSelection> mReceiver = new ResponseReceiver<>();
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/TextClassifier.java b/core/java/android/view/textclassifier/TextClassifier.java
index 9f75c4a..2a62f23 100644
--- a/core/java/android/view/textclassifier/TextClassifier.java
+++ b/core/java/android/view/textclassifier/TextClassifier.java
@@ -276,9 +276,11 @@
      * @param text the text to generate annotations for
      * @param options configuration for link generation
      *
-     * @throws IllegalArgumentException if text is null
+     * @throws IllegalArgumentException if text is null or the text is too long for the
+     *      TextClassifier implementation.
      *
      * @see #generateLinks(CharSequence)
+     * @see #getMaxGenerateLinksTextLength()
      */
     @WorkerThread
     default TextLinks generateLinks(
@@ -299,9 +301,11 @@
      *
      * @param text the text to generate annotations for
      *
-     * @throws IllegalArgumentException if text is null
+     * @throws IllegalArgumentException if text is null or the text is too long for the
+     *      TextClassifier implementation.
      *
      * @see #generateLinks(CharSequence, TextLinks.Options)
+     * @see #getMaxGenerateLinksTextLength()
      */
     @WorkerThread
     default TextLinks generateLinks(@NonNull CharSequence text) {
@@ -309,6 +313,16 @@
     }
 
     /**
+     * Returns the maximal length of text that can be processed by generateLinks.
+     *
+     * @see #generateLinks(CharSequence)
+     * @see #generateLinks(CharSequence, TextLinks.Options)
+     */
+    default int getMaxGenerateLinksTextLength() {
+        return Integer.MAX_VALUE;
+    }
+
+    /**
      * Returns a {@link Collection} of the entity types in the specified preset.
      *
      * @see #ENTITY_PRESET_ALL
@@ -461,6 +475,15 @@
             checkMainThread(allowInMainThread);
         }
 
+        /**
+         * @throws IllegalArgumentException if text is null; the text is too long or options is null
+         */
+        public static void validate(@NonNull CharSequence text, int maxLength,
+                boolean allowInMainThread) {
+            validate(text, allowInMainThread);
+            Preconditions.checkArgumentInRange(text.length(), 0, maxLength, "text.length()");
+        }
+
         private static void checkMainThread(boolean allowInMainThread) {
             if (!allowInMainThread && Looper.myLooper() == Looper.getMainLooper()) {
                 Slog.w(DEFAULT_LOG_TAG, "TextClassifier called on main thread");
diff --git a/core/java/android/view/textclassifier/TextClassifierConstants.java b/core/java/android/view/textclassifier/TextClassifierConstants.java
index 00695b7..efa6948 100644
--- a/core/java/android/view/textclassifier/TextClassifierConstants.java
+++ b/core/java/android/view/textclassifier/TextClassifierConstants.java
@@ -47,10 +47,19 @@
             "smart_selection_enabled_for_edit_text";
     private static final String SMART_LINKIFY_ENABLED =
             "smart_linkify_enabled";
+    private static final String SUGGEST_SELECTION_MAX_RANGE_LENGTH =
+            "suggest_selection_max_range_length";
+    private static final String CLASSIFY_TEXT_MAX_RANGE_LENGTH =
+            "classify_text_max_range_length";
+    private static final String GENERATE_LINKS_MAX_TEXT_LENGTH =
+            "generate_links_max_text_length";
 
     private static final boolean SMART_SELECTION_DARK_LAUNCH_DEFAULT = false;
     private static final boolean SMART_SELECTION_ENABLED_FOR_EDIT_TEXT_DEFAULT = true;
     private static final boolean SMART_LINKIFY_ENABLED_DEFAULT = true;
+    private static final int SUGGEST_SELECTION_MAX_RANGE_LENGTH_DEFAULT = 10 * 1000;
+    private static final int CLASSIFY_TEXT_MAX_RANGE_LENGTH_DEFAULT = 10 * 1000;
+    private static final int GENERATE_LINKS_MAX_TEXT_LENGTH_DEFAULT = 100 * 1000;
 
     /** Default settings. */
     static final TextClassifierConstants DEFAULT = new TextClassifierConstants();
@@ -58,11 +67,17 @@
     private final boolean mDarkLaunch;
     private final boolean mSuggestSelectionEnabledForEditableText;
     private final boolean mSmartLinkifyEnabled;
+    private final int mSuggestSelectionMaxRangeLength;
+    private final int mClassifyTextMaxRangeLength;
+    private final int mGenerateLinksMaxTextLength;
 
     private TextClassifierConstants() {
         mDarkLaunch = SMART_SELECTION_DARK_LAUNCH_DEFAULT;
         mSuggestSelectionEnabledForEditableText = SMART_SELECTION_ENABLED_FOR_EDIT_TEXT_DEFAULT;
         mSmartLinkifyEnabled = SMART_LINKIFY_ENABLED_DEFAULT;
+        mSuggestSelectionMaxRangeLength = SUGGEST_SELECTION_MAX_RANGE_LENGTH_DEFAULT;
+        mClassifyTextMaxRangeLength = CLASSIFY_TEXT_MAX_RANGE_LENGTH_DEFAULT;
+        mGenerateLinksMaxTextLength = GENERATE_LINKS_MAX_TEXT_LENGTH_DEFAULT;
     }
 
     private TextClassifierConstants(@Nullable String settings) {
@@ -82,6 +97,15 @@
         mSmartLinkifyEnabled = parser.getBoolean(
                 SMART_LINKIFY_ENABLED,
                 SMART_LINKIFY_ENABLED_DEFAULT);
+        mSuggestSelectionMaxRangeLength = parser.getInt(
+                SUGGEST_SELECTION_MAX_RANGE_LENGTH,
+                SUGGEST_SELECTION_MAX_RANGE_LENGTH_DEFAULT);
+        mClassifyTextMaxRangeLength = parser.getInt(
+                CLASSIFY_TEXT_MAX_RANGE_LENGTH,
+                CLASSIFY_TEXT_MAX_RANGE_LENGTH_DEFAULT);
+        mGenerateLinksMaxTextLength = parser.getInt(
+                GENERATE_LINKS_MAX_TEXT_LENGTH,
+                GENERATE_LINKS_MAX_TEXT_LENGTH_DEFAULT);
     }
 
     static TextClassifierConstants loadFromString(String settings) {
@@ -99,4 +123,16 @@
     public boolean isSmartLinkifyEnabled() {
         return mSmartLinkifyEnabled;
     }
+
+    public int getSuggestSelectionMaxRangeLength() {
+        return mSuggestSelectionMaxRangeLength;
+    }
+
+    public int getClassifyTextMaxRangeLength() {
+        return mClassifyTextMaxRangeLength;
+    }
+
+    public int getGenerateLinksMaxTextLength() {
+        return mGenerateLinksMaxTextLength;
+    }
 }
diff --git a/core/java/android/view/textclassifier/TextClassifierImpl.java b/core/java/android/view/textclassifier/TextClassifierImpl.java
index 9f389ba..795caff 100644
--- a/core/java/android/view/textclassifier/TextClassifierImpl.java
+++ b/core/java/android/view/textclassifier/TextClassifierImpl.java
@@ -27,8 +27,10 @@
 import android.content.pm.ResolveInfo;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
+import android.os.Bundle;
 import android.os.LocaleList;
 import android.os.ParcelFileDescriptor;
+import android.os.UserManager;
 import android.provider.Browser;
 import android.provider.CalendarContract;
 import android.provider.ContactsContract;
@@ -56,6 +58,7 @@
 import java.util.Locale;
 import java.util.Map;
 import java.util.Objects;
+import java.util.StringJoiner;
 import java.util.concurrent.TimeUnit;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
@@ -99,11 +102,9 @@
 
     private final Object mLock = new Object();
     @GuardedBy("mLock") // Do not access outside this lock.
-    private Map<Locale, String> mModelFilePaths;
+    private List<ModelFile> mAllModelFiles;
     @GuardedBy("mLock") // Do not access outside this lock.
-    private Locale mLocale;
-    @GuardedBy("mLock") // Do not access outside this lock.
-    private int mVersion;
+    private ModelFile mModel;
     @GuardedBy("mLock") // Do not access outside this lock.
     private SmartSelection mSmartSelection;
 
@@ -127,7 +128,9 @@
             @Nullable TextSelection.Options options) {
         Utils.validate(text, selectionStartIndex, selectionEndIndex, false /* allowInMainThread */);
         try {
-            if (text.length() > 0) {
+            final int rangeLength = selectionEndIndex - selectionStartIndex;
+            if (text.length() > 0
+                    && rangeLength <= getSettings().getSuggestSelectionMaxRangeLength()) {
                 final LocaleList locales = (options == null) ? null : options.getDefaultLocales();
                 final boolean darkLaunchAllowed = options != null && options.isDarkLaunchAllowed();
                 final SmartSelection smartSelection = getSmartSelection(locales);
@@ -182,7 +185,8 @@
             @Nullable TextClassification.Options options) {
         Utils.validate(text, startIndex, endIndex, false /* allowInMainThread */);
         try {
-            if (text.length() > 0) {
+            final int rangeLength = endIndex - startIndex;
+            if (text.length() > 0 && rangeLength <= getSettings().getClassifyTextMaxRangeLength()) {
                 final String string = text.toString();
                 final LocaleList locales = (options == null) ? null : options.getDefaultLocales();
                 final Calendar refTime = (options == null) ? null : options.getReferenceTime();
@@ -206,7 +210,7 @@
     @Override
     public TextLinks generateLinks(
             @NonNull CharSequence text, @Nullable TextLinks.Options options) {
-        Utils.validate(text, false /* allowInMainThread */);
+        Utils.validate(text, getMaxGenerateLinksTextLength(), false /* allowInMainThread */);
         final String textString = text.toString();
         final TextLinks.Builder builder = new TextLinks.Builder(textString);
 
@@ -240,6 +244,12 @@
         return mFallback.generateLinks(text, options);
     }
 
+    /** @inheritDoc */
+    @Override
+    public int getMaxGenerateLinksTextLength() {
+        return getSettings().getGenerateLinksMaxTextLength();
+    }
+
     @Override
     public Collection<String> getEntitiesForPreset(@TextClassifier.EntityPreset int entityPreset) {
         switch (entityPreset) {
@@ -279,18 +289,18 @@
     private SmartSelection getSmartSelection(LocaleList localeList) throws FileNotFoundException {
         synchronized (mLock) {
             localeList = localeList == null ? LocaleList.getEmptyLocaleList() : localeList;
-            final Locale locale = findBestSupportedLocaleLocked(localeList);
-            if (locale == null) {
-                throw new FileNotFoundException("No file for null locale");
+            final ModelFile bestModel = findBestModelLocked(localeList);
+            if (bestModel == null) {
+                throw new FileNotFoundException("No model for " + localeList.toLanguageTags());
             }
-            if (mSmartSelection == null || !Objects.equals(mLocale, locale)) {
+            if (mSmartSelection == null || !Objects.equals(mModel, bestModel)) {
+                Log.d(DEFAULT_LOG_TAG, "Loading " + bestModel);
                 destroySmartSelectionIfExistsLocked();
-                final ParcelFileDescriptor fd = getFdLocked(locale);
-                final int modelFd = fd.getFd();
-                mVersion = SmartSelection.getVersion(modelFd);
-                mSmartSelection = new SmartSelection(modelFd);
+                final ParcelFileDescriptor fd = ParcelFileDescriptor.open(
+                        new File(bestModel.getPath()), ParcelFileDescriptor.MODE_READ_ONLY);
+                mSmartSelection = new SmartSelection(fd.getFd());
                 closeAndLogError(fd);
-                mLocale = locale;
+                mModel = bestModel;
             }
             return mSmartSelection;
         }
@@ -298,74 +308,8 @@
 
     private String getSignature(String text, int start, int end) {
         synchronized (mLock) {
-            return DefaultLogger.createSignature(text, start, end, mContext, mVersion, mLocale);
-        }
-    }
-
-    @GuardedBy("mLock") // Do not call outside this lock.
-    private ParcelFileDescriptor getFdLocked(Locale locale) throws FileNotFoundException {
-        ParcelFileDescriptor updateFd;
-        int updateVersion = -1;
-        try {
-            updateFd = ParcelFileDescriptor.open(
-                    new File(UPDATED_MODEL_FILE_PATH), ParcelFileDescriptor.MODE_READ_ONLY);
-            if (updateFd != null) {
-                updateVersion = SmartSelection.getVersion(updateFd.getFd());
-            }
-        } catch (FileNotFoundException e) {
-            updateFd = null;
-        }
-        ParcelFileDescriptor factoryFd;
-        int factoryVersion = -1;
-        try {
-            final String factoryModelFilePath = getFactoryModelFilePathsLocked().get(locale);
-            if (factoryModelFilePath != null) {
-                factoryFd = ParcelFileDescriptor.open(
-                        new File(factoryModelFilePath), ParcelFileDescriptor.MODE_READ_ONLY);
-                if (factoryFd != null) {
-                    factoryVersion = SmartSelection.getVersion(factoryFd.getFd());
-                }
-            } else {
-                factoryFd = null;
-            }
-        } catch (FileNotFoundException e) {
-            factoryFd = null;
-        }
-
-        if (updateFd == null) {
-            if (factoryFd != null) {
-                return factoryFd;
-            } else {
-                throw new FileNotFoundException(
-                        String.format(Locale.US, "No model file found for %s", locale));
-            }
-        }
-
-        final int updateFdInt = updateFd.getFd();
-        final boolean localeMatches = Objects.equals(
-                locale.getLanguage().trim().toLowerCase(),
-                SmartSelection.getLanguage(updateFdInt).trim().toLowerCase());
-        if (factoryFd == null) {
-            if (localeMatches) {
-                return updateFd;
-            } else {
-                closeAndLogError(updateFd);
-                throw new FileNotFoundException(
-                        String.format(Locale.US, "No model file found for %s", locale));
-            }
-        }
-
-        if (!localeMatches) {
-            closeAndLogError(updateFd);
-            return factoryFd;
-        }
-
-        if (updateVersion > factoryVersion) {
-            closeAndLogError(factoryFd);
-            return updateFd;
-        } else {
-            closeAndLogError(updateFd);
-            return factoryFd;
+            return DefaultLogger.createSignature(text, start, end, mContext, mModel.getVersion(),
+                    mModel.getSupportedLocales());
         }
     }
 
@@ -377,60 +321,66 @@
         }
     }
 
+    /**
+     * Finds the most appropriate model to use for the given target locale list.
+     *
+     * The basic logic is: we ignore all models that don't support any of the target locales. For
+     * the remaining candidates, we take the update model unless its version number is lower than
+     * the factory version. It's assumed that factory models do not have overlapping locale ranges
+     * and conflict resolution between these models hence doesn't matter.
+     */
     @GuardedBy("mLock") // Do not call outside this lock.
     @Nullable
-    private Locale findBestSupportedLocaleLocked(LocaleList localeList) {
+    private ModelFile findBestModelLocked(LocaleList localeList) {
         // Specified localeList takes priority over the system default, so it is listed first.
         final String languages = localeList.isEmpty()
                 ? LocaleList.getDefault().toLanguageTags()
                 : localeList.toLanguageTags() + "," + LocaleList.getDefault().toLanguageTags();
         final List<Locale.LanguageRange> languageRangeList = Locale.LanguageRange.parse(languages);
 
-        final List<Locale> supportedLocales =
-                new ArrayList<>(getFactoryModelFilePathsLocked().keySet());
-        final Locale updatedModelLocale = getUpdatedModelLocale();
-        if (updatedModelLocale != null) {
-            supportedLocales.add(updatedModelLocale);
+        ModelFile bestModel = null;
+        int bestModelVersion = -1;
+        for (ModelFile model : listAllModelsLocked()) {
+            if (model.isAnyLanguageSupported(languageRangeList)) {
+                if (model.getVersion() >= bestModelVersion) {
+                    bestModel = model;
+                    bestModelVersion = model.getVersion();
+                }
+            }
         }
-        return Locale.lookup(languageRangeList, supportedLocales);
+        return bestModel;
     }
 
+    /** Returns a list of all model files available, in order of precedence. */
     @GuardedBy("mLock") // Do not call outside this lock.
-    private Map<Locale, String> getFactoryModelFilePathsLocked() {
-        if (mModelFilePaths == null) {
-            final Map<Locale, String> modelFilePaths = new HashMap<>();
+    private List<ModelFile> listAllModelsLocked() {
+        if (mAllModelFiles == null) {
+            final List<ModelFile> allModels = new ArrayList<>();
+            // The update model has the highest precedence.
+            if (new File(UPDATED_MODEL_FILE_PATH).exists()) {
+                final ModelFile updatedModel = ModelFile.fromPath(UPDATED_MODEL_FILE_PATH);
+                if (updatedModel != null) {
+                    allModels.add(updatedModel);
+                }
+            }
+            // Factory models should never have overlapping locales, so the order doesn't matter.
             final File modelsDir = new File(MODEL_DIR);
             if (modelsDir.exists() && modelsDir.isDirectory()) {
-                final File[] models = modelsDir.listFiles();
+                final File[] modelFiles = modelsDir.listFiles();
                 final Pattern modelFilenamePattern = Pattern.compile(MODEL_FILE_REGEX);
-                final int size = models.length;
-                for (int i = 0; i < size; i++) {
-                    final File modelFile = models[i];
+                for (File modelFile : modelFiles) {
                     final Matcher matcher = modelFilenamePattern.matcher(modelFile.getName());
                     if (matcher.matches() && modelFile.isFile()) {
-                        final String language = matcher.group(1);
-                        final Locale locale = Locale.forLanguageTag(language);
-                        modelFilePaths.put(locale, modelFile.getAbsolutePath());
+                        final ModelFile model = ModelFile.fromPath(modelFile.getAbsolutePath());
+                        if (model != null) {
+                            allModels.add(model);
+                        }
                     }
                 }
             }
-            mModelFilePaths = modelFilePaths;
+            mAllModelFiles = allModels;
         }
-        return mModelFilePaths;
-    }
-
-    @Nullable
-    private Locale getUpdatedModelLocale() {
-        try {
-            final ParcelFileDescriptor updateFd = ParcelFileDescriptor.open(
-                    new File(UPDATED_MODEL_FILE_PATH), ParcelFileDescriptor.MODE_READ_ONLY);
-            final Locale locale = Locale.forLanguageTag(
-                    SmartSelection.getLanguage(updateFd.getFd()));
-            closeAndLogError(updateFd);
-            return locale;
-        } catch (FileNotFoundException e) {
-            return null;
-        }
+        return mAllModelFiles;
     }
 
     private TextClassification createClassificationResult(
@@ -520,6 +470,95 @@
     }
 
     /**
+     * Describes TextClassifier model files on disk.
+     */
+    private static final class ModelFile {
+
+        private final String mPath;
+        private final String mName;
+        private final int mVersion;
+        private final List<Locale> mSupportedLocales;
+
+        /** Returns null if the path did not point to a compatible model. */
+        static @Nullable ModelFile fromPath(String path) {
+            final File file = new File(path);
+            try {
+                final ParcelFileDescriptor modelFd = ParcelFileDescriptor.open(
+                        file, ParcelFileDescriptor.MODE_READ_ONLY);
+                final int version = SmartSelection.getVersion(modelFd.getFd());
+                final String supportedLocalesStr = SmartSelection.getLanguages(modelFd.getFd());
+                if (supportedLocalesStr.isEmpty()) {
+                    Log.d(DEFAULT_LOG_TAG, "Ignoring " + file.getAbsolutePath());
+                    return null;
+                }
+                final List<Locale> supportedLocales = new ArrayList<>();
+                for (String langTag : supportedLocalesStr.split(",")) {
+                    supportedLocales.add(Locale.forLanguageTag(langTag));
+                }
+                closeAndLogError(modelFd);
+                return new ModelFile(path, file.getName(), version, supportedLocales);
+            } catch (FileNotFoundException e) {
+                Log.e(DEFAULT_LOG_TAG, "Failed to peek " + file.getAbsolutePath(), e);
+                return null;
+            }
+        }
+
+        /** The absolute path to the model file. */
+        String getPath() {
+            return mPath;
+        }
+
+        /** A name to use for signature generation. Effectively the name of the model file. */
+        String getName() {
+            return mName;
+        }
+
+        /** Returns the version tag in the model's metadata. */
+        int getVersion() {
+            return mVersion;
+        }
+
+        /** Returns whether the language supports any language in the given ranges. */
+        boolean isAnyLanguageSupported(List<Locale.LanguageRange> languageRanges) {
+            return Locale.lookup(languageRanges, mSupportedLocales) != null;
+        }
+
+        /** All locales supported by the model. */
+        List<Locale> getSupportedLocales() {
+            return Collections.unmodifiableList(mSupportedLocales);
+        }
+
+        @Override
+        public boolean equals(Object other) {
+            if (this == other) {
+                return true;
+            } else if (other == null || !ModelFile.class.isAssignableFrom(other.getClass())) {
+                return false;
+            } else {
+                final ModelFile otherModel = (ModelFile) other;
+                return mPath.equals(otherModel.mPath);
+            }
+        }
+
+        @Override
+        public String toString() {
+            final StringJoiner localesJoiner = new StringJoiner(",");
+            for (Locale locale : mSupportedLocales) {
+                localesJoiner.add(locale.toLanguageTag());
+            }
+            return String.format(Locale.US, "ModelFile { path=%s name=%s version=%d locales=%s }",
+                    mPath, mName, mVersion, localesJoiner.toString());
+        }
+
+        private ModelFile(String path, String name, int version, List<Locale> supportedLocales) {
+            mPath = path;
+            mName = name;
+            mVersion = version;
+            mSupportedLocales = supportedLocales;
+        }
+    }
+
+    /**
      * Creates intents based on the classification type.
      */
     static final class IntentFactory {
@@ -541,7 +580,7 @@
                 case TextClassifier.TYPE_EMAIL:
                     return createForEmail(text);
                 case TextClassifier.TYPE_PHONE:
-                    return createForPhone(text);
+                    return createForPhone(context, text);
                 case TextClassifier.TYPE_ADDRESS:
                     return createForAddress(text);
                 case TextClassifier.TYPE_URL:
@@ -573,15 +612,23 @@
         }
 
         @NonNull
-        private static List<Intent> createForPhone(String text) {
-            return Arrays.asList(
-                    new Intent(Intent.ACTION_DIAL)
-                            .setData(Uri.parse(String.format("tel:%s", text))),
-                    new Intent(Intent.ACTION_INSERT_OR_EDIT)
-                            .setType(ContactsContract.Contacts.CONTENT_ITEM_TYPE)
-                            .putExtra(ContactsContract.Intents.Insert.PHONE, text),
-                    new Intent(Intent.ACTION_SENDTO)
-                            .setData(Uri.parse(String.format("smsto:%s", text))));
+        private static List<Intent> createForPhone(Context context, String text) {
+            final List<Intent> intents = new ArrayList<>();
+            final UserManager userManager = context.getSystemService(UserManager.class);
+            final Bundle userRestrictions = userManager != null
+                    ? userManager.getUserRestrictions() : new Bundle();
+            if (!userRestrictions.getBoolean(UserManager.DISALLOW_OUTGOING_CALLS, false)) {
+                intents.add(new Intent(Intent.ACTION_DIAL)
+                        .setData(Uri.parse(String.format("tel:%s", text))));
+            }
+            intents.add(new Intent(Intent.ACTION_INSERT_OR_EDIT)
+                    .setType(ContactsContract.Contacts.CONTENT_ITEM_TYPE)
+                    .putExtra(ContactsContract.Intents.Insert.PHONE, text));
+            if (!userRestrictions.getBoolean(UserManager.DISALLOW_SMS, false)) {
+                intents.add(new Intent(Intent.ACTION_SENDTO)
+                        .setData(Uri.parse(String.format("smsto:%s", text))));
+            }
+            return intents;
         }
 
         @NonNull
diff --git a/core/java/android/view/textclassifier/TextLinks.java b/core/java/android/view/textclassifier/TextLinks.java
index d866d13..3d252f2 100644
--- a/core/java/android/view/textclassifier/TextLinks.java
+++ b/core/java/android/view/textclassifier/TextLinks.java
@@ -108,6 +108,7 @@
      * @param text the text to apply the links to. Must match the original text
      * @param applyStrategy strategy for resolving link conflicts
      * @param spanFactory a factory to generate spans from TextLinks. Will use a default if null
+     * @param allowPrefix whether to allow applying links only to a prefix of the text.
      *
      * @return a status code indicating whether or not the links were successfully applied
      *
@@ -117,10 +118,12 @@
     public int apply(
             @NonNull Spannable text,
             @ApplyStrategy int applyStrategy,
-            @Nullable Function<TextLink, TextLinkSpan> spanFactory) {
+            @Nullable Function<TextLink, TextLinkSpan> spanFactory,
+            boolean allowPrefix) {
         Preconditions.checkNotNull(text);
         checkValidApplyStrategy(applyStrategy);
-        if (!mFullText.equals(text.toString())) {
+        final String textString = text.toString();
+        if (!mFullText.equals(textString) && !(allowPrefix && textString.startsWith(mFullText))) {
             return STATUS_DIFFERENT_TEXT;
         }
         if (mLinks.isEmpty()) {
diff --git a/core/java/android/view/textclassifier/logging/DefaultLogger.java b/core/java/android/view/textclassifier/logging/DefaultLogger.java
index 6b84835..f510879 100644
--- a/core/java/android/view/textclassifier/logging/DefaultLogger.java
+++ b/core/java/android/view/textclassifier/logging/DefaultLogger.java
@@ -17,7 +17,6 @@
 package android.view.textclassifier.logging;
 
 import android.annotation.NonNull;
-import android.annotation.Nullable;
 import android.content.Context;
 import android.metrics.LogMaker;
 import android.util.Log;
@@ -27,8 +26,10 @@
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.internal.util.Preconditions;
 
+import java.util.List;
 import java.util.Locale;
 import java.util.Objects;
+import java.util.StringJoiner;
 
 /**
  * Default Logger.
@@ -79,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())
@@ -136,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:
@@ -175,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;
 
@@ -192,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(
@@ -201,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));
     }
 
     /**
@@ -210,12 +235,16 @@
      */
     public static String createSignature(
             String text, int start, int end, Context context, int modelVersion,
-            @Nullable Locale locale) {
+            List<Locale> locales) {
         Preconditions.checkNotNull(text);
         Preconditions.checkNotNull(context);
-        final String modelName = (locale != null)
-                ? String.format(Locale.US, "%s_v%d", locale.toLanguageTag(), modelVersion)
-                : "";
+        Preconditions.checkNotNull(locales);
+        final StringJoiner localesJoiner = new StringJoiner(",");
+        for (Locale locale : locales) {
+            localesJoiner.add(locale.toLanguageTag());
+        }
+        final String modelName = String.format(Locale.US, "%s_v%d", localesJoiner.toString(),
+                modelVersion);
         final int hash = Objects.hash(text, start, end, context.getPackageName());
         return SignatureParser.createSignature(CLASSIFIER_ID, modelName, hash);
     }
@@ -242,9 +271,9 @@
 
         static String getModelName(String signature) {
             Preconditions.checkNotNull(signature);
-            final int start = signature.indexOf("|");
+            final int start = signature.indexOf("|") + 1;
             final int end = signature.indexOf("|", start);
-            if (start >= 0 && end >= start) {
+            if (start >= 1 && end >= start) {
                 return signature.substring(start, end);
             }
             return "";
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/webkit/TracingConfig.java b/core/java/android/webkit/TracingConfig.java
index 75e2bf7..68badec 100644
--- a/core/java/android/webkit/TracingConfig.java
+++ b/core/java/android/webkit/TracingConfig.java
@@ -21,61 +21,76 @@
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
 
 /**
  * Holds tracing configuration information and predefined settings.
  */
 public class TracingConfig {
 
-    private final String mCustomCategoryPattern;
-    private final @PresetCategories int mPresetCategories;
+    private @PredefinedCategories int mPredefinedCategories;
+    private final List<String> mCustomIncludedCategories = new ArrayList<String>();
     private @TracingMode int mTracingMode;
 
     /** @hide */
-    @IntDef({CATEGORIES_NONE, CATEGORIES_WEB_DEVELOPER, CATEGORIES_INPUT_LATENCY,
-            CATEGORIES_RENDERING, CATEGORIES_JAVASCRIPT_AND_RENDERING, CATEGORIES_FRAME_VIEWER})
+    @IntDef(flag = true, value = {CATEGORIES_NONE, CATEGORIES_WEB_DEVELOPER,
+            CATEGORIES_INPUT_LATENCY, CATEGORIES_RENDERING, CATEGORIES_JAVASCRIPT_AND_RENDERING,
+            CATEGORIES_FRAME_VIEWER})
     @Retention(RetentionPolicy.SOURCE)
-    public @interface PresetCategories {}
+    public @interface PredefinedCategories {}
 
     /**
-     * Indicates that there are no preset categories.
+     * Indicates that there are no predefined categories.
      */
-    public static final int CATEGORIES_NONE = -1;
+    public static final int CATEGORIES_NONE = 0;
 
     /**
-     * Predefined categories typically useful for web developers.
+     * Predefined set of categories, includes all categories enabled by default in chromium.
+     * Use with caution: this setting may produce large trace output.
+     */
+    public static final int CATEGORIES_ALL = 1 << 0;
+
+    /**
+     * Predefined set of categories typically useful for analyzing WebViews.
+     * Typically includes android_webview and Java.
+     */
+    public static final int CATEGORIES_ANDROID_WEBVIEW = 1 << 1;
+
+    /**
+     * Predefined set of categories typically useful for web developers.
      * Typically includes blink, compositor, renderer.scheduler and v8 categories.
      */
-    public static final int CATEGORIES_WEB_DEVELOPER = 0;
+    public static final int CATEGORIES_WEB_DEVELOPER = 1 << 2;
 
     /**
-     * Predefined categories for analyzing input latency issues.
+     * Predefined set of categories for analyzing input latency issues.
      * Typically includes input, renderer.scheduler categories.
      */
-    public static final int CATEGORIES_INPUT_LATENCY = 1;
+    public static final int CATEGORIES_INPUT_LATENCY = 1 << 3;
 
     /**
-     * Predefined categories for analyzing rendering issues.
+     * Predefined set of categories for analyzing rendering issues.
      * Typically includes blink, compositor and gpu categories.
      */
-    public static final int CATEGORIES_RENDERING = 2;
+    public static final int CATEGORIES_RENDERING = 1 << 4;
 
     /**
-     * Predefined categories for analyzing javascript and rendering issues.
-     * Typically includes blink, compositor, gpu, renderer.schduler and v8 categories.
+     * Predefined set of categories for analyzing javascript and rendering issues.
+     * Typically includes blink, compositor, gpu, renderer.scheduler and v8 categories.
      */
-    public static final int CATEGORIES_JAVASCRIPT_AND_RENDERING = 3;
+    public static final int CATEGORIES_JAVASCRIPT_AND_RENDERING = 1 << 5;
 
     /**
-     * Predefined categories for studying difficult rendering performance problems.
+     * Predefined set of categories for studying difficult rendering performance problems.
      * Typically includes blink, compositor, gpu, renderer.scheduler, v8 and
      * some other compositor categories which are disabled by default.
      */
-    public static final int CATEGORIES_FRAME_VIEWER = 4;
+    public static final int CATEGORIES_FRAME_VIEWER = 1 << 6;
 
     /** @hide */
-    @IntDef({RECORD_UNTIL_FULL, RECORD_CONTINUOUSLY, RECORD_UNTIL_FULL_LARGE_BUFFER,
-            RECORD_TO_CONSOLE})
+    @IntDef({RECORD_UNTIL_FULL, RECORD_CONTINUOUSLY, RECORD_UNTIL_FULL_LARGE_BUFFER})
     @Retention(RetentionPolicy.SOURCE)
     public @interface TracingMode {}
 
@@ -97,99 +112,38 @@
 
     /**
      * Record trace events using a larger internal tracing buffer until it is full.
-     * Uses more memory than the other modes and may not be suitable on devices
-     * with smaller RAM. Depending on the implementation typically allows up to
-     * 512 million events to be stored.
+     * Uses significantly more memory than {@link #RECORD_UNTIL_FULL} and may not be
+     * suitable on devices with smaller RAM.
      */
     public static final int RECORD_UNTIL_FULL_LARGE_BUFFER = 2;
 
     /**
-     * Record trace events to console (logcat). The events are discarded and nothing
-     * is sent back to the caller. Uses the least memory as compared to the other modes.
+     * @hide
      */
-    public static final int RECORD_TO_CONSOLE = 3;
-
-    /**
-     * Create config with the preset categories.
-     * <p>
-     * Example:
-     *    TracingConfig(CATEGORIES_WEB_DEVELOPER) -- records trace events from the "web developer"
-     *                                               preset categories.
-     *
-     * @param presetCategories preset categories to use, one of {@link #CATEGORIES_WEB_DEVELOPER},
-     *                    {@link #CATEGORIES_INPUT_LATENCY}, {@link #CATEGORIES_RENDERING},
-     *                    {@link #CATEGORIES_JAVASCRIPT_AND_RENDERING} or
-     *                    {@link #CATEGORIES_FRAME_VIEWER}.
-     *
-     * Note: for specifying custom categories without presets use
-     * {@link #TracingConfig(int, String, int)}.
-     *
-     */
-    public TracingConfig(@PresetCategories int presetCategories) {
-        this(presetCategories, "", RECORD_UNTIL_FULL);
+    public TracingConfig(@PredefinedCategories int predefinedCategories,
+            @NonNull List<String> customIncludedCategories,
+            @TracingMode int tracingMode) {
+        mPredefinedCategories = predefinedCategories;
+        mCustomIncludedCategories.addAll(customIncludedCategories);
+        mTracingMode = tracingMode;
     }
 
     /**
-     * Create a configuration with both preset categories and custom categories.
-     * Also allows to specify the tracing mode.
-     *
-     * Note that the categories are defined by the currently-in-use version of WebView. They live
-     * in chromium code and are not part of the Android API. See
-     * See <a href="https://www.chromium.org/developers/how-tos/trace-event-profiling-tool">
-     * chromium documentation on tracing</a> for more details.
-     *
-     * <p>
-     * Examples:
-     *
-     *  Preset category with a specified trace mode:
-     *    TracingConfig(CATEGORIES_WEB_DEVELOPER, "", RECORD_UNTIL_FULL_LARGE_BUFFER);
-     *  Custom categories:
-     *    TracingConfig(CATEGORIES_NONE, "browser", RECORD_UNTIL_FULL)
-     *      -- records only the trace events from the "browser" category.
-     *    TraceConfig(CATEGORIES_NONE, "-input,-gpu", RECORD_UNTIL_FULL)
-     *      -- records all trace events excluding the events from the "input" and 'gpu' categories.
-     *    TracingConfig(CATEGORIES_NONE, "blink*,devtools*", RECORD_UNTIL_FULL)
-     *      -- records only the trace events matching the "blink*" and "devtools*" patterns
-     *         (e.g. "blink_gc" and "devtools.timeline" categories).
-     *
-     *  Combination of preset and additional custom categories:
-     *    TracingConfig(CATEGORIES_WEB_DEVELOPER, "memory-infra", RECORD_CONTINUOUSLY)
-     *      -- records events from the "web developer" categories and events from the "memory-infra"
-     *         category to understand where memory is being used.
-     *
-     * @param presetCategories preset categories to use, one of {@link #CATEGORIES_WEB_DEVELOPER},
-     *                    {@link #CATEGORIES_INPUT_LATENCY}, {@link #CATEGORIES_RENDERING},
-     *                    {@link #CATEGORIES_JAVASCRIPT_AND_RENDERING} or
-     *                    {@link #CATEGORIES_FRAME_VIEWER}.
-     * @param customCategories a comma-delimited list of category wildcards. A category can
-     *                         have an optional '-' prefix to make it an excluded category.
-     * @param tracingMode tracing mode to use, one of {@link #RECORD_UNTIL_FULL},
-     *                    {@link #RECORD_CONTINUOUSLY}, {@link #RECORD_UNTIL_FULL_LARGE_BUFFER}
-     *                    or {@link #RECORD_TO_CONSOLE}.
+     * Returns a bitmask of the predefined categories values of this configuration.
      */
-    public TracingConfig(@PresetCategories int presetCategories,
-            @NonNull String customCategories, @TracingMode int tracingMode) {
-        mPresetCategories = presetCategories;
-        mCustomCategoryPattern = customCategories;
-        mTracingMode = RECORD_UNTIL_FULL;
+    @PredefinedCategories
+    public int getPredefinedCategories() {
+        return mPredefinedCategories;
     }
 
     /**
-     * Returns the custom category pattern for this configuration.
+     * Returns the list of included custom category patterns for this configuration.
      *
-     * @return empty string if no custom category pattern is specified.
+     * @return empty list if no custom category patterns are specified.
      */
     @NonNull
-    public String getCustomCategoryPattern() {
-        return mCustomCategoryPattern;
-    }
-
-    /**
-     * Returns the preset categories value of this configuration.
-     */
-    @PresetCategories
-    public int getPresetCategories() {
-        return mPresetCategories;
+    public List<String> getCustomIncludedCategories() {
+        return mCustomIncludedCategories;
     }
 
     /**
@@ -200,4 +154,111 @@
         return mTracingMode;
     }
 
+    /**
+     * Builder used to create {@link TracingConfig} objects.
+     *
+     * Examples:
+     *   new TracingConfig.Builder().build()
+     *       -- creates a configuration with default options: {@link #CATEGORIES_NONE},
+     *          {@link #RECORD_UNTIL_FULL}.
+     *   new TracingConfig.Builder().addCategories(CATEGORIES_WEB_DEVELOPER).build()
+     *       -- records trace events from the "web developer" predefined category sets.
+     *   new TracingConfig.Builder().addCategories(CATEGORIES_RENDERING,
+     *                                             CATEGORIES_INPUT_LATENCY).build()
+     *       -- records trace events from the "rendering" and "input latency" predefined
+     *          category sets.
+     *   new TracingConfig.Builder().addCategories("browser").build()
+     *       -- records only the trace events from the "browser" category.
+     *   new TracingConfig.Builder().addCategories("blink*","renderer*").build()
+     *       -- records only the trace events matching the "blink*" and "renderer*" patterns
+     *          (e.g. "blink.animations", "renderer_host" and "renderer.scheduler" categories).
+     *   new TracingConfig.Builder().addCategories(CATEGORIES_WEB_DEVELOPER)
+     *                              .addCategories("disabled-by-default-v8.gc")
+     *                              .setTracingMode(RECORD_CONTINUOUSLY).build()
+     *       -- records events from the "web developer" predefined category set and events from
+     *          the "disabled-by-default-v8.gc" category to understand where garbage collection
+     *          is being triggered. Uses a ring buffer for internal storage during tracing.
+     */
+    public static class Builder {
+        private @PredefinedCategories int mPredefinedCategories = CATEGORIES_NONE;
+        private final List<String> mCustomIncludedCategories = new ArrayList<String>();
+        private @TracingMode int mTracingMode = RECORD_UNTIL_FULL;
+
+        /**
+         * Default constructor for Builder.
+         */
+        public Builder() {}
+
+        /**
+         * Build {@link TracingConfig} using the current settings.
+         */
+        public TracingConfig build() {
+            return new TracingConfig(mPredefinedCategories, mCustomIncludedCategories,
+                    mTracingMode);
+        }
+
+        /**
+         * Adds categories from a predefined set of categories to be included in the trace output.
+         *
+         * @param predefinedCategories list or bitmask of predefined category sets to use:
+         *                    {@link #CATEGORIES_NONE}, {@link #CATEGORIES_ALL},
+         *                    {@link #CATEGORIES_WEB_DEVELOPER}, {@link #CATEGORIES_INPUT_LATENCY},
+         *                    {@link #CATEGORIES_RENDERING},
+         *                    {@link #CATEGORIES_JAVASCRIPT_AND_RENDERING} or
+         *                    {@link #CATEGORIES_FRAME_VIEWER}.
+         * @return The builder to facilitate chaining.
+         */
+        public Builder addCategories(@PredefinedCategories int... predefinedCategories) {
+            for (int categorySet : predefinedCategories) {
+                mPredefinedCategories |= categorySet;
+            }
+            return this;
+        }
+
+        /**
+         * Adds custom categories to be included in trace output.
+         *
+         * Note that the categories are defined by the currently-in-use version of WebView. They
+         * live in chromium code and are not part of the Android API. See
+         * See <a href="https://www.chromium.org/developers/how-tos/trace-event-profiling-tool">
+         * chromium documentation on tracing</a> for more details.
+         *
+         * @param categories a list of category patterns. A category pattern can contain wilcards,
+         *        e.g. "blink*" or full category name e.g. "renderer.scheduler".
+         * @return The builder to facilitate chaining.
+         */
+        public Builder addCategories(String... categories) {
+            for (String category: categories) {
+                mCustomIncludedCategories.add(category);
+            }
+            return this;
+        }
+
+        /**
+         * Adds custom categories to be included in trace output.
+         *
+         * Same as {@link #addCategories(String...)} but allows to pass a Collection as a parameter.
+         *
+         * @param categories a list of category patters.
+         * @return The builder to facilitate chaining.
+         */
+        public Builder addCategories(Collection<String> categories) {
+            mCustomIncludedCategories.addAll(categories);
+            return this;
+        }
+
+        /**
+         * Sets the tracing mode for this configuration.
+         *
+         * @param tracingMode tracing mode to use, one of {@link #RECORD_UNTIL_FULL},
+         *                    {@link #RECORD_CONTINUOUSLY} or
+         *                    {@link #RECORD_UNTIL_FULL_LARGE_BUFFER}.
+         * @return The builder to facilitate chaining.
+         */
+        public Builder setTracingMode(@TracingMode int tracingMode) {
+            mTracingMode = tracingMode;
+            return this;
+        }
+    }
+
 }
diff --git a/core/java/android/webkit/TracingController.java b/core/java/android/webkit/TracingController.java
index cadb8a1..7871021 100644
--- a/core/java/android/webkit/TracingController.java
+++ b/core/java/android/webkit/TracingController.java
@@ -16,9 +16,12 @@
 
 package android.webkit;
 
+import android.annotation.CallbackExecutor;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.os.Handler;
+
+import java.io.OutputStream;
+import java.util.concurrent.Executor;
 
 /**
  * Manages tracing of WebViews. In particular provides functionality for the app
@@ -29,40 +32,22 @@
  * The resulting trace data is sent back as a byte sequence in json format. This
  * file can be loaded in "chrome://tracing" for further analysis.
  * <p>
- * Note: All methods in this class must be called on the UI thread. All callbacks
- * are also called on the UI thread.
- * <p>
  * Example usage:
  * <pre class="prettyprint">
  * TracingController tracingController = TracingController.getInstance();
- * tracingController.start(new TraceConfig(CATEGORIES_WEB_DEVELOPER));
+ * tracingController.start(new TraceConfig.Builder()
+ *                  .addCategories(CATEGORIES_WEB_DEVELOPER).build());
  * [..]
- * tracingController.stopAndFlush(new TraceFileOutput("trace.json"), null);
+ * tracingController.stop(new FileOutputStream("trace.json"),
+ *                        Executors.newSingleThreadExecutor());
  * </pre></p>
  */
 public abstract class TracingController {
 
     /**
-     * Interface for capturing tracing data.
-     */
-    public interface TracingOutputStream {
-        /**
-         * Will be called to return tracing data in chunks.
-         * Tracing data is returned in json format an array of bytes.
-         */
-        void write(byte[] chunk);
-
-        /**
-         * Called when tracing is finished and the data collection is over.
-         * There will be no calls to #write after #complete is called.
-         */
-        void complete();
-    }
-
-    /**
      * Returns the default TracingController instance. At present there is
      * only one TracingController instance for all WebView instances,
-     * however this restriction may be relaxed in the future.
+     * however this restriction may be relaxed in a future Android release.
      *
      * @return the default TracingController instance
      */
@@ -72,55 +57,38 @@
     }
 
     /**
-     * Starts tracing all webviews. Depeding on the trace mode in traceConfig
+     * Starts tracing all webviews. Depending on the trace mode in traceConfig
      * specifies how the trace events are recorded.
      *
      * For tracing modes {@link TracingConfig#RECORD_UNTIL_FULL},
      * {@link TracingConfig#RECORD_CONTINUOUSLY} and
      * {@link TracingConfig#RECORD_UNTIL_FULL_LARGE_BUFFER} the events are recorded
      * using an internal buffer and flushed to the outputStream when
-     * {@link #stopAndFlush(TracingOutputStream, Handler)} is called.
+     * {@link #stop(OutputStream, Executor)} is called.
      *
      * @param tracingConfig configuration options to use for tracing
-     * @return false if the system is already tracing, true otherwise.
+     * @throws IllegalStateException if the system is already tracing.
      */
-    public abstract boolean start(TracingConfig tracingConfig);
+    public abstract void start(@NonNull TracingConfig tracingConfig);
 
     /**
-     * Stops tracing and discards all tracing data.
+     * Stops tracing and flushes tracing data to the specified outputStream.
      *
-     * This method is particularly useful in conjunction with the
-     * {@link TracingConfig#RECORD_TO_CONSOLE} tracing mode because tracing data is logged to
-     * console and not sent to an outputStream as with
-     * {@link #stopAndFlush(TracingOutputStream, Handler)}.
+     * The data is sent to the specified output stream in json format typically
+     * in chunks by invoking {@link java.io.OutputStream#write(byte[])}. On completion
+     * the {@link java.io.OutputStream#close()} method is called.
      *
+     * @param outputStream the output steam the tracing data will be sent to. If null
+     *                     the tracing data will be discarded.
+     * @param executor the {@link java.util.concurrent.Executor} on which the
+     *        outputStream #write and #close methods will be invoked.
      * @return false if the system was not tracing at the time of the call, true
      *         otherwise.
      */
-    public abstract boolean stop();
-
-    /**
-     * Stops tracing and flushes tracing data to the specifid outputStream.
-     *
-     * Note that if the {@link TracingConfig#RECORD_TO_CONSOLE} tracing mode is used
-     * nothing will be sent to the outputStream and no TracingOuputStream methods will be
-     * called. In that case it is more convenient to just use {@link #stop()} instead.
-     *
-     * @param outputStream the output steam the tracing data will be sent to.
-     * @param handler the {@link android.os.Handler} on which the outputStream callbacks
-     *                will be invoked. If the handler is null the current thread's Looper
-     *                will be used.
-     * @return false if the system was not tracing at the time of the call, true
-     *         otherwise.
-     */
-    public abstract boolean stopAndFlush(TracingOutputStream outputStream,
-            @Nullable Handler handler);
+    public abstract boolean stop(@Nullable OutputStream outputStream,
+            @NonNull @CallbackExecutor Executor executor);
 
     /** True if the system is tracing */
     public abstract boolean isTracing();
 
-    // TODO: consider adding getTraceBufferUsage, percentage and approx event count.
-    // TODO: consider adding String getCategories(), for obtaining the actual list
-    // of categories used (given that presets are ints).
-
 }
diff --git a/core/java/android/webkit/TracingFileOutputStream.java b/core/java/android/webkit/TracingFileOutputStream.java
deleted file mode 100644
index 8a5fa36..0000000
--- a/core/java/android/webkit/TracingFileOutputStream.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright 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.webkit;
-
-import android.annotation.NonNull;
-
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-
-/**
- * Simple TracingOutputStream implementation which writes the trace data from
- * {@link TracingController} to a new file.
- *
- */
-public class TracingFileOutputStream implements TracingController.TracingOutputStream {
-
-    private FileOutputStream mFileOutput;
-
-    public TracingFileOutputStream(@NonNull String filename) throws FileNotFoundException {
-        mFileOutput = new FileOutputStream(filename);
-    }
-
-    /**
-     * Writes bytes chunk to the file.
-     */
-    public void write(byte[] chunk) {
-        try {
-            mFileOutput.write(chunk);
-        } catch (IOException e) {
-            onIOException(e);
-        }
-    }
-
-    /**
-     * Closes the file.
-     */
-    public void complete() {
-        try {
-            mFileOutput.close();
-        } catch (IOException e) {
-            onIOException(e);
-        }
-    }
-
-    private void onIOException(IOException e) {
-        throw new RuntimeException(e);
-    }
-}
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 5ab579d..9988661 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -1299,6 +1299,16 @@
             if (mSelectionModifierCursorController != null) {
                 mSelectionModifierCursorController.resetTouchOffsets();
             }
+
+            ensureNoSelectionIfNonSelectable();
+        }
+    }
+
+    private void ensureNoSelectionIfNonSelectable() {
+        // This could be the case if a TextLink has been tapped.
+        if (!mTextView.textCanBeSelected() && mTextView.hasSelection()) {
+            Selection.setSelection((Spannable) mTextView.getText(),
+                    mTextView.length(), mTextView.length());
         }
     }
 
@@ -1382,6 +1392,8 @@
 
             // Don't leave us in the middle of a batch edit. Same as in onFocusChanged
             ensureEndedBatchEdit();
+
+            ensureNoSelectionIfNonSelectable();
         }
     }
 
@@ -4174,7 +4186,7 @@
                         primaryHorizontal,
                         layout.getLineTop(line),
                         primaryHorizontal,
-                        layout.getLineBottom(line) - layout.getLineBottom(line) + mHandleHeight);
+                        layout.getLineBottom(line) + mHandleHeight);
             }
             // Take TextView's padding and scroll into account.
             int textHorizontalOffset = mTextView.viewportToContentHorizontalOffset();
diff --git a/core/java/android/widget/GridLayout.java b/core/java/android/widget/GridLayout.java
index 012b918..3aae849 100644
--- a/core/java/android/widget/GridLayout.java
+++ b/core/java/android/widget/GridLayout.java
@@ -904,6 +904,9 @@
         }
     }
 
+    /**
+     * @hide
+     */
     @Override
     protected void onDebugDrawMargins(Canvas canvas, Paint paint) {
         // Apply defaults, so as to remove UNDEFINED values
@@ -919,6 +922,9 @@
         }
     }
 
+    /**
+     * @hide
+     */
     @Override
     protected void onDebugDraw(Canvas canvas) {
         Paint paint = new Paint();
diff --git a/core/java/android/widget/LinearLayout.java b/core/java/android/widget/LinearLayout.java
index 7ea1f1e..d32e93c 100644
--- a/core/java/android/widget/LinearLayout.java
+++ b/core/java/android/widget/LinearLayout.java
@@ -917,7 +917,7 @@
         // measurement on any children, we need to measure them now.
         int remainingExcess = heightSize - mTotalLength
                 + (mAllowInconsistentMeasurement ? 0 : consumedExcessSpace);
-        if (skippedMeasure || remainingExcess != 0 && totalWeight > 0.0f) {
+        if (skippedMeasure || totalWeight > 0.0f) {
             float remainingWeightSum = mWeightSum > 0.0f ? mWeightSum : totalWeight;
 
             mTotalLength = 0;
@@ -1300,7 +1300,7 @@
         // measurement on any children, we need to measure them now.
         int remainingExcess = widthSize - mTotalLength
                 + (mAllowInconsistentMeasurement ? 0 : usedExcessSpace);
-        if (skippedMeasure || remainingExcess != 0 && totalWeight > 0.0f) {
+        if (skippedMeasure || totalWeight > 0.0f) {
             float remainingWeightSum = mWeightSum > 0.0f ? mWeightSum : totalWeight;
 
             maxAscent[0] = maxAscent[1] = maxAscent[2] = maxAscent[3] = -1;
diff --git a/core/java/android/widget/Magnifier.java b/core/java/android/widget/Magnifier.java
index 7a4c800..8836561 100644
--- a/core/java/android/widget/Magnifier.java
+++ b/core/java/android/widget/Magnifier.java
@@ -18,8 +18,10 @@
 
 import android.annotation.FloatRange;
 import android.annotation.NonNull;
+import android.annotation.TestApi;
 import android.annotation.UiThread;
 import android.content.Context;
+import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.Point;
 import android.graphics.PointF;
@@ -269,4 +271,46 @@
         return mWindow.getContentView().findViewById(
                 com.android.internal.R.id.magnifier_image);
     }
+
+    /**
+     * @return the content being currently displayed in the magnifier, as bitmap
+     *
+     * @hide
+     */
+    @TestApi
+    public Bitmap getContent() {
+        return mBitmap;
+    }
+
+    /**
+     * @return the position of the magnifier window relative to the screen
+     *
+     * @hide
+     */
+    @TestApi
+    public Rect getWindowPositionOnScreen() {
+        final int[] viewLocationOnScreen = new int[2];
+        mView.getLocationOnScreen(viewLocationOnScreen);
+        final int[] viewLocationInSurface = new int[2];
+        mView.getLocationInSurface(viewLocationInSurface);
+
+        final int left = mWindowCoords.x + viewLocationOnScreen[0] - viewLocationInSurface[0];
+        final int top = mWindowCoords.y + viewLocationOnScreen[1] - viewLocationInSurface[1];
+        return new Rect(left, top, left + mWindow.getWidth(), top + mWindow.getHeight());
+    }
+
+    /**
+     * @return the size of the magnifier window in dp
+     *
+     * @hide
+     */
+    @TestApi
+    public static PointF getMagnifierDefaultSize() {
+        final Resources resources = Resources.getSystem();
+        final float density = resources.getDisplayMetrics().density;
+        final PointF size = new PointF();
+        size.x = resources.getDimension(com.android.internal.R.dimen.magnifier_width) / density;
+        size.y = resources.getDimension(com.android.internal.R.dimen.magnifier_height) / density;
+        return size;
+    }
 }
diff --git a/core/java/android/widget/OWNERS b/core/java/android/widget/OWNERS
index 8f0d02f..e4b2930 100644
--- a/core/java/android/widget/OWNERS
+++ b/core/java/android/widget/OWNERS
@@ -1,12 +1,11 @@
 per-file TextView.java = siyamed@google.com
 per-file TextView.java = nona@google.com
 per-file TextView.java = clarabayarri@google.com
-per-file TextView.java = toki@google.com
+
 per-file EditText.java = siyamed@google.com
 per-file EditText.java = nona@google.com
 per-file EditText.java = clarabayarri@google.com
-per-file EditText.java = toki@google.com
+
 per-file Editor.java = siyamed@google.com
 per-file Editor.java = nona@google.com
 per-file Editor.java = clarabayarri@google.com
-per-file Editor.java = toki@google.com
diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java
index e91db13..7217def 100644
--- a/core/java/android/widget/PopupWindow.java
+++ b/core/java/android/widget/PopupWindow.java
@@ -1583,7 +1583,7 @@
      *
      * @hide
      */
-    protected final boolean findDropDownPosition(View anchor, WindowManager.LayoutParams outParams,
+    protected boolean findDropDownPosition(View anchor, WindowManager.LayoutParams outParams,
             int xOffset, int yOffset, int width, int height, int gravity, boolean allowScroll) {
         final int anchorHeight = anchor.getHeight();
         final int anchorWidth = anchor.getWidth();
diff --git a/core/java/android/widget/RadioGroup.java b/core/java/android/widget/RadioGroup.java
index 5c4d4d2..c987147 100644
--- a/core/java/android/widget/RadioGroup.java
+++ b/core/java/android/widget/RadioGroup.java
@@ -183,13 +183,17 @@
     }
 
     private void setCheckedId(@IdRes int id) {
+        boolean changed = id != mCheckedId;
         mCheckedId = id;
+
         if (mOnCheckedChangeListener != null) {
             mOnCheckedChangeListener.onCheckedChanged(this, mCheckedId);
         }
-        final AutofillManager afm = mContext.getSystemService(AutofillManager.class);
-        if (afm != null) {
-            afm.notifyValueChanged(this);
+        if (changed) {
+            final AutofillManager afm = mContext.getSystemService(AutofillManager.class);
+            if (afm != null) {
+                afm.notifyValueChanged(this);
+            }
         }
     }
 
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/TextInputTimePickerView.java b/core/java/android/widget/TextInputTimePickerView.java
index 0cf8faa..e0261ad 100644
--- a/core/java/android/widget/TextInputTimePickerView.java
+++ b/core/java/android/widget/TextInputTimePickerView.java
@@ -174,7 +174,8 @@
      */
     void updateTextInputValues(int localizedHour, int minute, int amOrPm, boolean is24Hour,
             boolean hourFormatStartsAtZero) {
-        final String format = "%d";
+        final String hourFormat = "%d";
+        final String minuteFormat = "%02d";
 
         mIs24Hour = is24Hour;
         mHourFormatStartsAtZero = hourFormatStartsAtZero;
@@ -187,8 +188,8 @@
             mAmPmSpinner.setSelection(1);
         }
 
-        mHourEditText.setText(String.format(format, localizedHour));
-        mMinuteEditText.setText(String.format(format, minute));
+        mHourEditText.setText(String.format(hourFormat, localizedHour));
+        mMinuteEditText.setText(String.format(minuteFormat, minute));
 
         if (mErrorShowing) {
             validateInput();
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 5710db3..1e02c30 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -791,11 +791,18 @@
     // mAutoSizeStepGranularityInPx.
     private boolean mHasPresetAutoSizeValues = false;
 
+    // Autofill-related attributes
+    //
     // Indicates whether the text was set statically or dynamically, so it can be used to
     // sanitize autofill requests.
     private boolean mTextSetFromXmlOrResourceId = false;
-    // Resource id used to set the text - used for autofill purposes.
+    // Resource id used to set the text.
     private @StringRes int mTextId = ResourceId.ID_NULL;
+    // Last value used on AFM.notifyValueChanged(), used to optimize autofill workflow by avoiding
+    // calls when the value did not change
+    private CharSequence mLastValueSentToAutofillManager;
+    //
+    // End of autofill-related attributes
 
     /**
      * Kick-start the font cache for the zygote process (to pay the cost of
@@ -5665,7 +5672,6 @@
         if (needEditableForNotification) {
             sendAfterTextChanged((Editable) text);
         } else {
-            // Always notify AutoFillManager - it will return right away if autofill is disabled.
             notifyAutoFillManagerAfterTextChangedIfNeeded();
         }
 
@@ -9697,11 +9703,21 @@
             return;
         }
         final AutofillManager afm = mContext.getSystemService(AutofillManager.class);
-        if (afm != null) {
+        if (afm == null) {
+            return;
+        }
+
+        if (mLastValueSentToAutofillManager == null
+                || !mLastValueSentToAutofillManager.equals(mText)) {
             if (android.view.autofill.Helper.sVerbose) {
-                Log.v(LOG_TAG, "sendAfterTextChanged(): notify AFM for text=" + mText);
+                Log.v(LOG_TAG, "notifying AFM after text changed");
             }
             afm.notifyValueChanged(TextView.this);
+            mLastValueSentToAutofillManager = mText;
+        } else {
+            if (android.view.autofill.Helper.sVerbose) {
+                Log.v(LOG_TAG, "not notifying AFM on unchanged text");
+            }
         }
     }
 
diff --git a/core/java/com/android/internal/app/PlatLogoActivity.java b/core/java/com/android/internal/app/PlatLogoActivity.java
index b22ce5e..f6a69d9 100644
--- a/core/java/com/android/internal/app/PlatLogoActivity.java
+++ b/core/java/com/android/internal/app/PlatLogoActivity.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010 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.
@@ -16,157 +16,214 @@
 
 package com.android.internal.app;
 
-import android.animation.Animator;
-import android.animation.ObjectAnimator;
-import android.annotation.Nullable;
+import android.animation.TimeAnimator;
 import android.app.Activity;
-import android.content.ActivityNotFoundException;
-import android.content.ContentResolver;
-import android.content.Intent;
-import android.content.res.ColorStateList;
 import android.graphics.Canvas;
 import android.graphics.Color;
 import android.graphics.ColorFilter;
-import android.graphics.Outline;
 import android.graphics.Paint;
 import android.graphics.Path;
-import android.graphics.PixelFormat;
-import android.graphics.PorterDuff;
-import android.graphics.PorterDuffColorFilter;
 import android.graphics.drawable.Drawable;
-import android.graphics.drawable.GradientDrawable;
-import android.graphics.drawable.RippleDrawable;
-import android.graphics.drawable.ShapeDrawable;
-import android.graphics.drawable.shapes.OvalShape;
 import android.os.Bundle;
-import android.provider.Settings;
-import android.util.DisplayMetrics;
 import android.util.Log;
-import android.util.MathUtils;
-import android.view.Gravity;
-import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.view.MotionEvent.PointerCoords;
 import android.view.View;
-import android.view.ViewGroup;
-import android.view.ViewOutlineProvider;
-import android.view.animation.PathInterpolator;
 import android.widget.FrameLayout;
-import android.widget.ImageView;
 
 public class PlatLogoActivity extends Activity {
-    public static final boolean FINISH = true;
+    FrameLayout layout;
+    TimeAnimator anim;
+    PBackground bg;
 
-    FrameLayout mLayout;
-    int mTapCount;
-    int mKeyCount;
-    PathInterpolator mInterpolator = new PathInterpolator(0f, 0f, 0.5f, 1f);
+    private class PBackground extends Drawable {
+        private float maxRadius, radius, x, y, dp;
+        private int[] palette;
+        private int darkest;
+        private float offset;
+
+        public PBackground() {
+            randomizePalette();
+        }
+
+        /**
+         * set inner radius of "p" logo
+         */
+        public void setRadius(float r) {
+            this.radius = Math.max(48*dp, r);
+        }
+
+        /**
+         * move the "p"
+         */
+        public void setPosition(float x, float y) {
+            this.x = x;
+            this.y = y;
+        }
+
+        /**
+         * for animating the "p"
+         */
+        public void setOffset(float o) {
+            this.offset = o;
+        }
+
+        /**
+         * rough luminance calculation
+         * https://www.w3.org/TR/AERT/#color-contrast
+         */
+        public float lum(int rgb) {
+            return ((Color.red(rgb) * 299f) + (Color.green(rgb) * 587f) + (Color.blue(rgb) * 114f)) / 1000f;
+        }
+
+        /**
+         * create a random evenly-spaced color palette
+         * guaranteed to contrast!
+         */
+        public void randomizePalette() {
+            final int slots = 2 + (int)(Math.random() * 2);
+            float[] color = new float[] { (float) Math.random() * 360f, 1f, 1f };
+            palette = new int[slots];
+            darkest = 0;
+            for (int i=0; i<slots; i++) {
+                palette[i] = Color.HSVToColor(color);
+                color[0] += 360f/slots;
+                if (lum(palette[i]) < lum(palette[darkest])) darkest = i;
+            }
+
+            final StringBuilder str = new StringBuilder();
+            for (int c : palette) {
+                str.append(String.format("#%08x ", c));
+            }
+            Log.v("PlatLogoActivity", "color palette: " + str);
+        }
+
+        @Override
+        public void draw(Canvas canvas) {
+            if (dp == 0) dp = getResources().getDisplayMetrics().density;
+            final float width = canvas.getWidth();
+            final float height = canvas.getHeight();
+            if (radius == 0) {
+                setPosition(width / 2, height / 2);
+                setRadius(width / 6);
+            }
+            final float inner_w = radius * 0.667f;
+
+            final Paint paint = new Paint();
+            paint.setStrokeCap(Paint.Cap.BUTT);
+            canvas.translate(x, y);
+
+            Path p = new Path();
+            p.moveTo(-radius, height);
+            p.lineTo(-radius, 0);
+            p.arcTo(-radius, -radius, radius, radius, -180, 270, false);
+            p.lineTo(-radius, radius);
+
+            float w = Math.max(canvas.getWidth(), canvas.getHeight())  * 1.414f;
+            paint.setStyle(Paint.Style.FILL);
+
+            int i=0;
+            while (w > radius*2 + inner_w*2) {
+                paint.setColor(0xFF000000 | palette[i % palette.length]);
+                // for a slower but more complete version:
+                // paint.setStrokeWidth(w);
+                // canvas.drawPath(p, paint);
+                canvas.drawOval(-w/2, -w/2, w/2, w/2, paint);
+                w -= inner_w * (1.1f + Math.sin((i/20f + offset) * 3.14159f));
+                i++;
+            }
+
+            // the innermost circle needs to be a constant color to avoid rapid flashing
+            paint.setColor(0xFF000000 | palette[(darkest+1) % palette.length]);
+            canvas.drawOval(-radius, -radius, radius, radius, paint);
+
+            p.reset();
+            p.moveTo(-radius, height);
+            p.lineTo(-radius, 0);
+            p.arcTo(-radius, -radius, radius, radius, -180, 270, false);
+            p.lineTo(-radius + inner_w, radius);
+
+            paint.setStyle(Paint.Style.STROKE);
+            paint.setStrokeWidth(inner_w*2);
+            paint.setColor(palette[darkest]);
+            canvas.drawPath(p, paint);
+            paint.setStrokeWidth(inner_w);
+            paint.setColor(0xFFFFFFFF);
+            canvas.drawPath(p, paint);
+        }
+
+        @Override
+        public void setAlpha(int alpha) {
+
+        }
+
+        @Override
+        public void setColorFilter(ColorFilter colorFilter) {
+
+        }
+
+        @Override
+        public int getOpacity() {
+            return 0;
+        }
+    }
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
 
-        mLayout = new FrameLayout(this);
-        setContentView(mLayout);
+        layout = new FrameLayout(this);
+        setContentView(layout);
+
+        bg = new PBackground();
+        layout.setBackground(bg);
+
+        layout.setOnTouchListener(new View.OnTouchListener() {
+            final PointerCoords pc0 = new PointerCoords();
+            final PointerCoords pc1 = new PointerCoords();
+
+            @Override
+            public boolean onTouch(View v, MotionEvent event) {
+                switch (event.getActionMasked()) {
+                    case MotionEvent.ACTION_DOWN:
+                    case MotionEvent.ACTION_MOVE:
+                        if (event.getPointerCount() > 1) {
+                            event.getPointerCoords(0, pc0);
+                            event.getPointerCoords(1, pc1);
+                            bg.setRadius((float) Math.hypot(pc0.x - pc1.x, pc0.y - pc1.y) / 2f);
+                        }
+                        break;
+                }
+                return true;
+            }
+        });
     }
 
     @Override
-    public void onAttachedToWindow() {
-        final DisplayMetrics dm = getResources().getDisplayMetrics();
-        final float dp = dm.density;
-        final int size = (int)
-                (Math.min(Math.min(dm.widthPixels, dm.heightPixels), 600*dp) - 100*dp);
+    public void onStart() {
+        super.onStart();
 
-        final ImageView im = new ImageView(this);
-        final int pad = (int)(40*dp);
-        im.setPadding(pad, pad, pad, pad);
-        im.setTranslationZ(20);
-        im.setScaleX(0.5f);
-        im.setScaleY(0.5f);
-        im.setAlpha(0f);
+        bg.randomizePalette();
 
-        im.setBackground(new RippleDrawable(
-                ColorStateList.valueOf(0xFF776677),
-                getDrawable(com.android.internal.R.drawable.platlogo),
-                null));
-        im.setOutlineProvider(new ViewOutlineProvider() {
-            @Override
-            public void getOutline(View view, Outline outline) {
-                final int w = view.getWidth();
-                final int h = view.getHeight();
-                outline.setOval((int)(w*.125), (int)(h*.125), (int)(w*.96), (int)(h*.96));
-            }
-        });
-        im.setElevation(12f*dp);
-        im.setClickable(true);
-        im.setOnClickListener(new View.OnClickListener() {
-            @Override
-            public void onClick(View v) {
-                im.setOnLongClickListener(new View.OnLongClickListener() {
+        anim = new TimeAnimator();
+        anim.setTimeListener(
+                new TimeAnimator.TimeListener() {
                     @Override
-                    public boolean onLongClick(View v) {
-                        if (mTapCount < 5) return false;
-
-                        final ContentResolver cr = getContentResolver();
-                        if (Settings.System.getLong(cr, Settings.System.EGG_MODE, 0)
-                                == 0) {
-                            // For posterity: the moment this user unlocked the easter egg
-                            try {
-                                Settings.System.putLong(cr,
-                                        Settings.System.EGG_MODE,
-                                        System.currentTimeMillis());
-                            } catch (RuntimeException e) {
-                                Log.e("PlatLogoActivity", "Can't write settings", e);
-                            }
-                        }
-                        im.post(new Runnable() {
-                            @Override
-                            public void run() {
-                                try {
-                                    startActivity(new Intent(Intent.ACTION_MAIN)
-                                            .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
-                                                    | Intent.FLAG_ACTIVITY_CLEAR_TASK
-                                                    | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS)
-                                            .addCategory("com.android.internal.category.PLATLOGO"));
-                                } catch (ActivityNotFoundException ex) {
-                                    Log.e("PlatLogoActivity", "No more eggs.");
-                                }
-                                if (FINISH) finish();
-                            }
-                        });
-                        return true;
+                    public void onTimeUpdate(TimeAnimator animation, long totalTime, long deltaTime) {
+                        bg.setOffset((float) totalTime / 60000f);
+                        bg.invalidateSelf();
                     }
                 });
-                mTapCount++;
-            }
-        });
 
-        // Enable hardware keyboard input for TV compatibility.
-        im.setFocusable(true);
-        im.requestFocus();
-        im.setOnKeyListener(new View.OnKeyListener() {
-            @Override
-            public boolean onKey(View v, int keyCode, KeyEvent event) {
-                if (keyCode != KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_DOWN) {
-                    ++mKeyCount;
-                    if (mKeyCount > 2) {
-                        if (mTapCount > 5) {
-                            im.performLongClick();
-                        } else {
-                            im.performClick();
-                        }
-                    }
-                    return true;
-                } else {
-                    return false;
-                }
-            }
-        });
+        anim.start();
+    }
 
-        mLayout.addView(im, new FrameLayout.LayoutParams(size, size, Gravity.CENTER));
-
-        im.animate().scaleX(1f).scaleY(1f).alpha(1f)
-                .setInterpolator(mInterpolator)
-                .setDuration(500)
-                .setStartDelay(800)
-                .start();
+    @Override
+    public void onStop() {
+        if (anim != null) {
+            anim.cancel();
+            anim = null;
+        }
+        super.onStop();
     }
 }
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/backup/LocalTransport.java b/core/java/com/android/internal/backup/LocalTransport.java
index 543bd0c..b049db3 100644
--- a/core/java/com/android/internal/backup/LocalTransport.java
+++ b/core/java/com/android/internal/backup/LocalTransport.java
@@ -16,6 +16,7 @@
 
 package com.android.internal.backup;
 
+import android.app.backup.BackupAgent;
 import android.app.backup.BackupDataInput;
 import android.app.backup.BackupDataOutput;
 import android.app.backup.BackupTransport;
@@ -98,6 +99,7 @@
     private FileInputStream mCurFullRestoreStream;
     private FileOutputStream mFullRestoreSocketStream;
     private byte[] mFullRestoreBuffer;
+    private final LocalTransportParameters mParameters;
 
     private void makeDataDirs() {
         mCurrentSetDir.mkdirs();
@@ -105,11 +107,16 @@
         mCurrentSetIncrementalDir.mkdir();
     }
 
-    public LocalTransport(Context context) {
+    public LocalTransport(Context context, LocalTransportParameters parameters) {
         mContext = context;
+        mParameters = parameters;
         makeDataDirs();
     }
 
+    LocalTransportParameters getParameters() {
+        return mParameters;
+    }
+
     @Override
     public String name() {
         return new ComponentName(mContext, this.getClass()).flattenToShortString();
@@ -143,6 +150,17 @@
     }
 
     @Override
+    public int getTransportFlags() {
+        int flags = super.getTransportFlags();
+        // Testing for a fake flag and having it set as a boolean in settings prevents anyone from
+        // using this it to pull data from the agent
+        if (mParameters.isFakeEncryptionFlag()) {
+            flags |= BackupAgent.FLAG_FAKE_CLIENT_SIDE_ENCRYPTION_ENABLED;
+        }
+        return flags;
+    }
+
+    @Override
     public long requestBackupTime() {
         // any time is a good time for local backup
         return 0;
diff --git a/core/java/com/android/internal/backup/LocalTransportParameters.java b/core/java/com/android/internal/backup/LocalTransportParameters.java
new file mode 100644
index 0000000..390fae9
--- /dev/null
+++ b/core/java/com/android/internal/backup/LocalTransportParameters.java
@@ -0,0 +1,77 @@
+/*
+ * 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.internal.backup;
+
+import android.content.ContentResolver;
+import android.database.ContentObserver;
+import android.os.Handler;
+import android.provider.Settings;
+import android.util.KeyValueListParser;
+import android.util.Slog;
+
+class LocalTransportParameters {
+    private static final String TAG = "LocalTransportParams";
+    private static final String SETTING = Settings.Secure.BACKUP_LOCAL_TRANSPORT_PARAMETERS;
+    private static final String KEY_FAKE_ENCRYPTION_FLAG = "fake_encryption_flag";
+
+    private final KeyValueListParser mParser = new KeyValueListParser(',');
+    private final ContentObserver mObserver;
+    private final ContentResolver mResolver;
+    private boolean mFakeEncryptionFlag;
+
+    LocalTransportParameters(Handler handler, ContentResolver resolver) {
+        mObserver = new Observer(handler);
+        mResolver = resolver;
+    }
+
+    /** Observes for changes in the setting. This method MUST be paired with {@link #stop()}. */
+    void start() {
+        mResolver.registerContentObserver(Settings.Secure.getUriFor(SETTING), false, mObserver);
+        update();
+    }
+
+    /** Stop observing for changes in the setting. */
+    void stop() {
+        mResolver.unregisterContentObserver(mObserver);
+    }
+
+    boolean isFakeEncryptionFlag() {
+        return mFakeEncryptionFlag;
+    }
+
+    private void update() {
+        String parameters = "";
+        try {
+            parameters = Settings.Secure.getString(mResolver, SETTING);
+        } catch (IllegalArgumentException e) {
+            Slog.e(TAG, "Malformed " + SETTING + " setting: " + e.getMessage());
+        }
+        mParser.setString(parameters);
+        mFakeEncryptionFlag = mParser.getBoolean(KEY_FAKE_ENCRYPTION_FLAG, false);
+    }
+
+    private class Observer extends ContentObserver {
+        private Observer(Handler handler) {
+            super(handler);
+        }
+
+        @Override
+        public void onChange(boolean selfChange) {
+            update();
+        }
+    }
+}
diff --git a/core/java/com/android/internal/backup/LocalTransportService.java b/core/java/com/android/internal/backup/LocalTransportService.java
index 77ac313..69c48e2 100644
--- a/core/java/com/android/internal/backup/LocalTransportService.java
+++ b/core/java/com/android/internal/backup/LocalTransportService.java
@@ -26,8 +26,16 @@
     @Override
     public void onCreate() {
         if (sTransport == null) {
-            sTransport = new LocalTransport(this);
+            LocalTransportParameters parameters =
+                    new LocalTransportParameters(getMainThreadHandler(), getContentResolver());
+            sTransport = new LocalTransport(this, parameters);
         }
+        sTransport.getParameters().start();
+    }
+
+    @Override
+    public void onDestroy() {
+        sTransport.getParameters().stop();
     }
 
     @Override
diff --git a/core/java/com/android/internal/colorextraction/drawable/GradientDrawable.java b/core/java/com/android/internal/colorextraction/drawable/GradientDrawable.java
index 500c028..bf151c3 100644
--- a/core/java/com/android/internal/colorextraction/drawable/GradientDrawable.java
+++ b/core/java/com/android/internal/colorextraction/drawable/GradientDrawable.java
@@ -57,6 +57,8 @@
     private int mMainColor;
     private int mSecondaryColor;
     private ValueAnimator mColorAnimation;
+    private int mMainColorTo;
+    private int mSecondaryColorTo;
 
     public GradientDrawable(@NonNull Context context) {
         mDensity = context.getResources().getDisplayMetrics().density;
@@ -76,7 +78,7 @@
     }
 
     public void setColors(int mainColor, int secondaryColor, boolean animated) {
-        if (mainColor == mMainColor && secondaryColor == mSecondaryColor) {
+        if (mainColor == mMainColorTo && secondaryColor == mSecondaryColorTo) {
             return;
         }
 
@@ -84,6 +86,9 @@
             mColorAnimation.cancel();
         }
 
+        mMainColorTo = mainColor;
+        mSecondaryColorTo = mainColor;
+
         if (animated) {
             final int mainFrom = mMainColor;
             final int secFrom = mSecondaryColor;
diff --git a/core/java/com/android/internal/colorextraction/types/Tonal.java b/core/java/com/android/internal/colorextraction/types/Tonal.java
index 9b7383f..7b25a06 100644
--- a/core/java/com/android/internal/colorextraction/types/Tonal.java
+++ b/core/java/com/android/internal/colorextraction/types/Tonal.java
@@ -405,12 +405,13 @@
         return v - (float) Math.floor(v);
     }
 
-    static class TonalPalette {
-        final float[] h;
-        final float[] s;
-        final float[] l;
-        final float minHue;
-        final float maxHue;
+    @VisibleForTesting
+    public static class TonalPalette {
+        public final float[] h;
+        public final float[] s;
+        public final float[] l;
+        public final float minHue;
+        public final float maxHue;
 
         TonalPalette(float[] h, float[] s, float[] l) {
             if (h.length != s.length || s.length != l.length) {
diff --git a/core/java/com/android/internal/notification/SystemNotificationChannels.java b/core/java/com/android/internal/notification/SystemNotificationChannels.java
index 4a181b2..44adbb2 100644
--- a/core/java/com/android/internal/notification/SystemNotificationChannels.java
+++ b/core/java/com/android/internal/notification/SystemNotificationChannels.java
@@ -49,6 +49,7 @@
     public static String USB = "USB";
     public static String FOREGROUND_SERVICE = "FOREGROUND_SERVICE";
     public static String HEAVY_WEIGHT_APP = "HEAVY_WEIGHT_APP";
+    public static String SYSTEM_CHANGES = "SYSTEM_CHANGES";
 
     public static void createAll(Context context) {
         final NotificationManager nm = context.getSystemService(NotificationManager.class);
@@ -152,6 +153,11 @@
                 .build());
         channelsList.add(heavyWeightChannel);
 
+        NotificationChannel systemChanges = new NotificationChannel(SYSTEM_CHANGES,
+                context.getString(R.string.notification_channel_system_changes),
+                NotificationManager.IMPORTANCE_LOW);
+        channelsList.add(systemChanges);
+
         nm.createNotificationChannels(channelsList);
     }
 
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 40dcf25b..4e51591 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -187,7 +187,7 @@
     public final AtomicFile mCheckinFile;
     public final AtomicFile mDailyFile;
 
-    static final int MSG_UPDATE_WAKELOCKS = 1;
+    static final int MSG_REPORT_CPU_UPDATE_NEEDED = 1;
     static final int MSG_REPORT_POWER_CHANGE = 2;
     static final int MSG_REPORT_CHARGING = 3;
     static final long DELAY_UPDATE_WAKELOCKS = 5*1000;
@@ -230,6 +230,13 @@
     @VisibleForTesting
     protected final SparseIntArray mPendingUids = new SparseIntArray();
 
+    @GuardedBy("this")
+    private long mNumCpuTimeReads;
+    @GuardedBy("this")
+    private long mNumBatchedCpuTimeReads;
+    @GuardedBy("this")
+    private long mCpuTimeReadsTrackingStartTime = SystemClock.uptimeMillis();
+
     /** Container for Resource Power Manager stats. Updated by updateRpmStatsLocked. */
     private final RpmStats mTmpRpmStats = new RpmStats();
     /** The soonest the RPM stats can be updated after it was last updated. */
@@ -273,10 +280,7 @@
         public void handleMessage(Message msg) {
             BatteryCallback cb = mCallback;
             switch (msg.what) {
-                case MSG_UPDATE_WAKELOCKS:
-                    synchronized (BatteryStatsImpl.this) {
-                        updateCpuTimeLocked();
-                    }
+                case MSG_REPORT_CPU_UPDATE_NEEDED:
                     if (cb != null) {
                         cb.batteryNeedsCpuUpdate();
                     }
@@ -302,6 +306,10 @@
         }
     }
 
+    public void postBatteryNeedsCpuUpdateMsg() {
+        mHandler.sendEmptyMessage(MSG_REPORT_CPU_UPDATE_NEEDED);
+    }
+
     /**
      * Update per-freq cpu times for all the uids in {@link #mPendingUids}.
      */
@@ -484,9 +492,14 @@
 
         Future<?> scheduleSync(String reason, int flags);
         Future<?> scheduleCpuSyncDueToRemovedUid(int uid);
-        Future<?> scheduleReadProcStateCpuTimes(boolean onBattery, boolean onBatteryScreenOff);
+        Future<?> scheduleReadProcStateCpuTimes(boolean onBattery, boolean onBatteryScreenOff,
+                long delayMillis);
         Future<?> scheduleCopyFromAllUidsCpuTimes(boolean onBattery, boolean onBatteryScreenOff);
         Future<?> scheduleCpuSyncDueToSettingChange();
+        Future<?> scheduleCpuSyncDueToScreenStateChange(boolean onBattery,
+                boolean onBatteryScreenOff);
+        Future<?> scheduleCpuSyncDueToWakelockChange(long delayMillis);
+        void cancelCpuSyncDueToWakelockChange();
     }
 
     public Handler mHandler;
@@ -678,7 +691,8 @@
     StopwatchTimer mCameraOnTimer;
 
     int mGpsSignalQualityBin = -1;
-    final StopwatchTimer[] mGpsSignalQualityTimer =
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+    protected final StopwatchTimer[] mGpsSignalQualityTimer =
         new StopwatchTimer[GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS];
 
     int mPhoneSignalStrengthBin = -1;
@@ -760,6 +774,8 @@
     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
     protected StopwatchTimer mBluetoothScanTimer;
 
+    boolean mIsCellularTxPowerHigh = false;
+
     int mMobileRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
     long mMobileRadioActiveStartTime;
     StopwatchTimer mMobileRadioActiveTimer;
@@ -1450,12 +1466,10 @@
         long mCount;
         long mLoadedCount;
         long mUnpluggedCount;
-        long mPluggedCount;
 
         LongSamplingCounter(TimeBase timeBase, Parcel in) {
             mTimeBase = timeBase;
-            mPluggedCount = in.readLong();
-            mCount = mPluggedCount;
+            mCount = in.readLong();
             mLoadedCount = in.readLong();
             mUnpluggedCount = in.readLong();
             timeBase.add(this);
@@ -1474,16 +1488,15 @@
 
         @Override
         public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
-            mUnpluggedCount = mPluggedCount;
+            mUnpluggedCount = mCount;
         }
 
         @Override
         public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
-            mPluggedCount = mCount;
         }
 
         public long getCountLocked(int which) {
-            long val = mTimeBase.isRunning() ? mCount : mPluggedCount;
+            long val = mCount;
             if (which == STATS_SINCE_UNPLUGGED) {
                 val -= mUnpluggedCount;
             } else if (which != STATS_SINCE_CHARGED) {
@@ -1496,12 +1509,15 @@
         public void logState(Printer pw, String prefix) {
             pw.println(prefix + "mCount=" + mCount
                     + " mLoadedCount=" + mLoadedCount
-                    + " mUnpluggedCount=" + mUnpluggedCount
-                    + " mPluggedCount=" + mPluggedCount);
+                    + " mUnpluggedCount=" + mUnpluggedCount);
         }
 
         void addCountLocked(long count) {
-            if (mTimeBase.isRunning()) {
+            addCountLocked(count, mTimeBase.isRunning());
+        }
+
+        void addCountLocked(long count, boolean isRunning) {
+            if (isRunning) {
                 mCount += count;
             }
         }
@@ -1511,7 +1527,7 @@
          */
         void reset(boolean detachIfReset) {
             mCount = 0;
-            mLoadedCount = mPluggedCount = mUnpluggedCount = 0;
+            mLoadedCount = mUnpluggedCount = 0;
             if (detachIfReset) {
                 detach();
             }
@@ -1528,7 +1544,7 @@
         void readSummaryFromParcelLocked(Parcel in) {
             mLoadedCount = in.readLong();
             mCount = mLoadedCount;
-            mUnpluggedCount = mPluggedCount = mLoadedCount;
+            mUnpluggedCount = mLoadedCount;
         }
     }
 
@@ -3522,7 +3538,7 @@
         mHistoryLastWritten.cmd = HistoryItem.CMD_NULL;
     }
 
-    void addHistoryBufferLocked(long elapsedRealtimeMs, long uptimeMs, HistoryItem cur) {
+    void addHistoryBufferLocked(long elapsedRealtimeMs, HistoryItem cur) {
         if (!mHaveBatteryLevel || !mRecordingHistory) {
             return;
         }
@@ -3603,8 +3619,8 @@
         } else if (dataSize >= MAX_HISTORY_BUFFER) {
             if (!mHistoryOverflow) {
                 mHistoryOverflow = true;
-                addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.CMD_UPDATE, cur);
-                addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.CMD_OVERFLOW, cur);
+                addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_UPDATE, cur);
+                addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_OVERFLOW, cur);
                 return;
             }
 
@@ -3642,7 +3658,7 @@
                 return;
             }
 
-            addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.CMD_UPDATE, cur);
+            addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_UPDATE, cur);
             return;
         }
 
@@ -3650,15 +3666,14 @@
             // The history is currently empty; we need it to start with a time stamp.
             cur.currentTime = System.currentTimeMillis();
             if (recordResetDueToOverflow) {
-                addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.CMD_OVERFLOW, cur);
+                addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_OVERFLOW, cur);
             }
-            addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.CMD_RESET, cur);
+            addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_RESET, cur);
         }
-        addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.CMD_UPDATE, cur);
+        addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_UPDATE, cur);
     }
 
-    private void addHistoryBufferLocked(long elapsedRealtimeMs, long uptimeMs, byte cmd,
-            HistoryItem cur) {
+    private void addHistoryBufferLocked(long elapsedRealtimeMs, byte cmd, HistoryItem cur) {
         if (mIteratingHistory) {
             throw new IllegalStateException("Can't do this while iterating history!");
         }
@@ -3692,17 +3707,17 @@
                 mHistoryAddTmp.wakeReasonTag = null;
                 mHistoryAddTmp.eventCode = HistoryItem.EVENT_NONE;
                 mHistoryAddTmp.states &= ~HistoryItem.STATE_CPU_RUNNING_FLAG;
-                addHistoryRecordInnerLocked(wakeElapsedTime, uptimeMs, mHistoryAddTmp);
+                addHistoryRecordInnerLocked(wakeElapsedTime, mHistoryAddTmp);
             }
         }
         mHistoryCur.states |= HistoryItem.STATE_CPU_RUNNING_FLAG;
         mTrackRunningHistoryElapsedRealtime = elapsedRealtimeMs;
         mTrackRunningHistoryUptime = uptimeMs;
-        addHistoryRecordInnerLocked(elapsedRealtimeMs, uptimeMs, mHistoryCur);
+        addHistoryRecordInnerLocked(elapsedRealtimeMs, mHistoryCur);
     }
 
-    void addHistoryRecordInnerLocked(long elapsedRealtimeMs, long uptimeMs, HistoryItem cur) {
-        addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs, cur);
+    void addHistoryRecordInnerLocked(long elapsedRealtimeMs, HistoryItem cur) {
+        addHistoryBufferLocked(elapsedRealtimeMs, cur);
 
         if (!USE_OLD_HISTORY) {
             return;
@@ -3743,7 +3758,7 @@
 
         if (mNumHistoryItems == MAX_HISTORY_ITEMS
                 || mNumHistoryItems == MAX_MAX_HISTORY_ITEMS) {
-            addHistoryRecordLocked(elapsedRealtimeMs, HistoryItem.CMD_OVERFLOW);
+            addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_OVERFLOW, cur);
         }
 
         if (mNumHistoryItems >= MAX_HISTORY_ITEMS) {
@@ -3760,7 +3775,7 @@
             }
         }
 
-        addHistoryRecordLocked(elapsedRealtimeMs, HistoryItem.CMD_UPDATE);
+        addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_UPDATE, cur);
     }
 
     public void addHistoryEventLocked(long elapsedRealtimeMs, long uptimeMs, int code,
@@ -3826,6 +3841,7 @@
         mActiveHistoryStates2 = 0xffffffff;
     }
 
+    @GuardedBy("this")
     public void updateTimeBasesLocked(boolean unplugged, int screenState, long uptime,
             long realtime) {
         final boolean screenOff = !isScreenOn(screenState);
@@ -3849,9 +3865,6 @@
                         + Display.stateToString(screenState)
                         + " and battery is " + (unplugged ? "on" : "off"));
             }
-            updateCpuTimeLocked();
-            mExternalSync.scheduleCopyFromAllUidsCpuTimes(mOnBatteryTimeBase.isRunning(),
-                    mOnBatteryScreenOffTimeBase.isRunning());
 
             mOnBatteryTimeBase.setRunning(unplugged, uptime, realtime);
             if (updateOnBatteryTimeBase) {
@@ -3903,6 +3916,7 @@
      * This should only be called after the cpu times have been read.
      * @see #scheduleRemoveIsolatedUidLocked(int, int)
      */
+    @GuardedBy("this")
     public void removeIsolatedUidLocked(int isolatedUid) {
         StatsLog.write(
                 StatsLog.ISOLATED_UID_CHANGED, mIsolatedUids.get(isolatedUid, -1),
@@ -4139,15 +4153,11 @@
     }
 
     private void requestWakelockCpuUpdate() {
-        if (!mHandler.hasMessages(MSG_UPDATE_WAKELOCKS)) {
-            Message m = mHandler.obtainMessage(MSG_UPDATE_WAKELOCKS);
-            mHandler.sendMessageDelayed(m, DELAY_UPDATE_WAKELOCKS);
-        }
+        mExternalSync.scheduleCpuSyncDueToWakelockChange(DELAY_UPDATE_WAKELOCKS);
     }
 
     private void requestImmediateCpuUpdate() {
-        mHandler.removeMessages(MSG_UPDATE_WAKELOCKS);
-        mHandler.sendEmptyMessage(MSG_UPDATE_WAKELOCKS);
+        mExternalSync.scheduleCpuSyncDueToWakelockChange(0 /* delayMillis */);
     }
 
     public void setRecordAllHistoryLocked(boolean enabled) {
@@ -4550,7 +4560,7 @@
     }
 
     public boolean startAddingCpuLocked() {
-        mHandler.removeMessages(MSG_UPDATE_WAKELOCKS);
+        mExternalSync.cancelCpuSyncDueToWakelockChange();
         return mOnBatteryInternal;
     }
 
@@ -4732,6 +4742,7 @@
         return;
     }
 
+    @GuardedBy("this")
     public void noteScreenStateLocked(int state) {
         state = mPretendScreenOff ? Display.STATE_OFF : state;
 
@@ -4802,6 +4813,8 @@
                         + Display.stateToString(state));
                 addHistoryRecordLocked(elapsedRealtime, uptime);
             }
+            mExternalSync.scheduleCpuSyncDueToScreenStateChange(
+                    mOnBatteryTimeBase.isRunning(), mOnBatteryScreenOffTimeBase.isRunning());
             if (isScreenOn(state)) {
                 updateTimeBasesLocked(mOnBatteryTimeBase.isRunning(), state,
                         mClocks.uptimeMillis() * 1000, elapsedRealtime * 1000);
@@ -5281,6 +5294,18 @@
                 case TelephonyManager.NETWORK_TYPE_HSPAP:
                     bin = DATA_CONNECTION_HSPAP;
                     break;
+                case TelephonyManager.NETWORK_TYPE_GSM:
+                    bin = DATA_CONNECTION_GSM;
+                    break;
+                case TelephonyManager.NETWORK_TYPE_TD_SCDMA:
+                    bin = DATA_CONNECTION_TD_SCDMA;
+                    break;
+                case TelephonyManager.NETWORK_TYPE_IWLAN:
+                    bin = DATA_CONNECTION_IWLAN;
+                    break;
+                case TelephonyManager.NETWORK_TYPE_LTE_CA:
+                    bin = DATA_CONNECTION_LTE_CA;
+                    break;
                 default:
                     bin = DATA_CONNECTION_OTHER;
                     break;
@@ -9191,8 +9216,14 @@
             }
 
             public void addCpuTimeLocked(int utime, int stime) {
-                mUserTime += utime;
-                mSystemTime += stime;
+                addCpuTimeLocked(utime, stime, mBsi.mOnBatteryTimeBase.isRunning());
+            }
+
+            public void addCpuTimeLocked(int utime, int stime, boolean isRunning) {
+                if (isRunning) {
+                    mUserTime += utime;
+                    mSystemTime += stime;
+                }
             }
 
             public void addForegroundTimeLocked(long ttime) {
@@ -9648,6 +9679,7 @@
             return ps;
         }
 
+        @GuardedBy("mBsi")
         public void updateUidProcessStateLocked(int procState) {
             int uidRunningState;
             // Make special note of Foreground Services
@@ -9670,7 +9702,11 @@
                         if (mBsi.mPendingUids.size() == 0) {
                             mBsi.mExternalSync.scheduleReadProcStateCpuTimes(
                                     mBsi.mOnBatteryTimeBase.isRunning(),
-                                    mBsi.mOnBatteryScreenOffTimeBase.isRunning());
+                                    mBsi.mOnBatteryScreenOffTimeBase.isRunning(),
+                                    mBsi.mConstants.PROC_STATE_CPU_TIMES_READ_DELAY_MS);
+                            mBsi.mNumCpuTimeReads++;
+                        } else {
+                            mBsi.mNumBatchedCpuTimeReads++;
                         }
                         if (mBsi.mPendingUids.indexOfKey(mUid) < 0
                                 || ArrayUtils.contains(CRITICAL_PROC_STATES, mProcessState)) {
@@ -9931,8 +9967,6 @@
             if (wl != null) {
                 StopwatchTimer wlt = getWakelockTimerLocked(wl, type);
                 wlt.stopRunningLocked(elapsedRealtimeMs);
-                if (!wlt.isRunningLocked()) { // only tell statsd if truly stopped
-                }
             }
             if (type == WAKE_TYPE_PARTIAL) {
                 if (mAggregatedPartialWakelockTimer != null) {
@@ -11206,6 +11240,25 @@
     private ModemActivityInfo mLastModemActivityInfo =
             new ModemActivityInfo(0, 0, 0, new int[0], 0, 0);
 
+    private ModemActivityInfo getDeltaModemActivityInfo(ModemActivityInfo activityInfo) {
+        if (activityInfo == null) {
+            return null;
+        }
+        int[] txTimeMs = new int[ModemActivityInfo.TX_POWER_LEVELS];
+        for (int i = 0; i < ModemActivityInfo.TX_POWER_LEVELS; i++) {
+            txTimeMs[i] = activityInfo.getTxTimeMillis()[i]
+                    - mLastModemActivityInfo.getTxTimeMillis()[i];
+        }
+        ModemActivityInfo deltaInfo = new ModemActivityInfo(activityInfo.getTimestamp(),
+                activityInfo.getSleepTimeMillis() - mLastModemActivityInfo.getSleepTimeMillis(),
+                activityInfo.getIdleTimeMillis() - mLastModemActivityInfo.getIdleTimeMillis(),
+                txTimeMs,
+                activityInfo.getRxTimeMillis() - mLastModemActivityInfo.getRxTimeMillis(),
+                activityInfo.getEnergyUsed() - mLastModemActivityInfo.getEnergyUsed());
+        mLastModemActivityInfo = activityInfo;
+        return deltaInfo;
+    }
+
     /**
      * Distribute Cell radio energy info and network traffic to apps.
      */
@@ -11213,6 +11266,10 @@
         if (DEBUG_ENERGY) {
             Slog.d(TAG, "Updating mobile radio stats with " + activityInfo);
         }
+        ModemActivityInfo deltaInfo = getDeltaModemActivityInfo(activityInfo);
+
+        // Add modem tx power to history.
+        addModemTxPowerToHistory(deltaInfo);
 
         // Grab a separate lock to acquire the network stats, which may do I/O.
         NetworkStats delta = null;
@@ -11226,22 +11283,6 @@
             }
         }
 
-        int rxTimeMs = 0;
-        int[] txTimeMs = new int[ModemActivityInfo.TX_POWER_LEVELS];
-        int idleTimeMs = 0;
-        int sleepTimeMs = 0;
-        if (activityInfo != null) {
-            rxTimeMs = activityInfo.getRxTimeMillis() - mLastModemActivityInfo.getRxTimeMillis();
-            for (int i = 0; i < ModemActivityInfo.TX_POWER_LEVELS; i++) {
-                txTimeMs[i] = activityInfo.getTxTimeMillis()[i]
-                        - mLastModemActivityInfo.getTxTimeMillis()[i];
-            }
-            idleTimeMs =
-                    activityInfo.getIdleTimeMillis() - mLastModemActivityInfo.getIdleTimeMillis();
-            sleepTimeMs =
-                    activityInfo.getSleepTimeMillis() - mLastModemActivityInfo.getSleepTimeMillis();
-        }
-
         synchronized (this) {
             if (!mOnBatteryInternal) {
                 if (delta != null) {
@@ -11250,14 +11291,14 @@
                 return;
             }
 
-            if (activityInfo != null) {
+            if (deltaInfo != null) {
                 mHasModemReporting = true;
                 mModemActivity.getIdleTimeCounter().addCountLocked(
-                    idleTimeMs);
-                mModemActivity.getRxTimeCounter().addCountLocked(rxTimeMs);
+                        deltaInfo.getIdleTimeMillis());
+                mModemActivity.getRxTimeCounter().addCountLocked(deltaInfo.getRxTimeMillis());
                 for (int lvl = 0; lvl < ModemActivityInfo.TX_POWER_LEVELS; lvl++) {
                     mModemActivity.getTxTimeCounters()[lvl]
-                        .addCountLocked(txTimeMs[lvl]);
+                        .addCountLocked(deltaInfo.getTxTimeMillis()[lvl]);
                 }
 
                 // POWER_MODEM_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
@@ -11265,16 +11306,17 @@
                     PowerProfile.POWER_MODEM_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
                 if (opVolt != 0) {
                     double energyUsed =
-                        sleepTimeMs *
+                            deltaInfo.getSleepTimeMillis() *
                             mPowerProfile.getAveragePower(PowerProfile.POWER_MODEM_CONTROLLER_SLEEP)
-                            + idleTimeMs *
+                            + deltaInfo.getIdleTimeMillis() *
                             mPowerProfile.getAveragePower(PowerProfile.POWER_MODEM_CONTROLLER_IDLE)
-                            + rxTimeMs *
+                            + deltaInfo.getRxTimeMillis() *
                             mPowerProfile.getAveragePower(PowerProfile.POWER_MODEM_CONTROLLER_RX);
+                    int[] txTimeMs = deltaInfo.getTxTimeMillis();
                     for (int i = 0; i < Math.min(txTimeMs.length,
-                        SignalStrength.NUM_SIGNAL_STRENGTH_BINS); i++) {
+                            SignalStrength.NUM_SIGNAL_STRENGTH_BINS); i++) {
                         energyUsed += txTimeMs[i] * mPowerProfile.getAveragePower(
-                            PowerProfile.POWER_MODEM_CONTROLLER_TX, i);
+                                PowerProfile.POWER_MODEM_CONTROLLER_TX, i);
                     }
 
                     // We store the power drain as mAms.
@@ -11350,11 +11392,11 @@
                         radioTime -= appRadioTime;
                         totalPackets -= appPackets;
 
-                        if (activityInfo != null) {
+                        if (deltaInfo != null) {
                             ControllerActivityCounterImpl activityCounter =
                                     u.getOrCreateModemControllerActivityLocked();
                             if (totalRxPackets > 0 && entry.rxPackets > 0) {
-                                final long rxMs = (entry.rxPackets * rxTimeMs)
+                                final long rxMs = (entry.rxPackets * deltaInfo.getRxTimeMillis())
                                         / totalRxPackets;
                                 activityCounter.getRxTimeCounter().addCountLocked(rxMs);
                             }
@@ -11362,7 +11404,7 @@
                             if (totalTxPackets > 0 && entry.txPackets > 0) {
                                 for (int lvl = 0; lvl < ModemActivityInfo.TX_POWER_LEVELS; lvl++) {
                                     long txMs =
-                                            entry.txPackets * txTimeMs[lvl];
+                                            entry.txPackets * deltaInfo.getTxTimeMillis()[lvl];
                                     txMs /= totalTxPackets;
                                     activityCounter.getTxTimeCounters()[lvl].addCountLocked(txMs);
                                 }
@@ -11388,6 +11430,44 @@
             new BluetoothActivityEnergyInfo(0, 0, 0, 0, 0, 0);
 
     /**
+     * Add modem tx power to history
+     * Device is said to be in high cellular transmit power when it has spent most of the transmit
+     * time at the highest power level.
+     * @param activityInfo
+     */
+    private void addModemTxPowerToHistory(final ModemActivityInfo activityInfo) {
+        if (activityInfo == null) {
+            return;
+        }
+        int[] txTimeMs = activityInfo.getTxTimeMillis();
+        if (txTimeMs == null || txTimeMs.length != ModemActivityInfo.TX_POWER_LEVELS) {
+            return;
+        }
+        final long elapsedRealtime = mClocks.elapsedRealtime();
+        final long uptime = mClocks.uptimeMillis();
+        int levelMaxTimeSpent = 0;
+        for (int i = 1; i < txTimeMs.length; i++) {
+            if (txTimeMs[i] > txTimeMs[levelMaxTimeSpent]) {
+                levelMaxTimeSpent = i;
+            }
+        }
+        if (levelMaxTimeSpent == ModemActivityInfo.TX_POWER_LEVELS - 1) {
+            if (!mIsCellularTxPowerHigh) {
+                mHistoryCur.states2 |= HistoryItem.STATE2_CELLULAR_HIGH_TX_POWER_FLAG;
+                addHistoryRecordLocked(elapsedRealtime, uptime);
+                mIsCellularTxPowerHigh = true;
+            }
+            return;
+        }
+        if (mIsCellularTxPowerHigh) {
+            mHistoryCur.states2 &= ~HistoryItem.STATE2_CELLULAR_HIGH_TX_POWER_FLAG;
+            addHistoryRecordLocked(elapsedRealtime, uptime);
+            mIsCellularTxPowerHigh = false;
+        }
+        return;
+    }
+
+    /**
      * Distribute Bluetooth energy info and network traffic to apps.
      * @param info The energy information from the bluetooth controller.
      */
@@ -11716,12 +11796,24 @@
         }
     }
 
+    public boolean isOnBatteryLocked() {
+        return mOnBatteryTimeBase.isRunning();
+    }
+
+    public boolean isOnBatteryScreenOffLocked() {
+        return mOnBatteryScreenOffTimeBase.isRunning();
+    }
+
     /**
      * Read and distribute CPU usage across apps. If their are partial wakelocks being held
      * and we are on battery with screen off, we give more of the cpu time to those apps holding
      * wakelocks. If the screen is on, we just assign the actual cpu time an app used.
+     * It's possible this will be invoked after the internal battery/screen states are updated, so
+     * passing the appropriate battery/screen states to try attribute the cpu times to correct
+     * buckets.
      */
-    public void updateCpuTimeLocked() {
+    @GuardedBy("this")
+    public void updateCpuTimeLocked(boolean onBattery, boolean onBatteryScreenOff) {
         if (mPowerProfile == null) {
             return;
         }
@@ -11738,7 +11830,7 @@
         // usually holding the wakelock on behalf of an app.
         // And Only distribute cpu power to wakelocks if the screen is off and we're on battery.
         ArrayList<StopwatchTimer> partialTimersToConsider = null;
-        if (mOnBatteryScreenOffTimeBase.isRunning()) {
+        if (onBatteryScreenOff) {
             partialTimersToConsider = new ArrayList<>();
             for (int i = mPartialTimers.size() - 1; i >= 0; --i) {
                 final StopwatchTimer timer = mPartialTimers.get(i);
@@ -11756,7 +11848,7 @@
 
         // When the battery is not on, we don't attribute the cpu times to any timers but we still
         // need to take the snapshots.
-        if (!mOnBatteryInternal) {
+        if (!onBattery) {
             mKernelUidCpuTimeReader.readDelta(null);
             mKernelUidCpuFreqTimeReader.readDelta(null);
             if (mConstants.TRACK_CPU_ACTIVE_CLUSTER_TIME) {
@@ -11772,16 +11864,16 @@
         mUserInfoProvider.refreshUserIds();
         final SparseLongArray updatedUids = mKernelUidCpuFreqTimeReader.perClusterTimesAvailable()
                 ? null : new SparseLongArray();
-        readKernelUidCpuTimesLocked(partialTimersToConsider, updatedUids);
+        readKernelUidCpuTimesLocked(partialTimersToConsider, updatedUids, onBattery);
         // updatedUids=null means /proc/uid_time_in_state provides snapshots of per-cluster cpu
         // freqs, so no need to approximate these values.
         if (updatedUids != null) {
-            updateClusterSpeedTimes(updatedUids);
+            updateClusterSpeedTimes(updatedUids, onBattery);
         }
-        readKernelUidCpuFreqTimesLocked(partialTimersToConsider);
+        readKernelUidCpuFreqTimesLocked(partialTimersToConsider, onBattery, onBatteryScreenOff);
         if (mConstants.TRACK_CPU_ACTIVE_CLUSTER_TIME) {
-            readKernelUidCpuActiveTimesLocked();
-            readKernelUidCpuClusterTimesLocked();
+            readKernelUidCpuActiveTimesLocked(onBattery);
+            readKernelUidCpuClusterTimesLocked(onBattery);
         }
     }
 
@@ -11821,7 +11913,7 @@
      * @param updatedUids The uids for which times spent at different frequencies are calculated.
      */
     @VisibleForTesting
-    public void updateClusterSpeedTimes(@NonNull SparseLongArray updatedUids) {
+    public void updateClusterSpeedTimes(@NonNull SparseLongArray updatedUids, boolean onBattery) {
         long totalCpuClustersTimeMs = 0;
         // Read the time spent for each cluster at various cpu frequencies.
         final long[][] clusterSpeedTimesMs = new long[mKernelCpuSpeedReaders.length][];
@@ -11863,7 +11955,7 @@
                         }
                         cpuSpeeds[speed].addCountLocked(appCpuTimeUs
                                 * clusterSpeedTimesMs[cluster][speed]
-                                / totalCpuClustersTimeMs);
+                                / totalCpuClustersTimeMs, onBattery);
                     }
                 }
             }
@@ -11880,7 +11972,7 @@
      */
     @VisibleForTesting
     public void readKernelUidCpuTimesLocked(@Nullable ArrayList<StopwatchTimer> partialTimers,
-            @Nullable SparseLongArray updatedUids) {
+            @Nullable SparseLongArray updatedUids, boolean onBattery) {
         mTempTotalCpuUserTimeUs = mTempTotalCpuSystemTimeUs = 0;
         final int numWakelocks = partialTimers == null ? 0 : partialTimers.size();
         final long startTimeMs = mClocks.uptimeMillis();
@@ -11931,8 +12023,8 @@
                 Slog.d(TAG, sb.toString());
             }
 
-            u.mUserCpuTime.addCountLocked(userTimeUs);
-            u.mSystemCpuTime.addCountLocked(systemTimeUs);
+            u.mUserCpuTime.addCountLocked(userTimeUs, onBattery);
+            u.mSystemCpuTime.addCountLocked(systemTimeUs, onBattery);
             if (updatedUids != null) {
                 updatedUids.put(u.getUid(), userTimeUs + systemTimeUs);
             }
@@ -11964,15 +12056,15 @@
                     Slog.d(TAG, sb.toString());
                 }
 
-                timer.mUid.mUserCpuTime.addCountLocked(userTimeUs);
-                timer.mUid.mSystemCpuTime.addCountLocked(systemTimeUs);
+                timer.mUid.mUserCpuTime.addCountLocked(userTimeUs, onBattery);
+                timer.mUid.mSystemCpuTime.addCountLocked(systemTimeUs, onBattery);
                 if (updatedUids != null) {
                     final int uid = timer.mUid.getUid();
                     updatedUids.put(uid, updatedUids.get(uid, 0) + userTimeUs + systemTimeUs);
                 }
 
                 final Uid.Proc proc = timer.mUid.getProcessStatsLocked("*wakelock*");
-                proc.addCpuTimeLocked(userTimeUs / 1000, systemTimeUs / 1000);
+                proc.addCpuTimeLocked(userTimeUs / 1000, systemTimeUs / 1000, onBattery);
 
                 mTempTotalCpuUserTimeUs -= userTimeUs;
                 mTempTotalCpuSystemTimeUs -= systemTimeUs;
@@ -11987,7 +12079,8 @@
      * @param partialTimers The wakelock holders among which the cpu freq times will be distributed.
      */
     @VisibleForTesting
-    public void readKernelUidCpuFreqTimesLocked(@Nullable ArrayList<StopwatchTimer> partialTimers) {
+    public void readKernelUidCpuFreqTimesLocked(@Nullable ArrayList<StopwatchTimer> partialTimers,
+            boolean onBattery, boolean onBatteryScreenOff) {
         final boolean perClusterTimesAvailable =
                 mKernelUidCpuFreqTimeReader.perClusterTimesAvailable();
         final int numWakelocks = partialTimers == null ? 0 : partialTimers.size();
@@ -12010,13 +12103,13 @@
             if (u.mCpuFreqTimeMs == null || u.mCpuFreqTimeMs.getSize() != cpuFreqTimeMs.length) {
                 u.mCpuFreqTimeMs = new LongSamplingCounterArray(mOnBatteryTimeBase);
             }
-            u.mCpuFreqTimeMs.addCountLocked(cpuFreqTimeMs);
+            u.mCpuFreqTimeMs.addCountLocked(cpuFreqTimeMs, onBattery);
             if (u.mScreenOffCpuFreqTimeMs == null ||
                     u.mScreenOffCpuFreqTimeMs.getSize() != cpuFreqTimeMs.length) {
                 u.mScreenOffCpuFreqTimeMs = new LongSamplingCounterArray(
                         mOnBatteryScreenOffTimeBase);
             }
-            u.mScreenOffCpuFreqTimeMs.addCountLocked(cpuFreqTimeMs);
+            u.mScreenOffCpuFreqTimeMs.addCountLocked(cpuFreqTimeMs, onBatteryScreenOff);
 
             if (perClusterTimesAvailable) {
                 if (u.mCpuClusterSpeedTimesUs == null ||
@@ -12052,7 +12145,7 @@
                         } else {
                             appAllocationUs = cpuFreqTimeMs[freqIndex] * 1000;
                         }
-                        cpuTimesUs[speed].addCountLocked(appAllocationUs);
+                        cpuTimesUs[speed].addCountLocked(appAllocationUs, onBattery);
                         freqIndex++;
                     }
                 }
@@ -12086,7 +12179,7 @@
                         }
                         final long allocationUs =
                                 mWakeLockAllocationsUs[cluster][speed] / (numWakelocks - i);
-                        cpuTimeUs[speed].addCountLocked(allocationUs);
+                        cpuTimeUs[speed].addCountLocked(allocationUs, onBattery);
                         mWakeLockAllocationsUs[cluster][speed] -= allocationUs;
                     }
                 }
@@ -12099,7 +12192,7 @@
      * counters.
      */
     @VisibleForTesting
-    public void readKernelUidCpuActiveTimesLocked() {
+    public void readKernelUidCpuActiveTimesLocked(boolean onBattery) {
         final long startTimeMs = mClocks.uptimeMillis();
         mKernelUidCpuActiveTimeReader.readDelta((uid, cpuActiveTimesUs) -> {
             uid = mapUid(uid);
@@ -12114,7 +12207,7 @@
                 return;
             }
             final Uid u = getUidStatsLocked(uid);
-            u.mCpuActiveTimeMs.addCountLocked(cpuActiveTimesUs);
+            u.mCpuActiveTimeMs.addCountLocked(cpuActiveTimesUs, onBattery);
         });
 
         final long elapsedTimeMs = mClocks.uptimeMillis() - startTimeMs;
@@ -12128,7 +12221,7 @@
      * counters.
      */
     @VisibleForTesting
-    public void readKernelUidCpuClusterTimesLocked() {
+    public void readKernelUidCpuClusterTimesLocked(boolean onBattery) {
         final long startTimeMs = mClocks.uptimeMillis();
         mKernelUidCpuClusterTimeReader.readDelta((uid, cpuClusterTimesUs) -> {
             uid = mapUid(uid);
@@ -12143,7 +12236,7 @@
                 return;
             }
             final Uid u = getUidStatsLocked(uid);
-            u.mCpuClusterTimesMs.addCountLocked(cpuClusterTimesUs);
+            u.mCpuClusterTimesMs.addCountLocked(cpuClusterTimesUs, onBattery);
         });
 
         final long elapsedTimeMs = mClocks.uptimeMillis() - startTimeMs;
@@ -12166,6 +12259,7 @@
         return false;
     }
 
+    @GuardedBy("this")
     protected void setOnBatteryLocked(final long mSecRealtime, final long mSecUptime,
             final boolean onBattery, final int oldStatus, final int level, final int chargeUAh) {
         boolean doWrite = false;
@@ -12307,7 +12401,7 @@
             boolean reset) {
         mRecordingHistory = true;
         mHistoryCur.currentTime = System.currentTimeMillis();
-        addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs,
+        addHistoryBufferLocked(elapsedRealtimeMs,
                 reset ? HistoryItem.CMD_RESET : HistoryItem.CMD_CURRENT_TIME,
                 mHistoryCur);
         mHistoryCur.currentTime = 0;
@@ -12320,8 +12414,7 @@
             final long uptimeMs) {
         if (mRecordingHistory) {
             mHistoryCur.currentTime = currentTime;
-            addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.CMD_CURRENT_TIME,
-                    mHistoryCur);
+            addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_CURRENT_TIME, mHistoryCur);
             mHistoryCur.currentTime = 0;
         }
     }
@@ -12329,8 +12422,7 @@
     private void recordShutdownLocked(final long elapsedRealtimeMs, final long uptimeMs) {
         if (mRecordingHistory) {
             mHistoryCur.currentTime = System.currentTimeMillis();
-            addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.CMD_SHUTDOWN,
-                    mHistoryCur);
+            addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_SHUTDOWN, mHistoryCur);
             mHistoryCur.currentTime = 0;
         }
     }
@@ -12344,6 +12436,7 @@
     // This should probably be exposed in the API, though it's not critical
     public static final int BATTERY_PLUGGED_NONE = OsProtoEnums.BATTERY_PLUGGED_NONE; // = 0
 
+    @GuardedBy("this")
     public void setBatteryStateLocked(final int status, final int health, final int plugType,
             final int level, /* not final */ int temp, final int volt, final int chargeUAh,
             final int chargeFullUAh) {
@@ -12353,9 +12446,7 @@
         reportChangesToStatsLog(mHaveBatteryLevel ? mHistoryCur : null,
                 status, plugType, level, temp);
 
-        final boolean onBattery =
-            plugType == BATTERY_PLUGGED_NONE &&
-            status != BatteryManager.BATTERY_STATUS_UNKNOWN;
+        final boolean onBattery = isOnBattery(plugType, status);
         final long uptime = mClocks.uptimeMillis();
         final long elapsedRealtime = mClocks.elapsedRealtime();
         if (!mHaveBatteryLevel) {
@@ -12545,6 +12636,10 @@
         mMaxLearnedBatteryCapacity = Math.max(mMaxLearnedBatteryCapacity, chargeFullUAh);
     }
 
+    public static boolean isOnBattery(int plugType, int status) {
+        return plugType == BATTERY_PLUGGED_NONE && status != BatteryManager.BATTERY_STATUS_UNKNOWN;
+    }
+
     // Inform StatsLog of setBatteryState changes.
     // If this is the first reporting, pass in recentPast == null.
     private void reportChangesToStatsLog(HistoryItem recentPast,
@@ -13089,15 +13184,19 @@
                 = "track_cpu_active_cluster_time";
         public static final String KEY_READ_BINARY_CPU_TIME
                 = "read_binary_cpu_time";
+        public static final String KEY_PROC_STATE_CPU_TIMES_READ_DELAY_MS
+                = "proc_state_cpu_times_read_delay_ms";
 
         private static final boolean DEFAULT_TRACK_CPU_TIMES_BY_PROC_STATE = true;
         private static final boolean DEFAULT_TRACK_CPU_ACTIVE_CLUSTER_TIME = true;
         private static final boolean DEFAULT_READ_BINARY_CPU_TIME = false;
+        private static final long DEFAULT_PROC_STATE_CPU_TIMES_READ_DELAY_MS = 5_000;
 
         public boolean TRACK_CPU_TIMES_BY_PROC_STATE = DEFAULT_TRACK_CPU_TIMES_BY_PROC_STATE;
         public boolean TRACK_CPU_ACTIVE_CLUSTER_TIME = DEFAULT_TRACK_CPU_ACTIVE_CLUSTER_TIME;
         // Not used right now.
         public boolean READ_BINARY_CPU_TIME = DEFAULT_READ_BINARY_CPU_TIME;
+        public long PROC_STATE_CPU_TIMES_READ_DELAY_MS = DEFAULT_PROC_STATE_CPU_TIMES_READ_DELAY_MS;
 
         private ContentResolver mResolver;
         private final KeyValueListParser mParser = new KeyValueListParser(',');
@@ -13137,7 +13236,9 @@
                         KEY_TRACK_CPU_ACTIVE_CLUSTER_TIME, DEFAULT_TRACK_CPU_ACTIVE_CLUSTER_TIME);
                 READ_BINARY_CPU_TIME = mParser.getBoolean(
                         KEY_READ_BINARY_CPU_TIME, DEFAULT_READ_BINARY_CPU_TIME);
-
+                updateProcStateCpuTimesReadDelayMs(PROC_STATE_CPU_TIMES_READ_DELAY_MS,
+                        mParser.getLong(KEY_PROC_STATE_CPU_TIMES_READ_DELAY_MS,
+                        DEFAULT_PROC_STATE_CPU_TIMES_READ_DELAY_MS));
             }
         }
 
@@ -13146,6 +13247,19 @@
             if (isEnabled && !wasEnabled) {
                 mKernelSingleUidTimeReader.markDataAsStale(true);
                 mExternalSync.scheduleCpuSyncDueToSettingChange();
+
+                mNumCpuTimeReads = 0;
+                mNumBatchedCpuTimeReads = 0;
+                mCpuTimeReadsTrackingStartTime = mClocks.uptimeMillis();
+            }
+        }
+
+        private void updateProcStateCpuTimesReadDelayMs(long oldDelayMillis, long newDelayMillis) {
+            PROC_STATE_CPU_TIMES_READ_DELAY_MS = newDelayMillis;
+            if (oldDelayMillis != newDelayMillis) {
+                mNumCpuTimeReads = 0;
+                mNumBatchedCpuTimeReads = 0;
+                mCpuTimeReadsTrackingStartTime = mClocks.uptimeMillis();
             }
         }
 
@@ -13156,9 +13270,12 @@
             pw.println(TRACK_CPU_ACTIVE_CLUSTER_TIME);
             pw.print(KEY_READ_BINARY_CPU_TIME); pw.print("=");
             pw.println(READ_BINARY_CPU_TIME);
+            pw.print(KEY_PROC_STATE_CPU_TIMES_READ_DELAY_MS); pw.print("=");
+            pw.println(PROC_STATE_CPU_TIMES_READ_DELAY_MS);
         }
     }
 
+    @GuardedBy("this")
     public void dumpConstantsLocked(PrintWriter pw) {
         mConstants.dumpLocked(pw);
     }
@@ -13274,7 +13391,7 @@
             if (USE_OLD_HISTORY) {
                 addHistoryRecordLocked(elapsedRealtime, uptime, HistoryItem.CMD_START, mHistoryCur);
             }
-            addHistoryBufferLocked(elapsedRealtime, uptime, HistoryItem.CMD_START, mHistoryCur);
+            addHistoryBufferLocked(elapsedRealtime, HistoryItem.CMD_START, mHistoryCur);
             startRecordingHistory(elapsedRealtime, uptime, false);
         }
 
@@ -13542,6 +13659,7 @@
         mCameraOnTimer.readSummaryFromParcelLocked(in);
         mBluetoothScanNesting = 0;
         mBluetoothScanTimer.readSummaryFromParcelLocked(in);
+        mIsCellularTxPowerHigh = false;
 
         int NRPMS = in.readInt();
         if (NRPMS > 10000) {
@@ -14478,6 +14596,7 @@
         mCameraOnTimer = new StopwatchTimer(mClocks, null, -13, null, mOnBatteryTimeBase, in);
         mBluetoothScanNesting = 0;
         mBluetoothScanTimer = new StopwatchTimer(mClocks, null, -14, null, mOnBatteryTimeBase, in);
+        mIsCellularTxPowerHigh = false;
         mDischargeUnplugLevel = in.readInt();
         mDischargePlugLevel = in.readInt();
         mDischargeCurrentLevel = in.readInt();
@@ -14862,5 +14981,11 @@
             mCameraOnTimer.logState(pr, "  ");
         }
         super.dumpLocked(context, pw, flags, reqUid, histStart);
+        pw.print("Total cpu time reads: ");
+        pw.println(mNumCpuTimeReads);
+        pw.print("Batched cpu time reads: ");
+        pw.println(mNumBatchedCpuTimeReads);
+        pw.print("Batching Duration (min): ");
+        pw.println((mClocks.uptimeMillis() - mCpuTimeReadsTrackingStartTime) / (60 * 1000));
     }
 }
diff --git a/core/java/com/android/internal/os/FuseAppLoop.java b/core/java/com/android/internal/os/FuseAppLoop.java
index 088e726..12405eb 100644
--- a/core/java/com/android/internal/os/FuseAppLoop.java
+++ b/core/java/com/android/internal/os/FuseAppLoop.java
@@ -283,6 +283,7 @@
         return -OsConstants.EBADF;
     }
 
+    @GuardedBy("mLock")
     private CallbackEntry getCallbackEntryOrThrowLocked(long inode) throws ErrnoException {
         final CallbackEntry entry = mCallbackMap.get(checkInode(inode));
         if (entry == null) {
@@ -291,12 +292,14 @@
         return entry;
     }
 
+    @GuardedBy("mLock")
     private void recycleLocked(Args args) {
         if (mArgsPool.size() < ARGS_POOL_SIZE) {
             mArgsPool.add(args);
         }
     }
 
+    @GuardedBy("mLock")
     private void replySimpleLocked(long unique, int result) {
         if (mInstance != 0) {
             native_replySimple(mInstance, unique, result);
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..bb5a0ad 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();
@@ -229,7 +230,7 @@
      * @param argv Argument vector for main()
      * @param classLoader the classLoader to load {@className} with
      */
-    private static Runnable findStaticMain(String className, String[] argv,
+    protected static Runnable findStaticMain(String className, String[] argv,
             ClassLoader classLoader) {
         Class<?> cl;
 
diff --git a/core/java/com/android/internal/os/WebViewZygoteInit.java b/core/java/com/android/internal/os/WebViewZygoteInit.java
index cadb66a..b38c851 100644
--- a/core/java/com/android/internal/os/WebViewZygoteInit.java
+++ b/core/java/com/android/internal/os/WebViewZygoteInit.java
@@ -129,7 +129,7 @@
 
         final Runnable caller;
         try {
-            sServer.registerServerSocket("webview_zygote");
+            sServer.registerServerSocketFromEnv("webview_zygote");
             // The select loop returns early in the child process after a fork and
             // loops forever in the zygote.
             caller = sServer.runSelectLoop(TextUtils.join(",", Build.SUPPORTED_ABIS));
diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java
index e69a360..28a7c12 100644
--- a/core/java/com/android/internal/os/Zygote.java
+++ b/core/java/com/android/internal/os/Zygote.java
@@ -53,8 +53,8 @@
     public static final int DISABLE_VERIFIER = 1 << 9;
     /** Only use oat files located in /system. Otherwise use dex/jar/apk . */
     public static final int ONLY_USE_SYSTEM_OAT_FILES = 1 << 10;
-    /** Do not enfore hidden API access restrictions. */
-    public static final int DISABLE_HIDDEN_API_CHECKS = 1 << 11;
+    /** Do enfore hidden API access restrictions. */
+    public static final int ENABLE_HIDDEN_API_CHECKS = 1 << 11;
     /** Force generation of native debugging information for backtraces. */
     public static final int DEBUG_GENERATE_MINI_DEBUG_INFO = 1 << 12;
 
@@ -69,6 +69,13 @@
 
     private static final ZygoteHooks VM_HOOKS = new ZygoteHooks();
 
+    /**
+     * An extraArg passed when a zygote process is forking a child-zygote, specifying a name
+     * in the abstract socket namespace. This socket name is what the new child zygote
+     * should listen for connections on.
+     */
+    public static final String CHILD_ZYGOTE_SOCKET_NAME_ARG = "--zygote-socket=";
+
     private Zygote() {}
 
     /** Called for some security initialization before any fork. */
@@ -100,6 +107,8 @@
      * @param fdsToIgnore null-ok an array of ints, either null or holding
      * one or more POSIX file descriptor numbers that are to be ignored
      * in the file descriptor table check.
+     * @param startChildZygote if true, the new child process will itself be a
+     * new zygote process.
      * @param instructionSet null-ok the instruction set to use.
      * @param appDataDir null-ok the data directory of the app.
      *
@@ -108,13 +117,13 @@
      */
     public static int forkAndSpecialize(int uid, int gid, int[] gids, int runtimeFlags,
           int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,
-          int[] fdsToIgnore, String instructionSet, String appDataDir) {
+          int[] fdsToIgnore, boolean startChildZygote, String instructionSet, String appDataDir) {
         VM_HOOKS.preFork();
         // Resets nice priority for zygote process.
         resetNicePriority();
         int pid = nativeForkAndSpecialize(
                   uid, gid, gids, runtimeFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose,
-                  fdsToIgnore, instructionSet, appDataDir);
+                  fdsToIgnore, startChildZygote, instructionSet, appDataDir);
         // Enable tracing as soon as possible for the child process.
         if (pid == 0) {
             Trace.setTracingEnabled(true, runtimeFlags);
@@ -128,7 +137,7 @@
 
     native private static int nativeForkAndSpecialize(int uid, int gid, int[] gids,int runtimeFlags,
           int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,
-          int[] fdsToIgnore, String instructionSet, String appDataDir);
+          int[] fdsToIgnore, boolean startChildZygote, String instructionSet, String appDataDir);
 
     /**
      * Called to do any initialization before starting an application.
@@ -160,9 +169,6 @@
      */
     public static int forkSystemServer(int uid, int gid, int[] gids, int runtimeFlags,
             int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {
-        // SystemServer is always allowed to use hidden APIs.
-        runtimeFlags |= DISABLE_HIDDEN_API_CHECKS;
-
         VM_HOOKS.preFork();
         // Resets nice priority for zygote process.
         resetNicePriority();
@@ -191,8 +197,8 @@
     native protected static void nativeUnmountStorageOnInit();
 
     private static void callPostForkChildHooks(int runtimeFlags, boolean isSystemServer,
-            String instructionSet) {
-        VM_HOOKS.postForkChild(runtimeFlags, isSystemServer, instructionSet);
+            boolean isZygote, String instructionSet) {
+        VM_HOOKS.postForkChild(runtimeFlags, isSystemServer, isZygote, instructionSet);
     }
 
     /**
diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java
index 6a87b1f..a32fb43 100644
--- a/core/java/com/android/internal/os/ZygoteConnection.java
+++ b/core/java/com/android/internal/os/ZygoteConnection.java
@@ -221,8 +221,8 @@
 
         pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
                 parsedArgs.runtimeFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
-                parsedArgs.niceName, fdsToClose, fdsToIgnore, parsedArgs.instructionSet,
-                parsedArgs.appDataDir);
+                parsedArgs.niceName, fdsToClose, fdsToIgnore, parsedArgs.startChildZygote,
+                parsedArgs.instructionSet, parsedArgs.appDataDir);
 
         try {
             if (pid == 0) {
@@ -233,7 +233,8 @@
                 IoUtils.closeQuietly(serverPipeFd);
                 serverPipeFd = null;
 
-                return handleChildProc(parsedArgs, descriptors, childPipeFd);
+                return handleChildProc(parsedArgs, descriptors, childPipeFd,
+                        parsedArgs.startChildZygote);
             } else {
                 // In the parent. A pid < 0 indicates a failure and will be handled in
                 // handleParentProc.
@@ -415,6 +416,14 @@
         boolean preloadDefault;
 
         /**
+         * Whether this is a request to start a zygote process as a child of this zygote.
+         * Set with --start-child-zygote. The remaining arguments must include the
+         * CHILD_ZYGOTE_SOCKET_NAME_ARG flag to indicate the abstract socket name that
+         * should be used for communication.
+         */
+        boolean startChildZygote;
+
+        /**
          * Constructs instance and parses args
          * @param args zygote command-line args
          * @throws IllegalArgumentException
@@ -565,6 +574,8 @@
                     preloadPackageCacheKey = args[++curArg];
                 } else if (arg.equals("--preload-default")) {
                     preloadDefault = true;
+                } else if (arg.equals("--start-child-zygote")) {
+                    startChildZygote = true;
                 } else {
                     break;
                 }
@@ -587,6 +598,20 @@
                 remainingArgs = new String[args.length - curArg];
                 System.arraycopy(args, curArg, remainingArgs, 0, remainingArgs.length);
             }
+
+            if (startChildZygote) {
+                boolean seenChildSocketArg = false;
+                for (String arg : remainingArgs) {
+                    if (arg.startsWith(Zygote.CHILD_ZYGOTE_SOCKET_NAME_ARG)) {
+                        seenChildSocketArg = true;
+                        break;
+                    }
+                }
+                if (!seenChildSocketArg) {
+                    throw new IllegalArgumentException("--start-child-zygote specified " +
+                            "without " + Zygote.CHILD_ZYGOTE_SOCKET_NAME_ARG);
+                }
+            }
         }
     }
 
@@ -739,9 +764,10 @@
      * @param parsedArgs non-null; zygote args
      * @param descriptors null-ok; new file descriptors for stdio if available.
      * @param pipeFd null-ok; pipe for communication back to Zygote.
+     * @param isZygote whether this new child process is itself a new Zygote.
      */
     private Runnable handleChildProc(Arguments parsedArgs, FileDescriptor[] descriptors,
-            FileDescriptor pipeFd) {
+            FileDescriptor pipeFd, boolean isZygote) {
         /**
          * By the time we get here, the native code has closed the two actual Zygote
          * socket connections, and substituted /dev/null in their place.  The LocalSocket
@@ -778,8 +804,13 @@
             // Should not get here.
             throw new IllegalStateException("WrapperInit.execApplication unexpectedly returned");
         } else {
-            return ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs,
-                    null /* classLoader */);
+            if (!isZygote) {
+                return ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs,
+                        null /* classLoader */);
+            } else {
+                return ZygoteInit.childZygoteInit(parsedArgs.targetSdkVersion,
+                        parsedArgs.remainingArgs, null /* classLoader */);
+            }
         }
     }
 
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 74802c8..c5d0a04 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -98,10 +98,6 @@
 
     private static final String SOCKET_NAME_ARG = "--socket-name=";
 
-    /* Dexopt flag to disable hidden API access checks when dexopting SystemServer.
-     * Must be kept in sync with com.android.server.pm.Installer. */
-    private static final int DEXOPT_DISABLE_HIDDEN_API_CHECKS = 1 << 10;
-
     /**
      * Used to pre-load resources.
      */
@@ -569,10 +565,7 @@
             if (dexoptNeeded != DexFile.NO_DEXOPT_NEEDED) {
                 final String packageName = "*";
                 final String outputPath = null;
-                // Dexopt with a flag which lifts restrictions on hidden API usage.
-                // Offending methods would otherwise be re-verified at runtime and
-                // we want to avoid the performance overhead of that.
-                final int dexFlags = DEXOPT_DISABLE_HIDDEN_API_CHECKS;
+                final int dexFlags = 0;
                 final String compilerFilter = systemServerFilter;
                 final String uuid = StorageManager.UUID_PRIVATE_INTERNAL;
                 final String seInfo = null;
@@ -583,7 +576,8 @@
                     installd.dexopt(classPathElement, Process.SYSTEM_UID, packageName,
                             instructionSet, dexoptNeeded, outputPath, dexFlags, compilerFilter,
                             uuid, classLoaderContext, seInfo, false /* downgrade */,
-                            targetSdkVersion, /*profileName*/ null, /*dexMetadataPath*/ null);
+                            targetSdkVersion, /*profileName*/ null, /*dexMetadataPath*/ null,
+                            "server-dexopt");
                 } catch (RemoteException | ServiceSpecificException e) {
                     // Ignore (but log), we need this on the classpath for fallback mode.
                     Log.w(TAG, "Failed compiling classpath element for system server: "
@@ -762,7 +756,7 @@
                 throw new RuntimeException("No ABI list supplied.");
             }
 
-            zygoteServer.registerServerSocket(socketName);
+            zygoteServer.registerServerSocketFromEnv(socketName);
             // In some configurations, we avoid preloading resources and classes eagerly.
             // In such cases, we will preload things prior to our first fork.
             if (!enableLazyPreload) {
@@ -877,5 +871,16 @@
         return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
     }
 
+    /**
+     * The main function called when starting a child zygote process. This is used as an
+     * alternative to zygoteInit(), which skips calling into initialization routines that
+     * start the Binder threadpool.
+     */
+    static final Runnable childZygoteInit(
+            int targetSdkVersion, String[] argv, ClassLoader classLoader) {
+        RuntimeInit.Arguments args = new RuntimeInit.Arguments(argv);
+        return RuntimeInit.findStaticMain(args.startClass, args.startArgs, classLoader);
+    }
+
     private static final native void nativeZygoteInit();
 }
diff --git a/core/java/com/android/internal/os/ZygoteServer.java b/core/java/com/android/internal/os/ZygoteServer.java
index 8baa15a..fecf9b9 100644
--- a/core/java/com/android/internal/os/ZygoteServer.java
+++ b/core/java/com/android/internal/os/ZygoteServer.java
@@ -44,9 +44,21 @@
 
     private static final String ANDROID_SOCKET_PREFIX = "ANDROID_SOCKET_";
 
+    /**
+     * Listening socket that accepts new server connections.
+     */
     private LocalServerSocket mServerSocket;
 
     /**
+     * Whether or not mServerSocket's underlying FD should be closed directly.
+     * If mServerSocket is created with an existing FD, closing the socket does
+     * not close the FD and it must be closed explicitly. If the socket is created
+     * with a name instead, then closing the socket will close the underlying FD
+     * and it should not be double-closed.
+     */
+    private boolean mCloseSocketFd;
+
+    /**
      * Set by the child process, immediately after a call to {@code Zygote.forkAndSpecialize}.
      */
     private boolean mIsForkChild;
@@ -59,11 +71,12 @@
     }
 
     /**
-     * Registers a server socket for zygote command connections
+     * Registers a server socket for zygote command connections. This locates the server socket
+     * file descriptor through an ANDROID_SOCKET_ environment variable.
      *
      * @throws RuntimeException when open fails
      */
-    void registerServerSocket(String socketName) {
+    void registerServerSocketFromEnv(String socketName) {
         if (mServerSocket == null) {
             int fileDesc;
             final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;
@@ -78,6 +91,7 @@
                 FileDescriptor fd = new FileDescriptor();
                 fd.setInt$(fileDesc);
                 mServerSocket = new LocalServerSocket(fd);
+                mCloseSocketFd = true;
             } catch (IOException ex) {
                 throw new RuntimeException(
                         "Error binding to local socket '" + fileDesc + "'", ex);
@@ -86,6 +100,22 @@
     }
 
     /**
+     * Registers a server socket for zygote command connections. This opens the server socket
+     * at the specified name in the abstract socket namespace.
+     */
+    void registerServerSocketAtAbstractName(String socketName) {
+        if (mServerSocket == null) {
+            try {
+                mServerSocket = new LocalServerSocket(socketName);
+                mCloseSocketFd = false;
+            } catch (IOException ex) {
+                throw new RuntimeException(
+                        "Error binding to abstract socket '" + socketName + "'", ex);
+            }
+        }
+    }
+
+    /**
      * Waits for and accepts a single command connection. Throws
      * RuntimeException on failure.
      */
@@ -112,7 +142,7 @@
             if (mServerSocket != null) {
                 FileDescriptor fd = mServerSocket.getFileDescriptor();
                 mServerSocket.close();
-                if (fd != null) {
+                if (fd != null && mCloseSocketFd) {
                     Os.close(fd);
                 }
             }
@@ -219,6 +249,11 @@
                             Log.e(TAG, "Caught post-fork exception in child process.", e);
                             throw e;
                         }
+                    } finally {
+                        // Reset the child flag, in the event that the child process is a child-
+                        // zygote. The flag will not be consulted this loop pass after the Runnable
+                        // is returned.
+                        mIsForkChild = false;
                     }
                 }
             }
diff --git a/core/java/com/android/internal/print/DumpUtils.java b/core/java/com/android/internal/print/DumpUtils.java
index 1916c11..f44a1d1 100644
--- a/core/java/com/android/internal/print/DumpUtils.java
+++ b/core/java/com/android/internal/print/DumpUtils.java
@@ -213,10 +213,9 @@
         PrintAttributes.MediaSize mediaSize = attributes.getMediaSize();
         if (mediaSize != null) {
             writeMediaSize(context, proto, "media_size", PrintAttributesProto.MEDIA_SIZE, mediaSize);
+            proto.write("is_portrait", PrintAttributesProto.IS_PORTRAIT, attributes.isPortrait());
         }
 
-        proto.write("is_portrait", PrintAttributesProto.IS_PORTRAIT, attributes.isPortrait());
-
         PrintAttributes.Resolution res = attributes.getResolution();
         if (res != null) {
             writeResolution(proto, "resolution", PrintAttributesProto.RESOLUTION, res);
diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl
index f70d3c2..221bf88 100644
--- a/core/java/com/android/internal/statusbar/IStatusBar.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl
@@ -35,7 +35,7 @@
     void animateCollapsePanels();
     void togglePanel();
 
-    void showChargingAnimation(int batteryLevel);
+    void showWirelessChargingAnimation(int batteryLevel);
 
     /**
      * Notifies the status bar of a System UI visibility flag change.
diff --git a/core/java/com/android/internal/util/OWNERS b/core/java/com/android/internal/util/OWNERS
new file mode 100644
index 0000000..21d750c
--- /dev/null
+++ b/core/java/com/android/internal/util/OWNERS
@@ -0,0 +1,24 @@
+per-file AsyncChannel*=lorenzo@google.com
+per-file AsyncChannel*=satk@google.com
+per-file AsyncChannel*=silberst@google.com
+per-file BitUtils*=ek@google.com
+per-file BitUtils*=lorenzo@google.com
+per-file BitUtils*=satk@google.com
+per-file MessageUtils*=ek@google.com
+per-file MessageUtils*=lorenzo@google.com
+per-file MessageUtils*=satk@google.com
+per-file Protocol*=ek@google.com
+per-file Protocol*=lorenzo@google.com
+per-file Protocol*=quiche@google.com
+per-file Protocol*=satk@google.com
+per-file Protocol*=silberst@google.com
+per-file RingBuffer*=ek@google.com
+per-file RingBuffer*=lorenzo@google.com
+per-file RingBuffer*=satk@google.com
+per-file State*=ek@google.com
+per-file State*=lorenzo@google.com
+per-file State*=quiche@google.com
+per-file State*=silberst@google.com
+per-file TokenBucket*=ek@google.com
+per-file TokenBucket*=lorenzo@google.com
+per-file TokenBucket*=satk@google.com
diff --git a/core/java/com/android/internal/view/menu/MenuBuilder.java b/core/java/com/android/internal/view/menu/MenuBuilder.java
index b53459e..67dc81a 100644
--- a/core/java/com/android/internal/view/menu/MenuBuilder.java
+++ b/core/java/com/android/internal/view/menu/MenuBuilder.java
@@ -551,6 +551,7 @@
         mPreventDispatchingItemsChanged = true;
         clear();
         clearHeader();
+        mPresenters.clear();
         mPreventDispatchingItemsChanged = false;
         mItemsChangedWhileDispatchPrevented = false;
         onItemsChanged(true);
diff --git a/core/java/com/android/internal/widget/LocalImageResolver.java b/core/java/com/android/internal/widget/LocalImageResolver.java
new file mode 100644
index 0000000..71d3bb5
--- /dev/null
+++ b/core/java/com/android/internal/widget/LocalImageResolver.java
@@ -0,0 +1,76 @@
+/*
+ * 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.internal.widget;
+
+import android.annotation.Nullable;
+import android.app.Notification;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.net.Uri;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * A class to extract Bitmaps from a MessagingStyle message.
+ */
+public class LocalImageResolver {
+
+    private static final int MAX_SAFE_ICON_SIZE_PX = 480;
+
+    @Nullable
+    public static Drawable resolveImage(Uri uri, Context context) throws IOException {
+        BitmapFactory.Options onlyBoundsOptions = getBoundsOptionsForImage(uri, context);
+        if ((onlyBoundsOptions.outWidth == -1) || (onlyBoundsOptions.outHeight == -1)) {
+            return null;
+        }
+
+        int originalSize =
+                (onlyBoundsOptions.outHeight > onlyBoundsOptions.outWidth)
+                        ? onlyBoundsOptions.outHeight
+                        : onlyBoundsOptions.outWidth;
+
+        double ratio = (originalSize > MAX_SAFE_ICON_SIZE_PX)
+                        ? (originalSize / MAX_SAFE_ICON_SIZE_PX)
+                        : 1.0;
+
+        BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();
+        bitmapOptions.inSampleSize = getPowerOfTwoForSampleRatio(ratio);
+        InputStream input = context.getContentResolver().openInputStream(uri);
+        Bitmap bitmap = BitmapFactory.decodeStream(input, null, bitmapOptions);
+        input.close();
+        return new BitmapDrawable(context.getResources(), bitmap);
+    }
+
+    private static BitmapFactory.Options getBoundsOptionsForImage(Uri uri, Context context)
+            throws IOException {
+        InputStream input = context.getContentResolver().openInputStream(uri);
+        BitmapFactory.Options onlyBoundsOptions = new BitmapFactory.Options();
+        onlyBoundsOptions.inJustDecodeBounds = true;
+        BitmapFactory.decodeStream(input, null, onlyBoundsOptions);
+        input.close();
+        return onlyBoundsOptions;
+    }
+
+    private static int getPowerOfTwoForSampleRatio(double ratio) {
+        int k = Integer.highestOneBit((int) Math.floor(ratio));
+        return Math.max(1, k);
+    }
+}
diff --git a/core/java/com/android/internal/widget/MessagingGroup.java b/core/java/com/android/internal/widget/MessagingGroup.java
index 5577d6e..239beaa 100644
--- a/core/java/com/android/internal/widget/MessagingGroup.java
+++ b/core/java/com/android/internal/widget/MessagingGroup.java
@@ -22,9 +22,12 @@
 import android.annotation.StyleRes;
 import android.app.Notification;
 import android.content.Context;
+import android.graphics.Point;
+import android.graphics.Rect;
 import android.graphics.drawable.Icon;
 import android.text.TextUtils;
 import android.util.AttributeSet;
+import android.util.DisplayMetrics;
 import android.util.Pools;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -61,6 +64,11 @@
     private boolean mIsHidingAnimated;
     private boolean mNeedsGeneratedAvatar;
     private Notification.Person mSender;
+    private boolean mAvatarsAtEnd;
+    private ViewGroup mImageContainer;
+    private MessagingImageMessage mIsolatedMessage;
+    private boolean mTransformingImages;
+    private Point mDisplaySize = new Point();
 
     public MessagingGroup(@NonNull Context context) {
         super(context);
@@ -87,6 +95,35 @@
         mSenderName = findViewById(R.id.message_name);
         mSenderName.addOnLayoutChangeListener(MessagingLayout.MESSAGING_PROPERTY_ANIMATOR);
         mAvatarView = findViewById(R.id.message_icon);
+        mImageContainer = findViewById(R.id.messaging_group_icon_container);
+        DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
+        mDisplaySize.x = displayMetrics.widthPixels;
+        mDisplaySize.y = displayMetrics.heightPixels;
+    }
+
+    public void updateClipRect() {
+        // We want to clip to the senderName if it's available, otherwise our images will come
+        // from a weird position
+        Rect clipRect;
+        if (mSenderName.getVisibility() != View.GONE && !mTransformingImages) {
+            ViewGroup parent = (ViewGroup) mSenderName.getParent();
+            int top = getDistanceFromParent(mSenderName, parent) - getDistanceFromParent(
+                    mMessageContainer, parent) + mSenderName.getHeight();
+            clipRect = new Rect(0, top, mDisplaySize.x, mDisplaySize.y);
+        } else {
+            clipRect = null;
+        }
+        mMessageContainer.setClipBounds(clipRect);
+    }
+
+    private int getDistanceFromParent(View searchedView, ViewGroup parent) {
+        int position = 0;
+        View view = searchedView;
+        while(view != parent) {
+            position += view.getTop() + view.getTranslationY();
+            view = (View) view.getParent();
+        }
+        return position;
     }
 
     public void setSender(Notification.Person sender, CharSequence nameOverride) {
@@ -129,12 +166,14 @@
     }
 
     public void removeMessage(MessagingMessage messagingMessage) {
-        mMessageContainer.removeView(messagingMessage);
+        ViewGroup messageParent = (ViewGroup) messagingMessage.getView().getParent();
+        messageParent.removeView(messagingMessage.getView());
         Runnable recycleRunnable = () -> {
-            mMessageContainer.removeTransientView(messagingMessage);
+            messageParent.removeTransientView(messagingMessage.getView());
             messagingMessage.recycle();
             if (mMessageContainer.getChildCount() == 0
-                    && mMessageContainer.getTransientViewCount() == 0) {
+                    && mMessageContainer.getTransientViewCount() == 0
+                    && mImageContainer.getChildCount() == 0) {
                 ViewParent parent = getParent();
                 if (parent instanceof ViewGroup) {
                     ((ViewGroup) parent).removeView(MessagingGroup.this);
@@ -148,9 +187,10 @@
             }
         };
         if (isShown()) {
-            mMessageContainer.addTransientView(messagingMessage, 0);
-            performRemoveAnimation(messagingMessage, recycleRunnable);
-            if (mMessageContainer.getChildCount() == 0) {
+            messageParent.addTransientView(messagingMessage.getView(), 0);
+            performRemoveAnimation(messagingMessage.getView(), recycleRunnable);
+            if (mMessageContainer.getChildCount() == 0
+                    && mImageContainer.getChildCount() == 0) {
                 removeGroupAnimated(null);
             }
         } else {
@@ -160,12 +200,8 @@
     }
 
     private void removeGroupAnimated(Runnable endAction) {
-        MessagingPropertyAnimator.fadeOut(mAvatarView, null);
-        MessagingPropertyAnimator.startLocalTranslationTo(mAvatarView,
-                (int) (-getHeight() * 0.5f), MessagingLayout.FAST_OUT_LINEAR_IN);
-        MessagingPropertyAnimator.fadeOut(mSenderName, null);
-        MessagingPropertyAnimator.startLocalTranslationTo(mSenderName,
-                (int) (-getHeight() * 0.5f), MessagingLayout.FAST_OUT_LINEAR_IN);
+        performRemoveAnimation(mAvatarView, null);
+        performRemoveAnimation(mSenderName, null);
         boolean endActionTriggered = false;
         for (int i = mMessageContainer.getChildCount() - 1; i >= 0; i--) {
             View child = mMessageContainer.getChildAt(i);
@@ -182,14 +218,17 @@
             performRemoveAnimation(child, childEndAction);
             endActionTriggered = true;
         }
+        if (mIsolatedMessage != null) {
+            performRemoveAnimation(mIsolatedMessage, !endActionTriggered ? endAction : null);
+            endActionTriggered = true;
+        }
         if (!endActionTriggered && endAction != null) {
             endAction.run();
         }
     }
 
-    public void performRemoveAnimation(View message,
-            Runnable recycleRunnable) {
-        MessagingPropertyAnimator.fadeOut(message, recycleRunnable);
+    public void performRemoveAnimation(View message, Runnable endAction) {
+        MessagingPropertyAnimator.fadeOut(message, endAction);
         MessagingPropertyAnimator.startLocalTranslationTo(message,
                 (int) (-getHeight() * 0.5f), MessagingLayout.FAST_OUT_LINEAR_IN);
     }
@@ -222,6 +261,9 @@
                 }
             }
         }
+        if (mMessageContainer.getChildCount() == 0 && mIsolatedMessage != null) {
+            return mIsolatedMessage.getMeasuredType();
+        }
         return MEASURED_NORMAL;
     }
 
@@ -234,6 +276,7 @@
                 result += ((MessagingLinearLayout.MessagingChild) child).getConsumedLines();
             }
         }
+        result = mIsolatedMessage != null ? Math.max(result, 1) : result;
         // A group is usually taking up quite some space with the padding and the name, let's add 1
         return result + 1;
     }
@@ -289,26 +332,67 @@
 
     public void setMessages(List<MessagingMessage> group) {
         // Let's now make sure all children are added and in the correct order
+        int textMessageIndex = 0;
+        MessagingImageMessage isolatedMessage = null;
         for (int messageIndex = 0; messageIndex < group.size(); messageIndex++) {
             MessagingMessage message = group.get(messageIndex);
+            message.setColor(mTextColor);
             if (message.getGroup() != this) {
                 message.setMessagingGroup(this);
-                ViewParent parent = mMessageContainer.getParent();
-                if (parent instanceof ViewGroup) {
-                    ((ViewGroup) parent).removeView(message);
-                }
-                mMessageContainer.addView(message, messageIndex);
                 mAddedMessages.add(message);
             }
-            if (messageIndex != mMessageContainer.indexOfChild(message)) {
-                mMessageContainer.removeView(message);
-                mMessageContainer.addView(message, messageIndex);
+            boolean isImage = message instanceof MessagingImageMessage;
+            if (mAvatarsAtEnd && isImage) {
+                isolatedMessage = (MessagingImageMessage) message;
+            } else {
+                if (removeFromParentIfDifferent(message, mMessageContainer)) {
+                    ViewGroup.LayoutParams layoutParams = message.getView().getLayoutParams();
+                    if (layoutParams != null
+                            && !(layoutParams instanceof MessagingLinearLayout.LayoutParams)) {
+                        message.getView().setLayoutParams(
+                                mMessageContainer.generateDefaultLayoutParams());
+                    }
+                    mMessageContainer.addView(message.getView(), textMessageIndex);
+                }
+                if (isImage) {
+                    ((MessagingImageMessage) message).setIsolated(false);
+                }
+                // Let's sort them properly
+                if (textMessageIndex != mMessageContainer.indexOfChild(message.getView())) {
+                    mMessageContainer.removeView(message.getView());
+                    mMessageContainer.addView(message.getView(), textMessageIndex);
+                }
+                textMessageIndex++;
             }
-            message.setTextColor(mTextColor);
         }
+        if (isolatedMessage != null) {
+            if (removeFromParentIfDifferent(isolatedMessage, mImageContainer)) {
+                mImageContainer.removeAllViews();
+                mImageContainer.addView(isolatedMessage.getView());
+            }
+            isolatedMessage.setIsolated(true);
+        } else if (mIsolatedMessage != null) {
+            mImageContainer.removeAllViews();
+        }
+        mIsolatedMessage = isolatedMessage;
         mMessages = group;
     }
 
+    /**
+     * Remove the message from the parent if the parent isn't the one provided
+     * @return whether the message was removed
+     */
+    private boolean removeFromParentIfDifferent(MessagingMessage message, ViewGroup newParent) {
+        ViewParent parent = message.getView().getParent();
+        if (parent != newParent) {
+            if (parent instanceof ViewGroup) {
+                ((ViewGroup) parent).removeView(message.getView());
+            }
+            return true;
+        }
+        return false;
+    }
+
     @Override
     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
         super.onLayout(changed, left, top, right, bottom);
@@ -317,13 +401,14 @@
                 @Override
                 public boolean onPreDraw() {
                     for (MessagingMessage message : mAddedMessages) {
-                        if (!message.isShown()) {
+                        if (!message.getView().isShown()) {
                             continue;
                         }
-                        MessagingPropertyAnimator.fadeIn(message);
+                        MessagingPropertyAnimator.fadeIn(message.getView());
                         if (!mFirstLayout) {
-                            MessagingPropertyAnimator.startLocalTranslationFrom(message,
-                                    message.getHeight(), MessagingLayout.LINEAR_OUT_SLOW_IN);
+                            MessagingPropertyAnimator.startLocalTranslationFrom(message.getView(),
+                                    message.getView().getHeight(),
+                                    MessagingLayout.LINEAR_OUT_SLOW_IN);
                         }
                     }
                     mAddedMessages.clear();
@@ -333,6 +418,7 @@
             });
         }
         mFirstLayout = false;
+        updateClipRect();
     }
 
     /**
@@ -372,6 +458,10 @@
         return mMessageContainer;
     }
 
+    public MessagingImageMessage getIsolatedMessage() {
+        return mIsolatedMessage;
+    }
+
     public boolean needsGeneratedAvatar() {
         return mNeedsGeneratedAvatar;
     }
@@ -379,4 +469,19 @@
     public Notification.Person getSender() {
         return mSender;
     }
+
+    public void setTransformingImages(boolean transformingImages) {
+        mTransformingImages = transformingImages;
+    }
+
+    public void setDisplayAvatarsAtEnd(boolean atEnd) {
+        if (mAvatarsAtEnd != atEnd) {
+            mAvatarsAtEnd = atEnd;
+            mImageContainer.setVisibility(atEnd ? View.VISIBLE : View.GONE);
+        }
+    }
+
+    public List<MessagingMessage> getMessages() {
+        return mMessages;
+    }
 }
diff --git a/core/java/com/android/internal/widget/MessagingImageMessage.java b/core/java/com/android/internal/widget/MessagingImageMessage.java
new file mode 100644
index 0000000..961f90a
--- /dev/null
+++ b/core/java/com/android/internal/widget/MessagingImageMessage.java
@@ -0,0 +1,273 @@
+/*
+ * 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.internal.widget;
+
+import android.annotation.AttrRes;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.StyleRes;
+import android.app.Notification;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Path;
+import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.util.Pools;
+import android.view.LayoutInflater;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.RemoteViews;
+
+import com.android.internal.R;
+
+import java.io.IOException;
+
+/**
+ * A message of a {@link MessagingLayout} that is an image.
+ */
+@RemoteViews.RemoteView
+public class MessagingImageMessage extends ImageView implements MessagingMessage {
+    private static final String TAG = "MessagingImageMessage";
+    private static Pools.SimplePool<MessagingImageMessage> sInstancePool
+            = new Pools.SynchronizedPool<>(10);
+    private final MessagingMessageState mState = new MessagingMessageState(this);
+    private final int mMinImageHeight;
+    private final Path mPath = new Path();
+    private final int mImageRounding;
+    private final int mMaxImageHeight;
+    private final int mIsolatedSize;
+    private final int mExtraSpacing;
+    private Drawable mDrawable;
+    private float mAspectRatio;
+    private int mActualWidth;
+    private int mActualHeight;
+    private boolean mIsIsolated;
+
+    public MessagingImageMessage(@NonNull Context context) {
+        this(context, null);
+    }
+
+    public MessagingImageMessage(@NonNull Context context, @Nullable AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public MessagingImageMessage(@NonNull Context context, @Nullable AttributeSet attrs,
+            @AttrRes int defStyleAttr) {
+        this(context, attrs, defStyleAttr, 0);
+    }
+
+    public MessagingImageMessage(@NonNull Context context, @Nullable AttributeSet attrs,
+            @AttrRes int defStyleAttr, @StyleRes int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+        mMinImageHeight = context.getResources().getDimensionPixelSize(
+                com.android.internal.R.dimen.messaging_image_min_size);
+        mMaxImageHeight = context.getResources().getDimensionPixelSize(
+                com.android.internal.R.dimen.messaging_image_max_height);
+        mImageRounding = context.getResources().getDimensionPixelSize(
+                com.android.internal.R.dimen.messaging_image_rounding);
+        mExtraSpacing = context.getResources().getDimensionPixelSize(
+                com.android.internal.R.dimen.messaging_image_extra_spacing);
+        setMaxHeight(mMaxImageHeight);
+        mIsolatedSize = getResources().getDimensionPixelSize(R.dimen.messaging_avatar_size);
+    }
+
+    @Override
+    public MessagingMessageState getState() {
+        return mState;
+    }
+
+    @Override
+    public boolean setMessage(Notification.MessagingStyle.Message message) {
+        MessagingMessage.super.setMessage(message);
+        Drawable drawable;
+        try {
+            drawable = LocalImageResolver.resolveImage(message.getDataUri(), getContext());
+        } catch (IOException e) {
+            e.printStackTrace();
+            return false;
+        }
+        int intrinsicHeight = drawable.getIntrinsicHeight();
+        if (intrinsicHeight == 0) {
+            Log.w(TAG, "Drawable with 0 intrinsic height was returned");
+            return false;
+        }
+        mDrawable = drawable;
+        mAspectRatio = ((float) mDrawable.getIntrinsicWidth()) / intrinsicHeight;
+        setImageDrawable(drawable);
+        setContentDescription(message.getText());
+        return true;
+    }
+
+    static MessagingMessage createMessage(MessagingLayout layout,
+            Notification.MessagingStyle.Message m) {
+        MessagingLinearLayout messagingLinearLayout = layout.getMessagingLinearLayout();
+        MessagingImageMessage createdMessage = sInstancePool.acquire();
+        if (createdMessage == null) {
+            createdMessage = (MessagingImageMessage) LayoutInflater.from(
+                    layout.getContext()).inflate(
+                            R.layout.notification_template_messaging_image_message,
+                            messagingLinearLayout,
+                            false);
+            createdMessage.addOnLayoutChangeListener(MessagingLayout.MESSAGING_PROPERTY_ANIMATOR);
+        }
+        boolean created = createdMessage.setMessage(m);
+        if (!created) {
+            createdMessage.recycle();
+            return MessagingTextMessage.createMessage(layout, m);
+        }
+        return createdMessage;
+    }
+
+    @Override
+    protected void onDraw(Canvas canvas) {
+        canvas.save();
+        canvas.clipPath(getRoundedRectPath());
+        int width = (int) Math.max(getActualWidth(), getActualHeight() * mAspectRatio);
+        int height = (int) (width / mAspectRatio);
+        int left = (int) ((getActualWidth() - width) / 2.0f);
+        mDrawable.setBounds(left, 0, left + width, height);
+        mDrawable.draw(canvas);
+        canvas.restore();
+    }
+
+    public Path getRoundedRectPath() {
+        int left = 0;
+        int right = getActualWidth();
+        int top = 0;
+        int bottom = getActualHeight();
+        mPath.reset();
+        int width = right - left;
+        float roundnessX = mImageRounding;
+        float roundnessY = mImageRounding;
+        roundnessX = Math.min(width / 2, roundnessX);
+        roundnessY = Math.min((bottom - top) / 2, roundnessY);
+        mPath.moveTo(left, top + roundnessY);
+        mPath.quadTo(left, top, left + roundnessX, top);
+        mPath.lineTo(right - roundnessX, top);
+        mPath.quadTo(right, top, right, top + roundnessY);
+        mPath.lineTo(right, bottom - roundnessY);
+        mPath.quadTo(right, bottom, right - roundnessX, bottom);
+        mPath.lineTo(left + roundnessX, bottom);
+        mPath.quadTo(left, bottom, left, bottom - roundnessY);
+        mPath.close();
+        return mPath;
+    }
+
+    public void recycle() {
+        MessagingMessage.super.recycle();
+        setAlpha(1.0f);
+        setTranslationY(0);
+        setImageBitmap(null);
+        mDrawable = null;
+        sInstancePool.release(this);
+    }
+
+    public static void dropCache() {
+        sInstancePool = new Pools.SynchronizedPool<>(10);
+    }
+
+    @Override
+    public int getMeasuredType() {
+        int measuredHeight = getMeasuredHeight();
+        int minImageHeight;
+        if (mIsIsolated) {
+            minImageHeight = mIsolatedSize;
+        } else {
+            minImageHeight = mMinImageHeight;
+        }
+        boolean measuredTooSmall = measuredHeight < minImageHeight
+                && measuredHeight != mDrawable.getIntrinsicHeight();
+        if (measuredTooSmall) {
+            return MEASURED_TOO_SMALL;
+        } else {
+            if (!mIsIsolated && measuredHeight != mDrawable.getIntrinsicHeight()) {
+                return MEASURED_SHORTENED;
+            } else {
+                return MEASURED_NORMAL;
+            }
+        }
+    }
+
+    @Override
+    public void setMaxDisplayedLines(int lines) {
+        // Nothing to do, this should be handled automatically.
+    }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+        if (mIsIsolated) {
+            setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec),
+                    MeasureSpec.getSize(heightMeasureSpec));
+        }
+    }
+
+    @Override
+    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+        super.onLayout(changed, left, top, right, bottom);
+        // TODO: ensure that this isn't called when transforming
+        setActualWidth(getStaticWidth());
+        setActualHeight(getHeight());
+    }
+
+    @Override
+    public int getConsumedLines() {
+        return 3;
+    }
+
+    public void setActualWidth(int actualWidth) {
+        mActualWidth = actualWidth;
+        invalidate();
+    }
+
+    public int getActualWidth() {
+        return mActualWidth;
+    }
+
+    public void setActualHeight(int actualHeight) {
+        mActualHeight = actualHeight;
+        invalidate();
+    }
+
+    public int getActualHeight() {
+        return mActualHeight;
+    }
+
+    public int getStaticWidth() {
+        if (mIsIsolated) {
+            return getWidth();
+        }
+        return (int) (getHeight() * mAspectRatio);
+    }
+
+    public void setIsolated(boolean isolated) {
+        if (mIsIsolated != isolated) {
+            mIsIsolated = isolated;
+            // update the layout params not to have margins
+            ViewGroup.MarginLayoutParams layoutParams =
+                    (ViewGroup.MarginLayoutParams) getLayoutParams();
+            layoutParams.topMargin = isolated ? 0 : mExtraSpacing;
+            setLayoutParams(layoutParams);
+        }
+    }
+
+    @Override
+    public int getExtraSpacing() {
+        return mExtraSpacing;
+    }
+}
diff --git a/core/java/com/android/internal/widget/MessagingLayout.java b/core/java/com/android/internal/widget/MessagingLayout.java
index d45c086..5279636 100644
--- a/core/java/com/android/internal/widget/MessagingLayout.java
+++ b/core/java/com/android/internal/widget/MessagingLayout.java
@@ -81,6 +81,7 @@
     private ArrayList<MessagingGroup> mAddedGroups = new ArrayList<>();
     private Notification.Person mUser;
     private CharSequence mNameReplacement;
+    private boolean mIsCollapsed;
 
     public MessagingLayout(@NonNull Context context) {
         super(context);
@@ -127,6 +128,11 @@
     }
 
     @RemotableViewMethod
+    public void setIsCollapsed(boolean isCollapsed) {
+        mIsCollapsed = isCollapsed;
+    }
+
+    @RemotableViewMethod
     public void setData(Bundle extras) {
         Parcelable[] messages = extras.getParcelableArray(Notification.EXTRA_MESSAGES);
         List<Notification.MessagingStyle.Message> newMessages
@@ -331,6 +337,7 @@
                 newGroup = MessagingGroup.createGroup(mMessagingLinearLayout);
                 mAddedGroups.add(newGroup);
             }
+            newGroup.setDisplayAvatarsAtEnd(mIsCollapsed);
             newGroup.setLayoutColor(mLayoutColor);
             Notification.Person sender = senders.get(groupIndex);
             CharSequence nameOverride = null;
@@ -392,7 +399,6 @@
             MessagingMessage message = findAndRemoveMatchingMessage(m);
             if (message == null) {
                 message = MessagingMessage.createMessage(this, m);
-                message.addOnLayoutChangeListener(MESSAGING_PROPERTY_ANIMATOR);
             }
             message.setIsHistoric(historic);
             result.add(message);
diff --git a/core/java/com/android/internal/widget/MessagingLinearLayout.java b/core/java/com/android/internal/widget/MessagingLinearLayout.java
index f0ef370..991e3e7 100644
--- a/core/java/com/android/internal/widget/MessagingLinearLayout.java
+++ b/core/java/com/android/internal/widget/MessagingLinearLayout.java
@@ -75,7 +75,6 @@
                 targetHeight = Integer.MAX_VALUE;
                 break;
         }
-        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
 
         // Now that we know which views to take, fix up the indents and see what width we get.
         int measuredWidth = mPaddingLeft + mPaddingRight;
@@ -90,7 +89,6 @@
         totalHeight = mPaddingTop + mPaddingBottom;
         boolean first = true;
         int linesRemaining = mMaxDisplayedLines;
-
         // Starting from the bottom: we measure every view as if it were the only one. If it still
         // fits, we take it, otherwise we stop there.
         for (int i = count - 1; i >= 0 && totalHeight < targetHeight; i--) {
@@ -100,11 +98,13 @@
             final View child = getChildAt(i);
             LayoutParams lp = (LayoutParams) getChildAt(i).getLayoutParams();
             MessagingChild messagingChild = null;
+            int spacing = mSpacing;
             if (child instanceof MessagingChild) {
                 messagingChild = (MessagingChild) child;
                 messagingChild.setMaxDisplayedLines(linesRemaining);
+                spacing += messagingChild.getExtraSpacing();
             }
-            int spacing = first ? 0 : mSpacing;
+            spacing = first ? 0 : spacing;
             measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, totalHeight
                     - mPaddingTop - mPaddingBottom + spacing);
 
@@ -254,6 +254,9 @@
         void setMaxDisplayedLines(int lines);
         void hideAnimated();
         boolean isHidingAnimated();
+        default int getExtraSpacing() {
+            return 0;
+        }
     }
 
     public static class LayoutParams extends MarginLayoutParams {
diff --git a/core/java/com/android/internal/widget/MessagingMessage.java b/core/java/com/android/internal/widget/MessagingMessage.java
index f09621f..bf1c5ca 100644
--- a/core/java/com/android/internal/widget/MessagingMessage.java
+++ b/core/java/com/android/internal/widget/MessagingMessage.java
@@ -16,182 +16,125 @@
 
 package com.android.internal.widget;
 
-import android.annotation.AttrRes;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.StyleRes;
 import android.app.Notification;
-import android.content.Context;
-import android.text.Layout;
-import android.util.AttributeSet;
-import android.util.Pools;
-import android.view.LayoutInflater;
-import android.view.ViewGroup;
-import android.view.ViewParent;
-import android.widget.RemoteViews;
-
-import com.android.internal.R;
+import android.view.View;
 
 import java.util.Objects;
 
 /**
  * A message of a {@link MessagingLayout}.
  */
-@RemoteViews.RemoteView
-public class MessagingMessage extends ImageFloatingTextView implements
-        MessagingLinearLayout.MessagingChild {
+public interface MessagingMessage extends MessagingLinearLayout.MessagingChild {
 
-    private static Pools.SimplePool<MessagingMessage> sInstancePool
-            = new Pools.SynchronizedPool<>(10);
-    private Notification.MessagingStyle.Message mMessage;
-    private MessagingGroup mGroup;
-    private boolean mIsHistoric;
-    private boolean mIsHidingAnimated;
+    /**
+     * Prefix for supported image MIME types
+     **/
+    String IMAGE_MIME_TYPE_PREFIX = "image/";
 
-    public MessagingMessage(@NonNull Context context) {
-        super(context);
+    static MessagingMessage createMessage(MessagingLayout layout,
+            Notification.MessagingStyle.Message m) {
+        if (hasImage(m)) {
+            return MessagingImageMessage.createMessage(layout, m);
+        } else {
+            return MessagingTextMessage.createMessage(layout, m);
+        }
     }
 
-    public MessagingMessage(@NonNull Context context, @Nullable AttributeSet attrs) {
-        super(context, attrs);
+    static void dropCache() {
+        MessagingTextMessage.dropCache();
+        MessagingImageMessage.dropCache();
     }
 
-    public MessagingMessage(@NonNull Context context, @Nullable AttributeSet attrs,
-            @AttrRes int defStyleAttr) {
-        super(context, attrs, defStyleAttr);
+    static boolean hasImage(Notification.MessagingStyle.Message m) {
+        return m.getDataUri() != null
+                && m.getDataMimeType() != null
+                && m.getDataMimeType().startsWith(IMAGE_MIME_TYPE_PREFIX);
     }
 
-    public MessagingMessage(@NonNull Context context, @Nullable AttributeSet attrs,
-            @AttrRes int defStyleAttr, @StyleRes int defStyleRes) {
-        super(context, attrs, defStyleAttr, defStyleRes);
+    /**
+     * Set a message for this view.
+     * @return true if setting the message worked
+     */
+    default boolean setMessage(Notification.MessagingStyle.Message message) {
+        getState().setMessage(message);
+        return true;
     }
 
-    private void setMessage(Notification.MessagingStyle.Message message) {
-        mMessage = message;
-        setText(message.getText());
+    default Notification.MessagingStyle.Message getMessage() {
+        return getState().getMessage();
     }
 
-    public Notification.MessagingStyle.Message getMessage() {
-        return mMessage;
-    }
-
-    boolean sameAs(Notification.MessagingStyle.Message message) {
-        if (!Objects.equals(message.getText(), mMessage.getText())) {
+    default boolean sameAs(Notification.MessagingStyle.Message message) {
+        Notification.MessagingStyle.Message ownMessage = getMessage();
+        if (!Objects.equals(message.getText(), ownMessage.getText())) {
             return false;
         }
-        if (!Objects.equals(message.getSender(), mMessage.getSender())) {
+        if (!Objects.equals(message.getSender(), ownMessage.getSender())) {
             return false;
         }
-        if (!Objects.equals(message.getTimestamp(), mMessage.getTimestamp())) {
+        if (!Objects.equals(message.getTimestamp(), ownMessage.getTimestamp())) {
+            return false;
+        }
+        if (!Objects.equals(message.getDataMimeType(), ownMessage.getDataMimeType())) {
+            return false;
+        }
+        if (!Objects.equals(message.getDataUri(), ownMessage.getDataUri())) {
             return false;
         }
         return true;
     }
 
-    boolean sameAs(MessagingMessage message) {
+    default boolean sameAs(MessagingMessage message) {
         return sameAs(message.getMessage());
     }
 
-    static MessagingMessage createMessage(MessagingLayout layout,
-            Notification.MessagingStyle.Message m) {
-        MessagingLinearLayout messagingLinearLayout = layout.getMessagingLinearLayout();
-        MessagingMessage createdMessage = sInstancePool.acquire();
-        if (createdMessage == null) {
-            createdMessage = (MessagingMessage) LayoutInflater.from(layout.getContext()).inflate(
-                    R.layout.notification_template_messaging_message, messagingLinearLayout,
-                    false);
-        }
-        createdMessage.setMessage(m);
-        return createdMessage;
+    default void removeMessage() {
+        getGroup().removeMessage(this);
     }
 
-    public void removeMessage() {
-        mGroup.removeMessage(this);
+    default void setMessagingGroup(MessagingGroup group) {
+        getState().setGroup(group);
     }
 
-    public void recycle() {
-        mGroup = null;
-        mMessage = null;
-        setAlpha(1.0f);
-        setTranslationY(0);
-        sInstancePool.release(this);
+    default void setIsHistoric(boolean isHistoric) {
+        getState().setIsHistoric(isHistoric);
     }
 
-    public void setMessagingGroup(MessagingGroup group) {
-        mGroup = group;
+    default MessagingGroup getGroup() {
+        return getState().getGroup();
     }
 
-    public static void dropCache() {
-        sInstancePool = new Pools.SynchronizedPool<>(10);
-    }
-
-    public void setIsHistoric(boolean isHistoric) {
-        mIsHistoric = isHistoric;
-    }
-
-    public MessagingGroup getGroup() {
-        return mGroup;
+    default void setIsHidingAnimated(boolean isHiding) {
+        getState().setIsHidingAnimated(isHiding);
     }
 
     @Override
-    public int getMeasuredType() {
-        boolean measuredTooSmall = getMeasuredHeight()
-                < getLayoutHeight() + getPaddingTop() + getPaddingBottom();
-        if (measuredTooSmall) {
-            return MEASURED_TOO_SMALL;
-        } else {
-            Layout layout = getLayout();
-            if (layout == null) {
-                return MEASURED_TOO_SMALL;
-            }
-            if (layout.getEllipsisCount(layout.getLineCount() - 1) > 0) {
-                return MEASURED_SHORTENED;
-            } else {
-                return MEASURED_NORMAL;
-            }
-        }
+    default boolean isHidingAnimated() {
+        return getState().isHidingAnimated();
     }
 
     @Override
-    public void hideAnimated() {
+    default void hideAnimated() {
         setIsHidingAnimated(true);
-        mGroup.performRemoveAnimation(this, () -> setIsHidingAnimated(false));
+        getGroup().performRemoveAnimation(getState().getHostView(),
+                () -> setIsHidingAnimated(false));
     }
 
-    private void setIsHidingAnimated(boolean isHiding) {
-        ViewParent parent = getParent();
-        mIsHidingAnimated = isHiding;
-        invalidate();
-        if (parent instanceof ViewGroup) {
-            ((ViewGroup) parent).invalidate();
-        }
-    }
-
-    @Override
-    public boolean isHidingAnimated() {
-        return mIsHidingAnimated;
-    }
-
-    @Override
-    public void setMaxDisplayedLines(int lines) {
-        setMaxLines(lines);
-    }
-
-    @Override
-    public int getConsumedLines() {
-        return getLineCount();
-    }
-
-    public int getLayoutHeight() {
-        Layout layout = getLayout();
-        if (layout == null) {
-            return 0;
-        }
-        return layout.getHeight();
-    }
-
-    @Override
-    public boolean hasOverlappingRendering() {
+    default boolean hasOverlappingRendering() {
         return false;
     }
+
+    default void recycle() {
+        getState().reset();
+    }
+
+    default View getView() {
+        return (View) this;
+    }
+
+    default void setColor(int textColor) {}
+
+    MessagingMessageState getState();
+
+    void setVisibility(int visibility);
 }
diff --git a/core/java/com/android/internal/widget/MessagingMessageState.java b/core/java/com/android/internal/widget/MessagingMessageState.java
new file mode 100644
index 0000000..ac62472
--- /dev/null
+++ b/core/java/com/android/internal/widget/MessagingMessageState.java
@@ -0,0 +1,81 @@
+/*
+ * 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.internal.widget;
+
+import android.app.Notification;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewParent;
+
+/**
+ * Shared state and implementation for MessagingMessages. Used to share common implementations.
+ */
+public class MessagingMessageState {
+    private final View mHostView;
+    private Notification.MessagingStyle.Message mMessage;
+    private MessagingGroup mGroup;
+    private boolean mIsHistoric;
+    private boolean mIsHidingAnimated;
+
+    MessagingMessageState(View hostView) {
+        mHostView = hostView;
+    }
+
+    public void setMessage(Notification.MessagingStyle.Message message) {
+        mMessage = message;
+    }
+
+    public Notification.MessagingStyle.Message getMessage() {
+        return mMessage;
+    }
+
+    public void setGroup(MessagingGroup group) {
+        mGroup = group;
+    }
+
+    public MessagingGroup getGroup() {
+        return mGroup;
+    }
+
+    public void setIsHistoric(boolean isHistoric) {
+        mIsHistoric = isHistoric;
+    }
+
+    public void setIsHidingAnimated(boolean isHiding) {
+        ViewParent parent = mHostView.getParent();
+        mIsHidingAnimated = isHiding;
+        mHostView.invalidate();
+        if (parent instanceof ViewGroup) {
+            ((ViewGroup) parent).invalidate();
+        }
+    }
+
+    public boolean isHidingAnimated() {
+        return mIsHidingAnimated;
+    }
+
+    public View getHostView() {
+        return mHostView;
+    }
+
+    public void reset() {
+        mIsHidingAnimated = false;
+        mIsHistoric = false;
+        mGroup = null;
+        mMessage = null;
+    }
+}
diff --git a/core/java/com/android/internal/widget/MessagingTextMessage.java b/core/java/com/android/internal/widget/MessagingTextMessage.java
new file mode 100644
index 0000000..794cc1d
--- /dev/null
+++ b/core/java/com/android/internal/widget/MessagingTextMessage.java
@@ -0,0 +1,145 @@
+/*
+ * 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.internal.widget;
+
+import android.annotation.AttrRes;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.StyleRes;
+import android.app.Notification;
+import android.content.Context;
+import android.text.Layout;
+import android.util.AttributeSet;
+import android.util.Pools;
+import android.view.LayoutInflater;
+import android.view.ViewGroup;
+import android.view.ViewParent;
+import android.widget.RemoteViews;
+
+import com.android.internal.R;
+
+import java.util.Objects;
+
+/**
+ * A message of a {@link MessagingLayout}.
+ */
+@RemoteViews.RemoteView
+public class MessagingTextMessage extends ImageFloatingTextView implements MessagingMessage {
+
+    private static Pools.SimplePool<MessagingTextMessage> sInstancePool
+            = new Pools.SynchronizedPool<>(20);
+    private final MessagingMessageState mState = new MessagingMessageState(this);
+
+    public MessagingTextMessage(@NonNull Context context) {
+        super(context);
+    }
+
+    public MessagingTextMessage(@NonNull Context context, @Nullable AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public MessagingTextMessage(@NonNull Context context, @Nullable AttributeSet attrs,
+            @AttrRes int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+    }
+
+    public MessagingTextMessage(@NonNull Context context, @Nullable AttributeSet attrs,
+            @AttrRes int defStyleAttr, @StyleRes int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+    }
+
+    @Override
+    public MessagingMessageState getState() {
+        return mState;
+    }
+
+    @Override
+    public boolean setMessage(Notification.MessagingStyle.Message message) {
+        MessagingMessage.super.setMessage(message);
+        setText(message.getText());
+        return true;
+    }
+
+    static MessagingMessage createMessage(MessagingLayout layout,
+            Notification.MessagingStyle.Message m) {
+        MessagingLinearLayout messagingLinearLayout = layout.getMessagingLinearLayout();
+        MessagingTextMessage createdMessage = sInstancePool.acquire();
+        if (createdMessage == null) {
+            createdMessage = (MessagingTextMessage) LayoutInflater.from(
+                    layout.getContext()).inflate(
+                            R.layout.notification_template_messaging_text_message,
+                            messagingLinearLayout,
+                            false);
+            createdMessage.addOnLayoutChangeListener(MessagingLayout.MESSAGING_PROPERTY_ANIMATOR);
+        }
+        createdMessage.setMessage(m);
+        return createdMessage;
+    }
+
+    public void recycle() {
+        MessagingMessage.super.recycle();
+        setAlpha(1.0f);
+        setTranslationY(0);
+        sInstancePool.release(this);
+    }
+
+    public static void dropCache() {
+        sInstancePool = new Pools.SynchronizedPool<>(10);
+    }
+
+    @Override
+    public int getMeasuredType() {
+        boolean measuredTooSmall = getMeasuredHeight()
+                < getLayoutHeight() + getPaddingTop() + getPaddingBottom();
+        if (measuredTooSmall) {
+            return MEASURED_TOO_SMALL;
+        } else {
+            Layout layout = getLayout();
+            if (layout == null) {
+                return MEASURED_TOO_SMALL;
+            }
+            if (layout.getEllipsisCount(layout.getLineCount() - 1) > 0) {
+                return MEASURED_SHORTENED;
+            } else {
+                return MEASURED_NORMAL;
+            }
+        }
+    }
+
+    @Override
+    public void setMaxDisplayedLines(int lines) {
+        setMaxLines(lines);
+    }
+
+    @Override
+    public int getConsumedLines() {
+        return getLineCount();
+    }
+
+    public int getLayoutHeight() {
+        Layout layout = getLayout();
+        if (layout == null) {
+            return 0;
+        }
+        return layout.getHeight();
+    }
+
+    @Override
+    public void setColor(int color) {
+        setTextColor(color);
+    }
+}
diff --git a/core/java/com/android/internal/widget/VerifyCredentialResponse.java b/core/java/com/android/internal/widget/VerifyCredentialResponse.java
index ad6020c..7d1c706 100644
--- a/core/java/com/android/internal/widget/VerifyCredentialResponse.java
+++ b/core/java/com/android/internal/widget/VerifyCredentialResponse.java
@@ -98,6 +98,8 @@
             if (mPayload != null) {
                 dest.writeInt(mPayload.length);
                 dest.writeByteArray(mPayload);
+            } else {
+                dest.writeInt(0);
             }
         }
     }
diff --git a/core/java/com/android/internal/widget/ViewPager.java b/core/java/com/android/internal/widget/ViewPager.java
index d5b6def..64bdc6e 100644
--- a/core/java/com/android/internal/widget/ViewPager.java
+++ b/core/java/com/android/internal/widget/ViewPager.java
@@ -31,6 +31,7 @@
 import android.util.AttributeSet;
 import android.util.Log;
 import android.util.MathUtils;
+import android.view.AbsSavedState;
 import android.view.FocusFinder;
 import android.view.Gravity;
 import android.view.KeyEvent;
@@ -1198,16 +1199,12 @@
      * state, in which case it should implement a subclass of this which
      * contains that state.
      */
-    public static class SavedState extends BaseSavedState {
+    public static class SavedState extends AbsSavedState {
         int position;
         Parcelable adapterState;
         ClassLoader loader;
 
-        public SavedState(Parcel source) {
-            super(source);
-        }
-
-        public SavedState(Parcelable superState) {
+        public SavedState(@NonNull Parcelable superState) {
             super(superState);
         }
 
@@ -1225,10 +1222,15 @@
                     + " position=" + position + "}";
         }
 
-        public static final Creator<SavedState> CREATOR = new Creator<SavedState>() {
+        public static final Creator<SavedState> CREATOR = new ClassLoaderCreator<SavedState>() {
+            @Override
+            public SavedState createFromParcel(Parcel in, ClassLoader loader) {
+                return new SavedState(in, loader);
+            }
+
             @Override
             public SavedState createFromParcel(Parcel in) {
-                return new SavedState(in);
+                return new SavedState(in, null);
             }
             @Override
             public SavedState[] newArray(int size) {
@@ -1237,7 +1239,7 @@
         };
 
         SavedState(Parcel in, ClassLoader loader) {
-            super(in);
+            super(in, loader);
             if (loader == null) {
                 loader = getClass().getClassLoader();
             }
diff --git a/core/java/com/android/server/BootReceiver.java b/core/java/com/android/server/BootReceiver.java
index fb18669..95534e2 100644
--- a/core/java/com/android/server/BootReceiver.java
+++ b/core/java/com/android/server/BootReceiver.java
@@ -72,6 +72,7 @@
         SystemProperties.getInt("ro.debuggable", 0) == 1 ? 98304 : 65536;
 
     private static final File TOMBSTONE_DIR = new File("/data/tombstones");
+    private static final String TAG_TOMBSTONE = "SYSTEM_TOMBSTONE";
 
     // The pre-froyo package and class of the system updater, which
     // ran in the system process.  We need to remove its packages here
@@ -164,7 +165,7 @@
             .append("Revision: ")
             .append(SystemProperties.get("ro.revision", "")).append("\n")
             .append("Bootloader: ").append(Build.BOOTLOADER).append("\n")
-            .append("Radio: ").append(Build.RADIO).append("\n")
+            .append("Radio: ").append(Build.getRadioVersion()).append("\n")
             .append("Kernel: ")
             .append(FileUtils.readTextFile(new File("/proc/version"), 1024, "...\n"))
             .append("\n").toString();
@@ -265,7 +266,7 @@
                     File file = new File(TOMBSTONE_DIR, path);
                     if (file.isFile()) {
                         addFileToDropBox(db, timestamps, headers, file.getPath(), LOG_SIZE,
-                                "SYSTEM_TOMBSTONE");
+                                TAG_TOMBSTONE);
                     }
                 } catch (IOException e) {
                     Slog.e(TAG, "Can't log tombstone", e);
@@ -299,9 +300,20 @@
 
         timestamps.put(filename, fileTime);
 
+
+        String fileContents = FileUtils.readTextFile(file, maxSize, "[[TRUNCATED]]\n");
+        String text = headers + fileContents + footers;
+        // Create an additional report for system server native crashes, with a special tag.
+        if (tag.equals(TAG_TOMBSTONE) && fileContents.contains(">>> system_server <<<")) {
+            addTextToDropBox(db, "system_server_native_crash", text, filename, maxSize);
+        }
+        addTextToDropBox(db, tag, text, filename, maxSize);
+    }
+
+    private static void addTextToDropBox(DropBoxManager db, String tag, String text,
+            String filename, int maxSize) {
         Slog.i(TAG, "Copying " + filename + " to DropBox (" + tag + ")");
-        db.addText(tag, headers + FileUtils.readTextFile(file, maxSize, "[[TRUNCATED]]\n") +
-                footers);
+        db.addText(tag, text);
         EventLog.writeEvent(DropboxLogTags.DROPBOX_FILE_COPY, filename, maxSize, tag);
     }
 
diff --git a/core/jni/OWNERS b/core/jni/OWNERS
new file mode 100644
index 0000000..ce79049
--- /dev/null
+++ b/core/jni/OWNERS
@@ -0,0 +1,12 @@
+# Camera
+per-file *Camera*,*camera* = cychen@google.com
+per-file *Camera*,*camera* = epeev@google.com
+per-file *Camera*,*camera* = etalvala@google.com
+per-file *Camera*,*camera* = shuzhenwang@google.com
+per-file *Camera*,*camera* = yinchiayeh@google.com
+per-file *Camera*,*camera* = zhijunhe@google.com
+
+# Connectivity
+per-file android_net_*=ek@google.com
+per-file android_net_*=lorenzo@google.com
+per-file android_net_*=satk@google.com
diff --git a/core/jni/android/graphics/FontFamily.cpp b/core/jni/android/graphics/FontFamily.cpp
index 937b3ff..48aef4a 100644
--- a/core/jni/android/graphics/FontFamily.cpp
+++ b/core/jni/android/graphics/FontFamily.cpp
@@ -90,7 +90,7 @@
 }
 
 static bool addSkTypeface(NativeFamilyBuilder* builder, sk_sp<SkData>&& data, int ttcIndex,
-        jint givenWeight, jint givenItalic) {
+        jint weight, jint italic) {
     uirenderer::FatVector<SkFontArguments::Axis, 2> skiaAxes;
     for (const auto& axis : builder->axes) {
         skiaAxes.emplace_back(SkFontArguments::Axis{axis.axisTag, axis.value});
@@ -114,27 +114,15 @@
     std::shared_ptr<minikin::MinikinFont> minikinFont =
             std::make_shared<MinikinFontSkia>(std::move(face), fontPtr, fontSize, ttcIndex,
                     builder->axes);
+    minikin::Font::Builder fontBuilder(minikinFont);
 
-    int weight = givenWeight;
-    bool italic = givenItalic == 1;
-    if (givenWeight == RESOLVE_BY_FONT_TABLE || givenItalic == RESOLVE_BY_FONT_TABLE) {
-        int os2Weight;
-        bool os2Italic;
-        if (!minikin::FontFamily::analyzeStyle(minikinFont, &os2Weight, &os2Italic)) {
-            ALOGE("analyzeStyle failed. Using default style");
-            os2Weight = 400;
-            os2Italic = false;
-        }
-        if (givenWeight == RESOLVE_BY_FONT_TABLE) {
-            weight = os2Weight;
-        }
-        if (givenItalic == RESOLVE_BY_FONT_TABLE) {
-            italic = os2Italic;
-        }
+    if (weight != RESOLVE_BY_FONT_TABLE) {
+        fontBuilder.setWeight(weight);
     }
-
-    builder->fonts.push_back(minikin::Font(minikinFont,
-            minikin::FontStyle(weight, static_cast<minikin::FontStyle::Slant>(italic))));
+    if (italic != RESOLVE_BY_FONT_TABLE) {
+        fontBuilder.setSlant(static_cast<minikin::FontStyle::Slant>(italic != 0));
+    }
+    builder->fonts.push_back(fontBuilder.build());
     builder->axes.clear();
     return true;
 }
diff --git a/core/jni/android/graphics/Paint.cpp b/core/jni/android/graphics/Paint.cpp
index 115d0d5..482d028 100644
--- a/core/jni/android/graphics/Paint.cpp
+++ b/core/jni/android/graphics/Paint.cpp
@@ -576,7 +576,7 @@
         minikin::FakedFont baseFont = typeface->fFontCollection->baseFontFaked(typeface->fStyle);
         float saveSkewX = paint->getTextSkewX();
         bool savefakeBold = paint->isFakeBoldText();
-        MinikinFontSkia::populateSkPaint(paint, baseFont.font, baseFont.fakery);
+        MinikinFontSkia::populateSkPaint(paint, baseFont.font->typeface().get(), baseFont.fakery);
         SkScalar spacing = paint->getFontMetrics(metrics);
         // The populateSkPaint call may have changed fake bold / text skew
         // because we want to measure with those effects applied, so now
diff --git a/core/jni/android_graphics_Canvas.cpp b/core/jni/android_graphics_Canvas.cpp
index 6b961f5..06de5da 100644
--- a/core/jni/android_graphics_Canvas.cpp
+++ b/core/jni/android_graphics_Canvas.cpp
@@ -573,6 +573,11 @@
     minikin::Layout::purgeCaches();
 }
 
+static void setCompatibilityVersion(JNIEnv* env, jobject, jint apiLevel) {
+    Canvas::setCompatibilityVersion(apiLevel);
+}
+
+
 }; // namespace CanvasJNI
 
 static const JNINativeMethod gMethods[] = {
@@ -580,6 +585,7 @@
     {"nInitRaster", "(Landroid/graphics/Bitmap;)J", (void*) CanvasJNI::initRaster},
     {"nFreeCaches", "()V", (void*) CanvasJNI::freeCaches},
     {"nFreeTextLayoutCaches", "()V", (void*) CanvasJNI::freeTextLayoutCaches},
+    {"nSetCompatibilityVersion", "(I)V", (void*) CanvasJNI::setCompatibilityVersion},
 
     // ------------ @FastNative ----------------
     {"nSetBitmap", "(JLandroid/graphics/Bitmap;)V", (void*) CanvasJNI::setBitmap},
diff --git a/core/jni/android_hardware_Camera.cpp b/core/jni/android_hardware_Camera.cpp
index d6f8dc4..61d5031 100644
--- a/core/jni/android_hardware_Camera.cpp
+++ b/core/jni/android_hardware_Camera.cpp
@@ -604,6 +604,7 @@
     CameraInfo cameraInfo;
     status_t rc = Camera::getCameraInfo(cameraId, &cameraInfo);
     if (rc != NO_ERROR) {
+        ALOGE("%s: getCameraInfo error: %d", __FUNCTION__, rc);
         return rc;
     }
     int defaultOrientation = 0;
diff --git a/core/jni/android_os_VintfObject.cpp b/core/jni/android_os_VintfObject.cpp
index 1659168..e8ef349 100644
--- a/core/jni/android_os_VintfObject.cpp
+++ b/core/jni/android_os_VintfObject.cpp
@@ -32,10 +32,13 @@
 static jclass gHashMapClazz;
 static jmethodID gHashMapInit;
 static jmethodID gHashMapPut;
+static jclass gLongClazz;
+static jmethodID gLongValueOf;
 
 namespace android {
 
 using vintf::HalManifest;
+using vintf::Level;
 using vintf::SchemaType;
 using vintf::VintfObject;
 using vintf::XmlConverter;
@@ -154,6 +157,14 @@
     return jMap;
 }
 
+static jobject android_os_VintfObject_getTargetFrameworkCompatibilityMatrixVersion(JNIEnv* env, jclass) {
+    std::shared_ptr<const HalManifest> manifest = VintfObject::GetDeviceHalManifest();
+    if (manifest == nullptr || manifest->level() == Level::UNSPECIFIED) {
+        return nullptr;
+    }
+    return env->CallStaticObjectMethod(gLongClazz, gLongValueOf, static_cast<jlong>(manifest->level()));
+}
+
 // ----------------------------------------------------------------------------
 
 static const JNINativeMethod gVintfObjectMethods[] = {
@@ -163,6 +174,7 @@
     {"getHalNamesAndVersions", "()[Ljava/lang/String;", (void*)android_os_VintfObject_getHalNamesAndVersions},
     {"getSepolicyVersion", "()Ljava/lang/String;", (void*)android_os_VintfObject_getSepolicyVersion},
     {"getVndkSnapshots", "()Ljava/util/Map;", (void*)android_os_VintfObject_getVndkSnapshots},
+    {"getTargetFrameworkCompatibilityMatrixVersion", "()Ljava/lang/Long;", (void*)android_os_VintfObject_getTargetFrameworkCompatibilityMatrixVersion},
 };
 
 const char* const kVintfObjectPathName = "android/os/VintfObject";
@@ -175,6 +187,8 @@
     gHashMapInit = GetMethodIDOrDie(env, gHashMapClazz, "<init>", "()V");
     gHashMapPut = GetMethodIDOrDie(env, gHashMapClazz,
             "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
+    gLongClazz = MakeGlobalRefOrDie(env, FindClassOrDie(env, "java/lang/Long"));
+    gLongValueOf = GetStaticMethodIDOrDie(env, gLongClazz, "valueOf", "(J)Ljava/lang/Long;");
 
     return RegisterMethodsOrDie(env, kVintfObjectPathName, gVintfObjectMethods,
             NELEM(gVintfObjectMethods));
diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp
index 1350f3f..d17993a 100644
--- a/core/jni/android_util_Binder.cpp
+++ b/core/jni/android_util_Binder.cpp
@@ -663,7 +663,8 @@
     jobject object = env->CallStaticObjectMethod(gBinderProxyOffsets.mClass,
             gBinderProxyOffsets.mGetInstance, (jlong) nativeData, (jlong) val.get());
     if (env->ExceptionCheck()) {
-        gNativeDataCache = nativeData;
+        // In the exception case, getInstance still took ownership of nativeData.
+        gNativeDataCache = nullptr;
         return NULL;
     }
     BinderProxyNativeData* actualNativeData = getBPNativeData(env, object);
@@ -673,7 +674,7 @@
         nativeData->mObject = val;
         gNativeDataCache = nullptr;
         ++gNumProxies;
-        if (++gNumProxies >= gProxiesWarned + PROXY_WARN_INTERVAL) {
+        if (gNumProxies >= gProxiesWarned + PROXY_WARN_INTERVAL) {
             ALOGW("Unexpectedly many live BinderProxies: %d\n", gNumProxies);
             gProxiesWarned = gNumProxies;
         }
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index 32945bf..d6fe568 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -516,7 +516,7 @@
                                      jint mount_external,
                                      jstring java_se_info, jstring java_se_name,
                                      bool is_system_server, jintArray fdsToClose,
-                                     jintArray fdsToIgnore,
+                                     jintArray fdsToIgnore, bool is_child_zygote,
                                      jstring instructionSet, jstring dataDir) {
   SetSignalHandlers();
 
@@ -699,7 +699,7 @@
     UnsetChldSignalHandler();
 
     env->CallStaticVoidMethod(gZygoteClass, gCallPostForkChildHooks, runtime_flags,
-                              is_system_server, instructionSet);
+                              is_system_server, is_child_zygote, instructionSet);
     if (env->ExceptionCheck()) {
       RuntimeAbort(env, __LINE__, "Error calling post fork hooks.");
     }
@@ -748,8 +748,7 @@
         JNIEnv* env, jclass, jint uid, jint gid, jintArray gids,
         jint runtime_flags, jobjectArray rlimits,
         jint mount_external, jstring se_info, jstring se_name,
-        jintArray fdsToClose,
-        jintArray fdsToIgnore,
+        jintArray fdsToClose, jintArray fdsToIgnore, jboolean is_child_zygote,
         jstring instructionSet, jstring appDataDir) {
     jlong capabilities = 0;
 
@@ -786,13 +785,22 @@
       capabilities |= (1LL << CAP_BLOCK_SUSPEND);
     }
 
+    // If forking a child zygote process, that zygote will need to be able to change
+    // the UID and GID of processes it forks, as well as drop those capabilities.
+    if (is_child_zygote) {
+      capabilities |= (1LL << CAP_SETUID);
+      capabilities |= (1LL << CAP_SETGID);
+      capabilities |= (1LL << CAP_SETPCAP);
+    }
+
     // Containers run without some capabilities, so drop any caps that are not
     // available.
     capabilities &= GetEffectiveCapabilityMask(env);
 
     return ForkAndSpecializeCommon(env, uid, gid, gids, runtime_flags,
             rlimits, capabilities, capabilities, mount_external, se_info,
-            se_name, false, fdsToClose, fdsToIgnore, instructionSet, appDataDir);
+            se_name, false, fdsToClose, fdsToIgnore, is_child_zygote == JNI_TRUE,
+            instructionSet, appDataDir);
 }
 
 static jint com_android_internal_os_Zygote_nativeForkSystemServer(
@@ -803,7 +811,7 @@
                                       runtime_flags, rlimits,
                                       permittedCapabilities, effectiveCapabilities,
                                       MOUNT_EXTERNAL_DEFAULT, NULL, NULL, true, NULL,
-                                      NULL, NULL, NULL);
+                                      NULL, false, NULL, NULL);
   if (pid > 0) {
       // The zygote process checks whether the child process has died or not.
       ALOGI("System server process %d has been created", pid);
@@ -880,7 +888,7 @@
     { "nativeSecurityInit", "()V",
       (void *) com_android_internal_os_Zygote_nativeSecurityInit },
     { "nativeForkAndSpecialize",
-      "(II[II[[IILjava/lang/String;Ljava/lang/String;[I[ILjava/lang/String;Ljava/lang/String;)I",
+      "(II[II[[IILjava/lang/String;Ljava/lang/String;[I[IZLjava/lang/String;Ljava/lang/String;)I",
       (void *) com_android_internal_os_Zygote_nativeForkAndSpecialize },
     { "nativeForkSystemServer", "(II[II[[IJJ)I",
       (void *) com_android_internal_os_Zygote_nativeForkSystemServer },
@@ -895,7 +903,7 @@
 int register_com_android_internal_os_Zygote(JNIEnv* env) {
   gZygoteClass = MakeGlobalRefOrDie(env, FindClassOrDie(env, kZygoteClassName));
   gCallPostForkChildHooks = GetStaticMethodIDOrDie(env, gZygoteClass, "callPostForkChildHooks",
-                                                   "(IZLjava/lang/String;)V");
+                                                   "(IZZLjava/lang/String;)V");
 
   return RegisterMethodsOrDie(env, "com/android/internal/os/Zygote", gMethods, NELEM(gMethods));
 }
diff --git a/core/jni/fd_utils.cpp b/core/jni/fd_utils.cpp
index 3b7b14c..2e60582 100644
--- a/core/jni/fd_utils.cpp
+++ b/core/jni/fd_utils.cpp
@@ -317,10 +317,12 @@
     return false;
   }
 
-  // This is a local socket with an abstract address, we do not accept it.
+  // This is a local socket with an abstract address. Remove the leading NUL byte and
+  // add a human-readable "ABSTRACT/" prefix.
   if (unix_addr->sun_path[0] == '\0') {
-    LOG(ERROR) << "Unsupported AF_UNIX socket (fd=" << fd << ") with abstract address.";
-    return false;
+    *result = "ABSTRACT/";
+    result->append(&unix_addr->sun_path[1], path_len - 1);
+    return true;
   }
 
   // If we're here, sun_path must refer to a null terminated filesystem
diff --git a/core/proto/android/net/OWNERS b/core/proto/android/net/OWNERS
new file mode 100644
index 0000000..a845dcb
--- /dev/null
+++ b/core/proto/android/net/OWNERS
@@ -0,0 +1,5 @@
+set noparent
+
+ek@google.com
+lorenzo@google.com
+satk@google.com
diff --git a/core/proto/android/os/cpufreq.proto b/core/proto/android/os/cpufreq.proto
index 8481ffc..46f4901 100644
--- a/core/proto/android/os/cpufreq.proto
+++ b/core/proto/android/os/cpufreq.proto
@@ -16,32 +16,30 @@
 syntax = "proto2";
 
 option java_multiple_files = true;
-option java_outer_classname = "CpuFreqProto";
 
 import "frameworks/base/libs/incident/proto/android/privacy.proto";
 
 package android.os;
 
 // cpu frequency time from /sys/devices/system/cpu/cpufreq/all_time_in_state
-message CpuFreq {
+message CpuFreqProto {
     option (android.msg_privacy).dest = DEST_AUTOMATIC;
 
     optional int32 jiffy_hz = 1; // obtain by system config.
 
-    repeated CpuFreqStats cpu_freqs = 2;
-}
-
-// frequency time pre cpu, unit in jiffy, TODO: obtain jiffies.
-message CpuFreqStats {
-    option (android.msg_privacy).dest = DEST_AUTOMATIC;
-
-    optional string cpu_name = 1;
-
-    message TimeInState {
+    // frequency time pre cpu, unit in jiffy.
+    message Stats {
         option (android.msg_privacy).dest = DEST_AUTOMATIC;
 
-        optional int32 state_khz = 1;  // cpu frequency
-        optional int64 time_jiffy = 2; // number of jiffies
+        optional string cpu_name = 1;
+
+        message TimeInState {
+            option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
+            optional int32 state_khz = 1;  // cpu frequency
+            optional int64 time_jiffy = 2; // number of jiffies
+        }
+        repeated TimeInState times = 2;
     }
-    repeated TimeInState times = 2;
+    repeated Stats cpu_freqs = 2;
 }
diff --git a/core/proto/android/os/cpuinfo.proto b/core/proto/android/os/cpuinfo.proto
index ca43602..ce69fc9 100644
--- a/core/proto/android/os/cpuinfo.proto
+++ b/core/proto/android/os/cpuinfo.proto
@@ -16,7 +16,6 @@
 syntax = "proto2";
 
 option java_multiple_files = true;
-option java_outer_classname = "CpuInfoProto";
 
 import "frameworks/base/libs/incident/proto/android/privacy.proto";
 
@@ -28,7 +27,7 @@
  *
  * Next Tag: 6
  */
-message CpuInfo {
+message CpuInfoProto {
     option (android.msg_privacy).dest = DEST_AUTOMATIC;
 
     message TaskStats {
diff --git a/core/proto/android/os/incident.proto b/core/proto/android/os/incident.proto
index 0b0ed83..9a53b89 100644
--- a/core/proto/android/os/incident.proto
+++ b/core/proto/android/os/incident.proto
@@ -46,18 +46,12 @@
 import "frameworks/base/core/proto/android/util/event_log_tags.proto";
 import "frameworks/base/core/proto/android/util/log.proto";
 import "frameworks/base/libs/incident/proto/android/os/header.proto";
+import "frameworks/base/libs/incident/proto/android/os/metadata.proto";
 import "frameworks/base/libs/incident/proto/android/privacy.proto";
 import "frameworks/base/libs/incident/proto/android/section.proto";
 
 package android.os;
 
-// This field contains internal metadata associated with an incident report,
-// such as the section ids and privacy policy specs from caller as well as how long
-// and how many bytes a section takes, etc.
-message IncidentMetadata {
-
-}
-
 // privacy field options must not be set at this level because all
 // the sections are able to be controlled and configured by section ids.
 // Instead privacy field options need to be configured in each section proto message.
@@ -122,32 +116,32 @@
     ];
 
     // Linux services
-    optional Procrank procrank = 2000 [
+    optional ProcrankProto procrank = 2000 [
         (section).type = SECTION_NONE, // disable procrank until figure out permission
         (section).args = "/system/xbin/procrank"
     ];
 
-    optional PageTypeInfo page_type_info = 2001 [
+    optional PageTypeInfoProto page_type_info = 2001 [
         (section).type = SECTION_FILE,
         (section).args = "/proc/pagetypeinfo"
     ];
 
-    optional KernelWakeSources kernel_wake_sources = 2002 [
+    optional KernelWakeSourcesProto kernel_wake_sources = 2002 [
         (section).type = SECTION_FILE,
         (section).args = "/d/wakeup_sources"
     ];
 
-    optional CpuInfo cpu_info = 2003 [
+    optional CpuInfoProto cpu_info = 2003 [
         (section).type = SECTION_COMMAND,
         (section).args = "top -b -n 1 -H -s 6 -o pid,tid,user,pr,ni,%cpu,s,virt,res,pcy,cmd,name"
     ];
 
-    optional CpuFreq cpu_freq = 2004 [
+    optional CpuFreqProto cpu_freq = 2004 [
         (section).type = SECTION_FILE,
         (section).args = "/sys/devices/system/cpu/cpufreq/all_time_in_state"
     ];
 
-    optional PsDumpProto processes_and_threads = 2005 [
+    optional PsProto processes_and_threads = 2005 [
         (section).type = SECTION_COMMAND,
         (section).args = "ps -A -T -Z -O pri,nice,rtprio,sched,pcy,time"
     ];
@@ -204,7 +198,10 @@
         (section).args = "power --proto"
     ];
 
-    optional android.service.print.PrintServiceDumpProto print = 3010;
+    optional android.service.print.PrintServiceDumpProto print = 3010 [
+        (section).type = SECTION_DUMPSYS,
+        (section).args = "print --proto"
+    ];
 
     optional android.service.procstats.ProcessStatsServiceDumpProto procstats = 3011 [
         (section).type = SECTION_DUMPSYS,
diff --git a/core/proto/android/os/kernelwake.proto b/core/proto/android/os/kernelwake.proto
index c296dab..5021a06 100644
--- a/core/proto/android/os/kernelwake.proto
+++ b/core/proto/android/os/kernelwake.proto
@@ -16,41 +16,40 @@
 syntax = "proto2";
 
 option java_multiple_files = true;
-option java_outer_classname = "WakeupSourcesProto";
 
 import "frameworks/base/libs/incident/proto/android/privacy.proto";
 
 package android.os;
 
-message KernelWakeSources {
+message KernelWakeSourcesProto {
     option (android.msg_privacy).dest = DEST_AUTOMATIC;
 
     // Kernel records of what caused the application processor to wake up
-    repeated WakeupSourceProto wakeup_sources = 1;
-}
+    message WakeupSource {
+        option (android.msg_privacy).dest = DEST_AUTOMATIC;
 
-// Next Tag: 11
-message WakeupSourceProto {
-    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+        // Name of the event which triggers application processor
+        optional string name = 1;
 
-    // Name of the event which triggers application processor
-    optional string name = 1;
+        optional int32 active_count = 2;
 
-    optional int32 active_count = 2;
+        optional int32 event_count = 3;
 
-    optional int32 event_count = 3;
+        optional int32 wakeup_count = 4;
 
-    optional int32 wakeup_count = 4;
+        optional int32 expire_count = 5;
 
-    optional int32 expire_count = 5;
+        optional int64 active_since = 6;
 
-    optional int64 active_since = 6;
+        optional int64 total_time = 7;
 
-    optional int64 total_time = 7;
+        optional int64 max_time = 8;
 
-    optional int64 max_time = 8;
+        optional int64 last_change = 9;
 
-    optional int64 last_change = 9;
+        optional int64 prevent_suspend_time = 10;
 
-    optional int64 prevent_suspend_time = 10;
+        // Next Tag: 11
+    }
+    repeated WakeupSource wakeup_sources = 1;
 }
diff --git a/core/proto/android/os/pagetypeinfo.proto b/core/proto/android/os/pagetypeinfo.proto
index b8f618b..f5d77d6 100644
--- a/core/proto/android/os/pagetypeinfo.proto
+++ b/core/proto/android/os/pagetypeinfo.proto
@@ -16,7 +16,6 @@
 syntax = "proto2";
 
 option java_multiple_files = true;
-option java_outer_classname = "PageTypeInfoProto";
 
 import "frameworks/base/libs/incident/proto/android/privacy.proto";
 
@@ -37,49 +36,47 @@
  *
  *  Next tag: 5
  */
-message PageTypeInfo {
+message PageTypeInfoProto {
     option (android.msg_privacy).dest = DEST_AUTOMATIC;
 
     optional int32 page_block_order = 1;
 
     optional int32 pages_per_block = 2;
 
-    repeated MigrateTypeProto migrate_types = 3;
+    // Next tag: 5
+    message MigrateType {
+        option (android.msg_privacy).dest = DEST_AUTOMATIC;
 
-    repeated BlockProto blocks = 4;
-}
+        optional int32 node = 1;
 
-// Next tag: 5
-message MigrateTypeProto {
-    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+        optional string zone = 2;
 
-    optional int32 node = 1;
+        optional string type = 3;
 
-    optional string zone = 2;
+        // order level starts from 0 for 4KB to page_block_order defined above, e.g. 10 for 4096KB
+        repeated int32 free_pages_count = 4;
+    }
+    repeated MigrateType migrate_types = 3;
 
-    optional string type = 3;
+    // Next tag: 9
+    message Block {
+        option (android.msg_privacy).dest = DEST_AUTOMATIC;
 
-    // order level starts from 0 for 4KB to page_block_order defined above, e.g. 10 for 4096KB
-    repeated int32 free_pages_count = 4;
-}
+        optional int32 node = 1;
 
-// Next tag: 9
-message BlockProto {
-    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+        optional string zone = 2;
 
-    optional int32 node = 1;
+        optional int32 unmovable = 3;
 
-    optional string zone = 2;
+        optional int32 reclaimable = 4;
 
-    optional int32 unmovable = 3;
+        optional int32 movable = 5;
 
-    optional int32 reclaimable = 4;
+        optional int32 cma = 6;
 
-    optional int32 movable = 5;
+        optional int32 reserve = 7;
 
-    optional int32 cma = 6;
-
-    optional int32 reserve = 7;
-
-    optional int32 isolate = 8;
+        optional int32 isolate = 8;
+    }
+    repeated Block blocks = 4;
 }
diff --git a/core/proto/android/os/procrank.proto b/core/proto/android/os/procrank.proto
index 204a5af..ff7515e 100644
--- a/core/proto/android/os/procrank.proto
+++ b/core/proto/android/os/procrank.proto
@@ -16,78 +16,73 @@
 
 syntax = "proto2";
 option java_multiple_files = true;
-option java_outer_classname = "ProcrankProto";
 
 import "frameworks/base/libs/incident/proto/android/privacy.proto";
 
 package android.os;
 
 //Memory usage of running processes
-message Procrank {
+message ProcrankProto {
     option (android.msg_privacy).dest = DEST_AUTOMATIC;
 
     // Currently running process
-    repeated ProcessProto processes = 1;
+    // Next Tag: 11
+    message Process {
+        option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
+        // ID of the process
+        optional int32 pid = 1;
+
+        // virtual set size, unit KB
+        optional int64 vss = 2;
+
+        // resident set size, unit KB
+        optional int64 rss = 3;
+
+        // proportional set size, unit KB
+        optional int64 pss = 4;
+
+        // unique set size, unit KB
+        optional int64 uss = 5;
+
+        // swap size, unit KB
+        optional int64 swap = 6;
+
+        // proportional swap size, unit KB
+        optional int64 pswap = 7;
+
+        // unique swap size, unit KB
+        optional int64 uswap = 8;
+
+        // zswap size, unit KB
+        optional int64 zswap = 9;
+
+        // process command
+        optional string cmdline = 10;
+    }
+    repeated Process processes = 1;
 
     // Summary
-    optional SummaryProto summary = 2;
-}
+    // Next Tag: 3
+    message Summary {
+        option (android.msg_privacy).dest = DEST_AUTOMATIC;
 
-// Next Tag: 11
-message ProcessProto {
-    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+        optional Process total = 1;
 
-    // ID of the process
-    optional int32 pid = 1;
+        // TODO: sync on how to use these values
+        message Zram {
+            option (android.msg_privacy).dest = DEST_AUTOMATIC;
 
-    // virtual set size, unit KB
-    optional int64 vss = 2;
+            optional string raw_text = 1;
+        }
+        optional Zram zram = 2;
 
-    // resident set size, unit KB
-    optional int64 rss = 3;
+        message Ram {
+            option (android.msg_privacy).dest = DEST_AUTOMATIC;
 
-    // proportional set size, unit KB
-    optional int64 pss = 4;
-
-    // unique set size, unit KB
-    optional int64 uss = 5;
-
-    // swap size, unit KB
-    optional int64 swap = 6;
-
-    // proportional swap size, unit KB
-    optional int64 pswap = 7;
-
-    // unique swap size, unit KB
-    optional int64 uswap = 8;
-
-    // zswap size, unit KB
-    optional int64 zswap = 9;
-
-    // process command
-    optional string cmdline = 10;
-}
-
-// Next Tag: 3
-message SummaryProto {
-    option (android.msg_privacy).dest = DEST_AUTOMATIC;
-
-    optional ProcessProto total = 1;
-
-    optional ZramProto zram = 2;
-
-    optional RamProto ram = 3;
-}
-
-// TODO: sync on how to use these values
-message ZramProto {
-    option (android.msg_privacy).dest = DEST_AUTOMATIC;
-
-    optional string raw_text = 1;
-}
-
-message RamProto {
-    option (android.msg_privacy).dest = DEST_AUTOMATIC;
-
-    optional string raw_text = 1;
+            optional string raw_text = 1;
+        }
+        optional Ram ram = 3;
+    }
+    optional Summary summary = 2;
 }
diff --git a/core/proto/android/os/ps.proto b/core/proto/android/os/ps.proto
index 9cce727..0ab92d7 100644
--- a/core/proto/android/os/ps.proto
+++ b/core/proto/android/os/ps.proto
@@ -22,7 +22,7 @@
 
 import "frameworks/base/libs/incident/proto/android/privacy.proto";
 
-message PsDumpProto {
+message PsProto {
     option (android.msg_privacy).dest = DEST_AUTOMATIC;
 
     message Process {
diff --git a/core/proto/android/providers/settings.proto b/core/proto/android/providers/settings.proto
index ff0f4fd..c35b2ec 100644
--- a/core/proto/android/providers/settings.proto
+++ b/core/proto/android/providers/settings.proto
@@ -399,6 +399,7 @@
     optional SettingProto euicc_factory_reset_timeout_millis = 333 [ (android.privacy).dest = DEST_AUTOMATIC ];
     optional SettingProto storage_settings_clobber_threshold = 334 [ (android.privacy).dest = DEST_AUTOMATIC ];
     optional SettingProto chained_battery_attribution_enabled = 353 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto hidden_api_blacklist_exemptions = 355 [ (android.privacy).dest = DEST_AUTOMATIC ];
     // Subscription to be used for voice call on a multi sim device. The
     // supported values are 0 = SUB1, 1 = SUB2 and etc.
     optional SettingProto multi_sim_voice_call_subscription = 276 [ (android.privacy).dest = DEST_AUTOMATIC ];
@@ -421,15 +422,18 @@
     optional SettingProto enable_deletion_helper_no_threshold_toggle = 340 [ (android.privacy).dest = DEST_AUTOMATIC ];
     optional SettingProto notification_snooze_options = 341 [ (android.privacy).dest = DEST_AUTOMATIC ];
     optional SettingProto enable_gnss_raw_meas_full_tracking = 346 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto install_carrier_app_notification_persistent = 356 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto install_carrier_app_notification_sleep_millis = 357 [ (android.privacy).dest = DEST_AUTOMATIC ];
     optional SettingProto zram_enabled = 347 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto 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 ];
+    optional SettingsProto show_zen_upgrade_notification = 354  [ (android.privacy).dest = DEST_AUTOMATIC ];
 
     // Please insert fields in the same order as in
     // frameworks/base/core/java/android/provider/Settings.java.
-    // Next tag = 354;
+    // Next tag = 356;
 }
 
 message SecureSettingsProto {
@@ -662,10 +666,11 @@
     optional SettingProto backup_manager_constants = 169;
     optional SettingProto show_first_crash_dialog_dev_option = 195 [ (android.privacy).dest = DEST_AUTOMATIC ];
     optional SettingProto bluetooth_on_while_driving = 196 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto backup_local_transport_parameters = 197;
 
     // Please insert fields in the same order as in
     // frameworks/base/core/java/android/provider/Settings.java.
-    // Next tag = 197
+    // Next tag = 198
 }
 
 message SystemSettingsProto {
diff --git a/core/proto/android/server/alarmmanagerservice.proto b/core/proto/android/server/alarmmanagerservice.proto
index 0342c9c..d1c5db6 100644
--- a/core/proto/android/server/alarmmanagerservice.proto
+++ b/core/proto/android/server/alarmmanagerservice.proto
@@ -104,11 +104,6 @@
 
   repeated InFlightProto outstanding_deliveries = 34;
 
-  // Minimum time between ALLOW_WHILE_IDLE alarms when system is idling. It
-  // should be either CosntantsProto.allow_while_idle_short_duration_ms or
-  // ConstantsProto.allow_while_idle_long_duration_ms.
-  optional int64 allow_while_idle_min_duration_ms = 35;
-
   message LastAllowWhileIdleDispatch {
     option (.android.msg_privacy).dest = DEST_AUTOMATIC;
 
@@ -121,7 +116,7 @@
   }
 
   // Whether the short or long while-idle timeout should be used for each UID.
-  repeated int32 use_allow_while_idle_short_time = 42;
+  repeated int32 use_allow_while_idle_short_time = 35;
 
   // For each uid, this is the last time we dispatched an "allow while idle"
   // alarm, used to determine the earliest we can dispatch the next such alarm.
diff --git a/core/proto/android/server/powermanagerservice.proto b/core/proto/android/server/powermanagerservice.proto
index b5c3ac0..5cb5319 100644
--- a/core/proto/android/server/powermanagerservice.proto
+++ b/core/proto/android/server/powermanagerservice.proto
@@ -227,7 +227,6 @@
         optional int32 setting_minimum = 1;
         optional int32 setting_maximum = 2;
         optional int32 setting_default = 3;
-        optional int32 setting_for_vr_default = 4;
     }
 
     // True to decouple auto-suspend mode from the display state.
@@ -293,44 +292,27 @@
     // The stay on while plugged in setting.
     // A set of battery conditions under which to make the screen stay on.
     optional StayOnWhilePluggedInProto stay_on_while_plugged_in = 29;
-    // The screen brightness setting, from 0 to 255.
-    // Use -1 if no value has been set.
-    optional sint32 screen_brightness_setting = 30;
-    // The screen auto-brightness adjustment setting, from -1 to 1.
-    // Use 0 if there is no adjustment.
-    optional float screen_auto_brightness_adjustment_setting = 31;
     // The screen brightness mode.
-    optional .android.providers.settings.SettingsProto.ScreenBrightnessMode screen_brightness_mode_setting = 32;
+    optional .android.providers.settings.SettingsProto.ScreenBrightnessMode screen_brightness_mode_setting = 30;
     // The screen brightness setting override from the window manager
     // to allow the current foreground activity to override the brightness.
     // Use -1 to disable.
-    optional sint32 screen_brightness_override_from_window_manager = 33;
+    optional sint32 screen_brightness_override_from_window_manager = 31;
     // The user activity timeout override from the window manager
     // to allow the current foreground activity to override the user activity
     // timeout. Use -1 to disable.
-    optional sint64 user_activity_timeout_override_from_window_manager_ms = 34;
+    optional sint64 user_activity_timeout_override_from_window_manager_ms = 32;
     // The window manager has determined the user to be inactive via other means.
     // Set this to false to disable.
-    optional bool is_user_inactive_override_from_window_manager = 35;
-    // The screen brightness setting override from the settings application
-    // to temporarily adjust the brightness until next updated,
-    // Use -1 to disable.
-    optional sint32 temporary_screen_brightness_setting_override = 36;
-    // The screen brightness adjustment setting override from the settings
-    // application to temporarily adjust the auto-brightness adjustment factor
-    // until next updated, in the range -1..1.
-    // Use NaN to disable.
-    optional float temporary_screen_auto_brightness_adjustment_setting_override = 37;
+    optional bool is_user_inactive_override_from_window_manager = 33;
     // The screen state to use while dozing.
-    optional .android.view.DisplayStateEnum doze_screen_state_override_from_dream_manager = 38;
+    optional .android.view.DisplayStateEnum doze_screen_state_override_from_dream_manager = 34;
     // The screen brightness to use while dozing.
-    optional float dozed_screen_brightness_override_from_dream_manager = 39;
+    optional float dozed_screen_brightness_override_from_dream_manager = 35;
     // Screen brightness settings limits.
-    optional ScreenBrightnessSettingLimitsProto screen_brightness_setting_limits = 40;
-    // The screen brightness setting, from 0 to 255, to be used while in VR Mode.
-    optional int32 screen_brightness_for_vr_setting = 41;
+    optional ScreenBrightnessSettingLimitsProto screen_brightness_setting_limits = 36;
     // True if double tap to wake is enabled
-    optional bool is_double_tap_wake_enabled = 42;
+    optional bool is_double_tap_wake_enabled = 37;
     // True if we are currently in VR Mode.
-    optional bool is_vr_mode_enabled = 43;
+    optional bool is_vr_mode_enabled = 38;
 }
diff --git a/core/proto/android/service/package.proto b/core/proto/android/service/package.proto
index ef777de..f8050a1 100644
--- a/core/proto/android/service/package.proto
+++ b/core/proto/android/service/package.proto
@@ -49,7 +49,8 @@
         option (android.msg_privacy).dest = DEST_AUTOMATIC;
 
         optional int32 user_id = 1;
-        optional string name = 2 [ (android.privacy).dest = DEST_EXPLICIT ];
+        // Name of the shared UID. eg: android.uid.bluetooth
+        optional string name = 2;
     }
 
     // Installed packages.
diff --git a/core/proto/android/service/print.proto b/core/proto/android/service/print.proto
index c2be7f1..f783b86 100644
--- a/core/proto/android/service/print.proto
+++ b/core/proto/android/service/print.proto
@@ -21,13 +21,18 @@
 option java_outer_classname = "PrintServiceProto";
 
 import "frameworks/base/core/proto/android/content/component_name.proto";
+import "frameworks/base/libs/incident/proto/android/privacy.proto";
 
 message PrintServiceDumpProto {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
     // Each user has a separate printer state
     repeated PrintUserStateProto userStates = 1;
 }
 
 message PrintUserStateProto {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
     // Should be 0, 10, 11, 12, etc. where 0 is the owner.
     optional int32 user_id = 1;
 
@@ -51,6 +56,8 @@
 }
 
 message PrintSpoolerStateProto {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
     // Is the print spooler destroyed?
     optional bool is_destroyed = 1;
 
@@ -62,6 +69,8 @@
 }
 
 message PrintSpoolerInternalStateProto {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
     // Print jobs
     repeated PrintJobInfoProto print_jobs = 1;
 
@@ -73,6 +82,8 @@
 }
 
 message PrinterCapabilitiesProto {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
     // Minimum margins of the printer
     optional MarginsProto min_margins = 1;
 
@@ -90,6 +101,8 @@
 }
 
 message PrinterInfoProto {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
     // The id of the printer
     optional PrinterIdProto id = 1;
 
@@ -120,6 +133,8 @@
 }
 
 message PrinterDiscoverySessionProto {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
     // Is this session destroyed?
     optional bool is_destroyed = 1;
 
@@ -140,6 +155,8 @@
 }
 
 message InstalledPrintServiceProto {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
     // Component name of the service
     optional android.content.ComponentNameProto component_name = 1;
 
@@ -154,14 +171,18 @@
 }
 
 message PrinterIdProto {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
     // Component name of the service that reported the printer
     optional android.content.ComponentNameProto service_name = 1;
 
     // Local id of the printer
-    optional string local_id = 2;
+    optional string local_id = 2 [ (android.privacy).dest = DEST_EXPLICIT ];
 }
 
 message ActivePrintServiceProto {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
     // Component name of the service
     optional android.content.ComponentNameProto component_name = 1;
 
@@ -185,6 +206,8 @@
 }
 
 message MediaSizeProto {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
     // Id of this media size
     optional string id = 1;
 
@@ -199,6 +222,8 @@
 }
 
 message ResolutionProto {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
     // Id of this resolution
     optional string id = 1;
 
@@ -213,6 +238,8 @@
 }
 
 message MarginsProto {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
     // Space at the top
     optional int32 top_mils = 1;
 
@@ -227,6 +254,8 @@
 }
 
 message PrintAttributesProto {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
     // Media to use
     optional ResolutionProto media_size = 1;
 
@@ -270,8 +299,10 @@
 }
 
 message PrintDocumentInfoProto {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
     // Name of the document to print
-    optional string name = 1;
+    optional string name = 1 [ (android.privacy).dest = DEST_EXPLICIT ];
 
     // Number of pages in the doc
     optional int32 page_count = 2;
@@ -284,6 +315,8 @@
 }
 
 message PageRangeProto {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
     // Start of the range
     optional int32 start = 1;
 
@@ -292,8 +325,10 @@
 }
 
 message PrintJobInfoProto {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
     // Label of the job
-    optional string label = 1;
+    optional string label = 1 [ (android.privacy).dest = DEST_EXPLICIT ];
 
     // Id of the job
     optional string print_job_id = 2;
@@ -359,6 +394,8 @@
 }
 
 message CachedPrintJobProto {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
     // The id of the app the job belongs to
     optional int32 app_id = 1;
 
diff --git a/core/proto/android/telecomm/enums.proto b/core/proto/android/telecomm/enums.proto
new file mode 100644
index 0000000..7a2ba62
--- /dev/null
+++ b/core/proto/android/telecomm/enums.proto
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+syntax = "proto2";
+package android.telecom;
+
+option java_outer_classname = "TelecomProtoEnums";
+option java_multiple_files = true;
+
+/**
+ * Call states, primarily used in CallState.java,
+ * Call.java, and CallsManager.java in packages/services.
+ */
+enum CallStateEnum {
+    /**
+     * Indicates that a call is new and not connected. This is used as the default state internally
+     * within Telecom and should not be used between Telecom and call services. Call services are
+     * not expected to ever interact with NEW calls, but {@link android.telecom.InCallService}s will
+     * see calls in this state.
+     */
+    NEW = 0;
+
+    /**
+     * The initial state of an outgoing {@code Call}.
+     * Common transitions are to {@link #DIALING} state for a successful call or
+     * {@link #DISCONNECTED} if it failed.
+     */
+    CONNECTING = 1;
+
+    /**
+     * The state of an outgoing {@code Call} when waiting on user to select a
+     * {@link android.telecom.PhoneAccount} through which to place the call.
+     */
+    SELECT_PHONE_ACCOUNT = 2;
+
+    /**
+     * Indicates that a call is outgoing and in the dialing state. A call transitions to this state
+     * once an outgoing call has begun (e.g., user presses the dial button in Dialer). Calls in this
+     * state usually transition to {@link #ACTIVE} if the call was answered or {@link #DISCONNECTED}
+     * if the call was disconnected somehow (e.g., failure or cancellation of the call by the user).
+     */
+    DIALING = 3;
+
+    /**
+     * Indicates that a call is incoming and the user still has the option of answering, rejecting,
+     * or doing nothing with the call. This state is usually associated with some type of audible
+     * ringtone. Normal transitions are to {@link #ACTIVE} if answered or {@link #DISCONNECTED}
+     * otherwise.
+     */
+    RINGING = 4;
+
+    /**
+     * Indicates that a call is currently connected to another party and a communication channel is
+     * open between them. The normal transition to this state is by the user answering a
+     * {@link #DIALING} call or a {@link #RINGING} call being answered by the other party.
+     */
+    ACTIVE = 5;
+
+    /**
+     * Indicates that the call is currently on hold. In this state, the call is not terminated
+     * but no communication is allowed until the call is no longer on hold. The typical transition
+     * to this state is by the user putting an {@link #ACTIVE} call on hold by explicitly performing
+     * an action, such as clicking the hold button.
+     */
+    ON_HOLD = 6;
+
+    /**
+     * Indicates that a call is currently disconnected. All states can transition to this state
+     * by the call service giving notice that the connection has been severed. When the user
+     * explicitly ends a call, it will not transition to this state until the call service confirms
+     * the disconnection or communication was lost to the call service currently responsible for
+     * this call (e.g., call service crashes).
+     */
+    DISCONNECTED = 7;
+
+    /**
+     * Indicates that the call was attempted (mostly in the context of outgoing, at least at the
+     * time of writing) but cancelled before it was successfully connected.
+     */
+    ABORTED = 8;
+
+    /**
+     * Indicates that the call is in the process of being disconnected and will transition next
+     * to a {@link #DISCONNECTED} state.
+     * <p>
+     * This state is not expected to be communicated from the Telephony layer, but will be reported
+     * to the InCall UI for calls where disconnection has been initiated by the user but the
+     * ConnectionService has confirmed the call as disconnected.
+     */
+    DISCONNECTING = 9;
+
+    /**
+     * Indicates that the call is in the process of being pulled to the local device.
+     * <p>
+     * This state should only be set on a call with
+     * {@link android.telecom.Connection#PROPERTY_IS_EXTERNAL_CALL} and
+     * {@link android.telecom.Connection#CAPABILITY_CAN_PULL_CALL}.
+     */
+    PULLING = 10;
+}
+
+// Disconnect causes for a call. Primarily used by android/telecom/DisconnectCause.java
+enum DisconnectCauseEnum {
+    /**
+     * Disconnected because of an unknown or unspecified reason.
+     */
+    UNKNOWN = 0;
+
+    /**
+     * Disconnected because there was an error, such as a problem with the network.
+     */
+    ERROR = 1;
+
+    /**
+     * Disconnected because of a local user-initiated action, such as hanging up.
+     */
+    LOCAL = 2;
+
+    /**
+     * Disconnected because of a remote user-initiated action, such as the other party hanging up
+     * up.
+     */
+    REMOTE = 3;
+
+    /**
+     * Disconnected because it has been canceled.
+     */
+    CANCELED = 4;
+
+    /**
+     * Disconnected because there was no response to an incoming call.
+     */
+    MISSED = 5;
+
+    /**
+     * Disconnected because the user rejected an incoming call.
+     */
+    REJECTED = 6;
+
+    /**
+     * Disconnected because the other party was busy.
+     */
+    BUSY = 7;
+
+    /**
+     * Disconnected because of a restriction on placing the call, such as dialing in airplane
+     * mode.
+     */
+    RESTRICTED = 8;
+
+    /**
+     * Disconnected for reason not described by other disconnect codes.
+     */
+    OTHER = 9;
+
+    /**
+     * Disconnected because the connection manager did not support the call. The call will be tried
+     * again without a connection manager. See {@link PhoneAccount#CAPABILITY_CONNECTION_MANAGER}.
+     */
+    CONNECTION_MANAGER_NOT_SUPPORTED = 10;
+
+    /**
+     * Disconnected because the user did not locally answer the incoming call, but it was answered
+     * on another device where the call was ringing.
+     */
+    ANSWERED_ELSEWHERE = 11;
+
+    /**
+     * Disconnected because the call was pulled from the current device to another device.
+     */
+    CALL_PULLED = 12;
+}
diff --git a/core/proto/android/view/displayinfo.proto b/core/proto/android/view/displayinfo.proto
index 3ac8f3b..cbd06fd 100644
--- a/core/proto/android/view/displayinfo.proto
+++ b/core/proto/android/view/displayinfo.proto
@@ -29,4 +29,5 @@
   optional int32 logical_height = 2;
   optional int32 app_width = 3;
   optional int32 app_height = 4;
+  optional string name = 5;
 }
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 56e276d..3a07a23 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -53,6 +53,7 @@
     <protected-broadcast android:name="android.intent.action.UID_REMOVED" />
     <protected-broadcast android:name="android.intent.action.QUERY_PACKAGE_RESTART" />
     <protected-broadcast android:name="android.intent.action.CONFIGURATION_CHANGED" />
+    <protected-broadcast android:name="android.intent.action.SPLIT_CONFIGURATION_CHANGED" />
     <protected-broadcast android:name="android.intent.action.LOCALE_CHANGED" />
     <protected-broadcast android:name="android.intent.action.BATTERY_CHANGED" />
     <protected-broadcast android:name="android.intent.action.BATTERY_LOW" />
@@ -173,6 +174,10 @@
     <protected-broadcast
         android:name="android.bluetooth.headsetclient.profile.action.LAST_VTAG" />
     <protected-broadcast
+        android:name="android.bluetooth.hearingaid.profile.action.CONNECTION_STATE_CHANGED" />
+    <protected-broadcast
+        android:name="android.bluetooth.hearingaid.profile.action.PLAYING_STATE_CHANGED" />
+    <protected-broadcast
         android:name="android.bluetooth.a2dp.profile.action.CONNECTION_STATE_CHANGED" />
     <protected-broadcast
         android:name="android.bluetooth.a2dp.profile.action.ACTIVE_DEVICE_CHANGED" />
@@ -592,6 +597,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" />
@@ -1431,6 +1440,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 -->
     <!-- ======================================= -->
@@ -1514,6 +1529,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 -->
     <!-- ================================== -->
@@ -1831,19 +1851,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" />
 
     <!-- ================================== -->
@@ -2974,11 +2995,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
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 f78d9b6..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-nodpi/platlogo.xml b/core/res/res/drawable-nodpi/platlogo.xml
index a6dee8a..f5bbadc 100644
--- a/core/res/res/drawable-nodpi/platlogo.xml
+++ b/core/res/res/drawable-nodpi/platlogo.xml
@@ -1,6 +1,5 @@
-<?xml version="1.0" encoding="utf-8"?>
 <!--
-Copyright (C) 2017 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.
@@ -14,36 +13,21 @@
     See the License for the specific language governing permissions and
     limitations under the License.
 -->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="48dp"
-    android:height="48dp"
-    android:viewportWidth="48"
-    android:viewportHeight="48">
-    <group>
-        <path
-            android:fillColor="#2C292A"
-            android:fillType="evenOdd"
-            android:pathData="M6,26a20,20 0 0,1 40,0a20,20 0 0,1 -40,0z"/>
-        <path
-            android:fillColor="#FAFAFA"
-            android:fillType="evenOdd"
-            android:pathData="M4,24a20,20 0 0,1 40,0a20,20 0 0,1 -40,0z"/>
-        <path
-            android:fillColor="#2C292A"
-            android:fillType="evenOdd"
-            android:pathData="M2,22a20,20 0 0,1 40,0a20,20 0 0,1 -40,0z"/>
-        <path
-            android:fillColor="#00000000"
-            android:strokeColor="#453F41"
-            android:strokeWidth="1"
-            android:fillType="evenOdd"
-            android:pathData="M26.5 29.5v3c0 1.13-.87 2-2 2s-2-.87-2-2v-3h-1v3c0 1.13-.87 2-2 2s-2-.87-2-2v-3H17a1.5 1.5 0 0 1-1.5-1.5V17.5h13V28a1.5 1.5 0 0 1-1.5 1.5h-.5zM13.5 17.5c1.13 0 2 .87 2 2v7c0 1.13-.87 2-2 2s-2-.87-2-2v-7c0-1.13.87-2 2-2zM30.5 17.5c1.13 0 2 .87 2 2v7c0 1.13-.87 2-2 2s-2-.87-2-2v-7c0-1.13.87-2 2-2zM26.3 12.11A6.46 6.46 0 0 1 28.5 17v.5h-13V17a6.46 6.46 0 0 1 2.2-4.89l-.9-.9a.98.98 0 0 1 0-1.41.98.98 0 0 1 1.4 0l1.26 1.25A6.33 6.33 0 0 1 22 10.5c.87 0 1.73.2 2.54.55L25.8 9.8a.98.98 0 0 1 1.4 0 .98.98 0 0 1 0 1.4l-.9.91z"/>
-        <path
-            android:fillColor="#453F41"
-            android:fillType="evenOdd"
-            android:pathData="M20.16 14.5a.66.66 0 1 1-1.31 0c0-.36.29-.65.65-.65.36 0 .65.29.65.65zM25.16 14.5c0 .36-.3.66-.66.66a.65.65 0 1 1 .66-.66z"/>
-        <path
-            android:fillColor="#453F41"
-            android:pathData="M22 40.5c0.36 0 0.73-0.01 1.09-0.03l-0.18-3A15.77 15.77 0 0 1 22 37.5v3zm2.17-0.13a18.48 18.48 0 0 0 1.08-0.15l-0.53-2.96c-0.3 0.05-0.6 0.1-0.9 0.13l0.35 2.98zM26.32 40a18.37 18.37 0 0 0 1.05-0.28l-0.87-2.87a15.37 15.37 0 0 1-0.88 0.23l0.7 2.92zm2.1-0.64l-1.03-2.81a15.39 15.39 0 0 0 0.84-0.34l1.2 2.74a18.39 18.39 0 0 1-1 0.41zm1.99-0.87l-1.37-2.67a15.46 15.46 0 0 0 0.8-0.44l1.52 2.59a18.46 18.46 0 0 1-0.95 0.52zm1.89-1.11l-1.67-2.5a15.55 15.55 0 0 0 0.74-0.52l1.81 2.39a18.55 18.55 0 0 1-0.88 0.63zm1.75-1.33l-1.95-2.28a15.6 15.6 0 0 0 0.67-0.61l2.09 2.15a18.6 18.6 0 0 1-0.8 0.74zm1.6-1.55l-2.22-2.02a15.6 15.6 0 0 0 0.6-0.7l2.33 1.9a18.6 18.6 0 0 1-0.72 0.82zM37 32.82l-2.43-1.76a15.53 15.53 0 0 0 0.5-0.75l2.54 1.6c-0.2 0.31-0.4 0.61-0.61 0.9zm1.15-1.8l-2.62-1.47a15.45 15.45 0 0 0 0.42-0.8l2.7 1.3a18.45 18.45 0 0 1-0.5 0.97zm0.95-1.98l-2.77-1.14a15.38 15.38 0 0 0 0.32-0.86l2.84 0.98a18.38 18.38 0 0 1-0.39 1.02zm0.72-2.09c0.1-0.34 0.18-0.7 0.26-1.05l-2.93-0.63a15.38 15.38 0 0 1-0.22 0.88l2.89 0.8zm0.46-2.15a18.52 18.52 0 0 0 0.13-1.08l-2.99-0.28a15.52 15.52 0 0 1-0.1 0.9l2.96 0.46zm0.2-2.2a18.81 18.81 0 0 0 0-1.1l-3 0.08a16 16 0 0 1 0 0.92l3 0.1zm-0.06-2.2a18.54 18.54 0 0 0-0.12-1.07l-2.97 0.43c0.04 0.3 0.08 0.6 0.1 0.9l3-0.25zm-0.31-2.15a18.39 18.39 0 0 0-0.25-1.06l-2.9 0.78a15.39 15.39 0 0 1 0.21 0.89l2.94-0.6zm-0.57-2.12l-2.85 0.95a15.37 15.37 0 0 0-0.31-0.85l2.78-1.12a18.37 18.37 0 0 1 0.38 1.02zm-0.83-2.06l-2.71 1.29a15.44 15.44 0 0 0-0.42-0.81l2.63-1.45a18.44 18.44 0 0 1 0.5 0.97zm-1.03-1.88l-2.54 1.6a15.53 15.53 0 0 0-0.5-0.76l2.44-1.74 0.6 0.9zm-1.28-1.79l-2.33 1.88a15.6 15.6 0 0 0-0.6-0.69l2.23-2.02a18.6 18.6 0 0 1 0.7 0.83zm-1.48-1.63l-2.1 2.14a15.6 15.6 0 0 0-0.67-0.62l1.97-2.26a18.6 18.6 0 0 1 0.8 0.74zM33.24 7.3l-1.82 2.38a15.55 15.55 0 0 0-0.74-0.53l1.68-2.49c0.3 0.2 0.6 0.42 0.88 0.64zm-1.71-1.17L29.98 8.7a15.47 15.47 0 0 0-0.8-0.45l1.4-2.66a18.47 18.47 0 0 1 0.95 0.54zm-1.95-1.02l-1.23 2.74A15.4 15.4 0 0 0 27.5 7.5l1.06-2.8a18.4 18.4 0 0 1 1.01 0.4zm-2.06-0.78l-0.9 2.86a15.37 15.37 0 0 0-0.87-0.24l0.72-2.92a18.37 18.37 0 0 1 1.05 0.3zM25.38 3.8a18.47 18.47 0 0 0-1.08-0.17l-0.37 2.98c0.3 0.04 0.6 0.08 0.9 0.14l0.55-2.95zm-2.2-0.27A18.75 18.75 0 0 0 22.1 3.5l-0.02 3L23 6.53l0.19-3zM21 3.53a18.6 18.6 0 0 0-1.08 0.09l0.33 2.98a15.6 15.6 0 0 1 0.91-0.08l-0.16-3zm-2.16 0.24A18.4 18.4 0 0 0 17.76 4l0.68 2.92a15.4 15.4 0 0 1 0.9-0.18l-0.51-2.96zm-2.14 0.5l0.86 2.88a15.37 15.37 0 0 0-0.86 0.28l-1.03-2.81a18.37 18.37 0 0 1 1.03-0.35zm-2.07 0.76l1.2 2.75a15.42 15.42 0 0 0-0.83 0.4L13.63 5.5a18.42 18.42 0 0 1 0.99-0.47zM12.7 6l1.5 2.6a15.5 15.5 0 0 0-0.76 0.48l-1.66-2.5A18.5 18.5 0 0 1 12.7 6zm-1.83 1.22l1.8 2.4a15.58 15.58 0 0 0-0.7 0.57L10.01 7.9a18.58 18.58 0 0 1 0.85-0.68zM9.19 8.66l2.07 2.16a15.6 15.6 0 0 0-0.63 0.65l-2.2-2.04a18.6 18.6 0 0 1 0.76-0.77zm-1.51 1.63l2.32 1.9a15.57 15.57 0 0 0-0.56 0.72l-2.42-1.76a18.57 18.57 0 0 1 0.66-0.86zm-1.23 1.69l2.52 1.62a15.5 15.5 0 0 0-0.47 0.78l-2.61-1.47a18.5 18.5 0 0 1 0.56-0.93zm-1.08 1.9l2.7 1.32a15.41 15.41 0 0 0-0.38 0.83l-2.77-1.15a18.41 18.41 0 0 1 0.45-1zm-0.85 2.04l2.84 0.98a15.37 15.37 0 0 0-0.28 0.87L4.2 16.96c0.1-0.35 0.2-0.7 0.32-1.04zm-0.6 2.12a18.43 18.43 0 0 0-0.2 1.07l2.97 0.47c0.05-0.3 0.1-0.6 0.17-0.9l-2.93-0.64zm-0.34 2.18a18.65 18.65 0 0 0-0.07 1.09l3 0.11 0.06-0.91-2.99-0.29zm-0.08 2.2a18.7 18.7 0 0 0 0.06 1.1l3-0.25a15.7 15.7 0 0 1-0.06-0.91l-3 0.07zm0.18 2.18a18.44 18.44 0 0 0 0.18 1.07l2.95-0.6a15.44 15.44 0 0 1-0.16-0.9L3.68 24.6zm0.43 2.14l2.9-0.77a15.37 15.37 0 0 0 0.26 0.88l-2.85 0.94a18.37 18.37 0 0 1-0.3-1.05zm0.7 2.1l2.78-1.11a15.4 15.4 0 0 0 0.36 0.83l-2.71 1.27a18.4 18.4 0 0 1-0.44-1zm0.9 1.95l2.65-1.43a15.48 15.48 0 0 0 0.45 0.8l-2.55 1.57a18.48 18.48 0 0 1-0.54-0.94zm1.17 1.87l2.45-1.73a15.56 15.56 0 0 0 0.54 0.73l-2.34 1.87a18.56 18.56 0 0 1-0.65-0.87zm1.37 1.72l2.23-2a15.6 15.6 0 0 0 0.63 0.65l-2.1 2.14a18.6 18.6 0 0 1-0.76-0.79zm1.58 1.56l1.98-2.26c0.22 0.2 0.46 0.39 0.7 0.58l-1.84 2.37a18.59 18.59 0 0 1-0.84-0.7zm1.66 1.28l1.7-2.46a15.52 15.52 0 0 0 0.77 0.5l-1.56 2.56a18.52 18.52 0 0 1-0.91-0.6zm1.87 1.14l1.4-2.65a15.43 15.43 0 0 0 0.82 0.4l-1.24 2.73a18.43 18.43 0 0 1-0.98-0.48zm2 0.91l1.08-2.8a15.37 15.37 0 0 0 0.86 0.3l-0.9 2.86a18.37 18.37 0 0 1-1.04-0.36zm2.1 0.67a18.4 18.4 0 0 0 1.07 0.23l0.56-2.94a15.4 15.4 0 0 1-0.9-0.2l-0.72 2.91zm2.18 0.41a18.57 18.57 0 0 0 1.08 0.1l0.2-2.99a15.57 15.57 0 0 1-0.9-0.09l-0.38 2.98zm2.2 0.15H22v-3h-0.13l-0.03 3z"/>
-    </group>
+<vector
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:name="vector"
+    android:width="640dp"
+    android:height="640dp"
+    android:viewportWidth="64"
+    android:viewportHeight="64">
+    <path
+        android:name="bg"
+        android:pathData="M 27 43 L 32 43 C 38.075 43 43 38.075 43 32 C 43 25.925 38.075 21 32 21 C 25.925 21 21 25.925 21 32 L 21 64"
+        android:strokeColor="#6823a1"
+        android:strokeWidth="16"/>
+    <path
+        android:name="fg"
+        android:pathData="M 29 43 L 32 43 C 38.075 43 43 38.075 43 32 C 43 25.925 38.075 21 32 21 C 25.925 21 21 25.925 21 32 L 21 64"
+        android:strokeColor="#ff0000"
+        android:strokeWidth="8"/>
 </vector>
diff --git a/core/res/res/drawable-nodpi/platlogo_m.xml b/core/res/res/drawable-nodpi/platlogo_m.xml
index aacf674..8e43638 100644
--- a/core/res/res/drawable-nodpi/platlogo_m.xml
+++ b/core/res/res/drawable-nodpi/platlogo_m.xml
@@ -18,23 +18,4 @@
         android:height="480dp"
         android:viewportWidth="48.0"
         android:viewportHeight="48.0">
-    <!--<path
-        android:pathData="M25.0,25.0m-20.5,0.0a20.5,20.5,0,1,1,41.0,0.0a20.5,20.5,0,1,1,-41.0,0.0"
-        android:fillAlpha="0.066"
-        android:fillColor="#000000"/>-->
-    <path
-        android:pathData="M24.0,24.0m-20.0,0.0a20.0,20.0,0,1,1,40.0,0.0a20.0,20.0,0,1,1,-40.0,0.0"
-        android:fillColor="#FFC107"/>
-    <path
-        android:pathData="M44,24.2010101 L33.9004889,14.101499 L14.101499,33.9004889 L24.2010101,44 C29.2525804,43.9497929 34.2887564,41.9975027 38.1431296,38.1431296 C41.9975027,34.2887564 43.9497929,29.2525804 44,24.2010101 Z"
-        android:fillColor="#FE9F00"/>
-    <path
-        android:pathData="M24.0,24.0m-14.0,0.0a14.0,14.0,0,1,1,28.0,0.0a14.0,14.0,0,1,1,-28.0,0.0"
-        android:fillColor="#FED44F"/>
-    <path
-        android:pathData="M37.7829445,26.469236 L29.6578482,18.3441397 L18.3441397,29.6578482 L26.469236,37.7829445 C29.1911841,37.2979273 31.7972024,36.0037754 33.9004889,33.9004889 C36.0037754,31.7972024 37.2979273,29.1911841 37.7829445,26.469236 Z"
-        android:fillColor="#FFC107"/>
-    <path
-        android:pathData="M24.0,24.0m-8.0,0.0a8.0,8.0,0,1,1,16.0,0.0a8.0,8.0,0,1,1,-16.0,0.0"
-        android:fillColor="#FFFFFF"/>
 </vector>
diff --git a/core/res/res/drawable-nodpi/stat_sys_adb.xml b/core/res/res/drawable-nodpi/stat_sys_adb.xml
index 2e2b395..0fde2cc 100644
--- a/core/res/res/drawable-nodpi/stat_sys_adb.xml
+++ b/core/res/res/drawable-nodpi/stat_sys_adb.xml
@@ -1,6 +1,5 @@
-<?xml version="1.0" encoding="utf-8"?>
 <!--
-Copyright (C) 2017 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.
@@ -14,24 +13,24 @@
     See the License for the specific language governing permissions and
     limitations under the License.
 -->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="24dp"
-    android:height="24dp"
-    android:viewportWidth="24"
-    android:viewportHeight="24">
-    <group>
+<vector
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:name="vector"
+    android:width="48dp"
+    android:height="48dp"
+    android:viewportWidth="48"
+    android:viewportHeight="48">
+    <group android:name="stat_sys_adb">
         <path
-            android:fillColor="#FFFFFF"
-            android:fillAlpha=".33"
-            android:fillType="evenOdd"
-            android:pathData="M5.71 18.29A8.99 8.99 0 0 0 22 13c0-3-1.46-5.65-3.71-7.29A8.99 8.99 0 0 0 2 11c0 3 1.46 5.65 3.71 7.29z"/>
+            android:name="outer"
+            android:pathData="M 18 30 L 24 30 C 29.523 30 34 25.523 34 20 C 34 14.477 29.523 10 24 10 C 18.477 10 14 14.477 14 20 L 14 44"
+            android:strokeColor="#000000"
+            android:strokeWidth="10"/>
         <path
-            android:fillColor="#FFFFFF"
-            android:fillType="evenOdd"
-            android:pathData="M7.25 19.18A8.5 8.5 0 0 0 19.19 7.24 9 9 0 0 1 7.24 19.19z"/>
-        <path
-            android:fillColor="#FFFFFF"
-            android:fillAlpha=".33"
-            android:pathData="M10.5 3a0.5 0.5 0 1 1 1 0v2.05a0.5 0.5 0 1 1-1 0V3zm3.1 0.42a0.5 0.5 0 0 1 0.93 0.39l-0.8 1.88A0.5 0.5 0 1 1 12.8 5.3l0.8-1.88zm2.7 1.57a0.5 0.5 0 1 1 0.71 0.7l-1.45 1.46a0.5 0.5 0 0 1-0.7-0.71l1.44-1.45zm1.9 2.5a0.5 0.5 0 0 1 0.38 0.92l-1.9 0.77a0.5 0.5 0 0 1-0.37-0.93l1.9-0.77zM19 10.5a0.5 0.5 0 1 1 0 1h-2.05a0.5 0.5 0 0 1 0-1H19zm-0.42 3.1a0.5 0.5 0 0 1-0.39 0.93l-1.88-0.8a0.5 0.5 0 1 1 0.39-0.92l1.88 0.8zm-1.57 2.7a0.5 0.5 0 1 1-0.7 0.71l-1.46-1.45a0.5 0.5 0 0 1 0.71-0.7l1.45 1.44zm-2.5 1.9a0.5 0.5 0 1 1-0.92 0.38l-0.77-1.9a0.5 0.5 0 0 1 0.93-0.37l0.77 1.9zM11.5 19a0.5 0.5 0 1 1-1 0v-2.05a0.5 0.5 0 0 1 1 0V19zm-3.1-0.42a0.5 0.5 0 0 1-0.93-0.39l0.8-1.88A0.5 0.5 0 0 1 9.2 16.7l-0.8 1.88zm-2.7-1.57a0.5 0.5 0 1 1-0.71-0.7l1.45-1.46a0.5 0.5 0 0 1 0.7 0.71L5.7 17.01zm-1.9-2.48a0.5 0.5 0 0 1-0.38-0.92l1.88-0.8a0.5 0.5 0 0 1 0.4 0.92l-1.9 0.8zM3 11.5a0.5 0.5 0 1 1 0-1h2.05a0.5 0.5 0 1 1 0 1H3zm0.42-3.1A0.5 0.5 0 0 1 3.8 7.46l1.88 0.8A0.5 0.5 0 1 1 5.3 9.2L3.42 8.4zm1.57-2.7a0.5 0.5 0 1 1 0.7-0.71l1.46 1.45a0.5 0.5 0 0 1-0.71 0.7L4.99 5.7zm2.5-1.9A0.5 0.5 0 0 1 8.4 3.41l0.77 1.9a0.5 0.5 0 0 1-0.93 0.37L7.48 3.8z"/>
+            android:name="inner"
+            android:pathData="M 19 30 L 24 30 C 29.523 30 34 25.523 34 20 C 34 14.477 29.523 10 24 10 C 18.477 10 14 14.477 14 20 L 14 44"
+            android:strokeColor="#000000"
+            android:strokeAlpha="0"
+            android:strokeWidth="6"/>
     </group>
-</vector>
\ No newline at end of file
+</vector>
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/drawable/ic_settings_24dp.xml b/core/res/res/drawable/ic_settings_24dp.xml
index fc75f04..c70b122 100644
--- a/core/res/res/drawable/ic_settings_24dp.xml
+++ b/core/res/res/drawable/ic_settings_24dp.xml
@@ -16,9 +16,9 @@
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
         android:width="24dp"
         android:height="24dp"
-        android:viewportWidth="48.0"
-        android:viewportHeight="48.0">
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
     <path
-        android:fillColor="#FF000000"
-        android:pathData="M38.86 25.95c.08,-.64.14,-1.29.14,-1.95s-.06,-1.31,-.14,-1.95l4.23,-3.31c.38,-.3.49,-.84.24,-1.28l-4,-6.93c-.25,-.43,-.77,-.61,-1.22,-.43l-4.98 2.01c-1.03,-.79,-2.16,-1.46,-3.38,-1.97L29 4.84c-.09,-.47,-.5,-.84,-1,-.84h-8c-.5 0,-.91.37,-.99.84l-.75 5.3c-1.22.51,-2.35 1.17,-3.38 1.97L9.9 10.1c-.45,-.17,-.97 0,-1.22.43l-4 6.93c-.25.43,-.14.97.24 1.28l4.22 3.31C9.06 22.69 9 23.34 9 24s.06 1.31.14 1.95l-4.22 3.31c-.38.3,-.49.84,-.24 1.28l4 6.93c.25.43.77.61 1.22.43l4.98,-2.01c1.03.79 2.16 1.46 3.38 1.97l.75 5.3c.08.47.49.84.99.84h8c.5 0 .91,-.37.99,-.84l.75,-5.3c1.22,-.51 2.35,-1.17 3.38,-1.97l4.98 2.01c.45.17.97 0 1.22,-.43l4,-6.93c.25,-.43.14,-.97,-.24,-1.28l-4.22,-3.31zM24 31c-3.87 0,-7,-3.13,-7,-7s3.13,-7 7,-7 7 3.13 7 7,-3.13 7,-7 7z"/>
+        android:pathData="M19.4,13.0c0.0,-0.3 0.1,-0.6 0.1,-1.0s0.0,-0.7 -0.1,-1.0l2.1,-1.7c0.2,-0.2 0.2,-0.4 0.1,-0.6l-2.0,-3.5C19.5,5.1 19.3,5.0 19.0,5.1l-2.5,1.0c-0.5,-0.4 -1.1,-0.7 -1.7,-1.0l-0.4,-2.6C14.5,2.2 14.2,2.0 14.0,2.0l-4.0,0.0C9.8,2.0 9.5,2.2 9.5,2.4L9.1,5.1C8.5,5.3 8.0,5.7 7.4,6.1L5.0,5.1C4.7,5.0 4.5,5.1 4.3,5.3l-2.0,3.5C2.2,8.9 2.3,9.2 2.5,9.4L4.6,11.0c0.0,0.3 -0.1,0.6 -0.1,1.0s0.0,0.7 0.1,1.0l-2.1,1.7c-0.2,0.2 -0.2,0.4 -0.1,0.6l2.0,3.5C4.5,18.9 4.7,19.0 5.0,18.9l2.5,-1.0c0.5,0.4 1.1,0.7 1.7,1.0l0.4,2.6c0.0,0.2 0.2,0.4 0.5,0.4l4.0,0.0c0.2,0.0 0.5,-0.2 0.5,-0.4l0.4,-2.6c0.6,-0.3 1.2,-0.6 1.7,-1.0l2.5,1.0c0.2,0.1 0.5,0.0 0.6,-0.2l2.0,-3.5c0.1,-0.2 0.1,-0.5 -0.1,-0.6L19.4,13.0zM12.0,15.5c-1.9,0.0 -3.5,-1.6 -3.5,-3.5s1.6,-3.5 3.5,-3.5s3.5,1.6 3.5,3.5S13.9,15.5 12.0,15.5z"
+        android:fillColor="#FF000000" />
 </vector>
diff --git a/core/res/res/drawable/ic_signal_cellular_alt_24px.xml b/core/res/res/drawable/ic_signal_cellular_alt_24px.xml
new file mode 100644
index 0000000..29f1f43
--- /dev/null
+++ b/core/res/res/drawable/ic_signal_cellular_alt_24px.xml
@@ -0,0 +1,40 @@
+<?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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="20dp"
+    android:height="21dp"
+    android:viewportWidth="20"
+    android:viewportHeight="21">
+
+    <group
+            android:translateX="-31.000000"
+            android:translateY="-77.000000">
+        <group
+                android:translateX="24.000000"
+                android:translateY="72.000000">
+            <path
+                android:fillType="evenOdd"
+                android:strokeWidth="1"
+                android:pathData="M 0 0 H 32 V 32 H 0 V 0 Z" />
+            <path
+                android:fillColor="#4285F4"
+                android:strokeWidth="1"
+                android:pathData="M23,5 L27,5 L27,26 L23,26 L23,5 Z M7,18.125 L11,18.125 L11,26 L7,26 L7,18.125 Z
+M15,11.5625 L19,11.5625 L19,26 L15,26 L15,11.5625 Z" />
+        </group>
+    </group>
+</vector>
\ No newline at end of file
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/layout/autofill_dataset_picker_fullscreen.xml b/core/res/res/layout/autofill_dataset_picker_fullscreen.xml
new file mode 100644
index 0000000..07298c1
--- /dev/null
+++ b/core/res/res/layout/autofill_dataset_picker_fullscreen.xml
@@ -0,0 +1,48 @@
+<?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.
+-->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/autofill_dataset_picker"
+    style="@style/AutofillDatasetPicker"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent">
+
+    <TextView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="@string/autofill_window_title"
+        android:layout_above="@+id/autofill_dataset_container"
+        android:layout_alignStart="@+id/autofill_dataset_container"
+        android:textSize="16sp"/>
+
+    <!-- autofill_container is the common parent for inserting authentication item or
+         autofill_dataset_list-->
+    <FrameLayout
+        android:id="@+id/autofill_dataset_container"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_centerInParent="true">
+        <ListView
+            android:id="@+id/autofill_dataset_list"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:clickable="true"
+            android:divider="@null"
+            android:drawSelectorOnTop="true"
+            android:visibility="gone"/>
+    </FrameLayout>
+
+</RelativeLayout>
diff --git a/core/res/res/layout/notification_template_messaging_group.xml b/core/res/res/layout/notification_template_messaging_group.xml
index 4ac308a..bd1030e 100644
--- a/core/res/res/layout/notification_template_messaging_group.xml
+++ b/core/res/res/layout/notification_template_messaging_group.xml
@@ -28,9 +28,9 @@
         android:scaleType="centerCrop"
         android:importantForAccessibility="no" />
     <com.android.internal.widget.RemeasuringLinearLayout
-        android:id="@+id/message_group_and_sender_container"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
+        android:layout_weight="1"
         android:orientation="vertical">
         <com.android.internal.widget.ImageFloatingTextView
             android:id="@+id/message_name"
@@ -44,4 +44,10 @@
             android:spacing="2dp"
             android:layout_weight="1"/>
     </com.android.internal.widget.RemeasuringLinearLayout>
+    <FrameLayout
+        android:id="@+id/messaging_group_icon_container"
+        android:layout_width="@dimen/messaging_avatar_size"
+        android:layout_height="@dimen/messaging_avatar_size"
+        android:layout_marginStart="12dp"
+        android:visibility="gone"/>
 </com.android.internal.widget.MessagingGroup>
diff --git a/core/res/res/layout/notification_template_messaging_message.xml b/core/res/res/layout/notification_template_messaging_image_message.xml
similarity index 71%
copy from core/res/res/layout/notification_template_messaging_message.xml
copy to core/res/res/layout/notification_template_messaging_image_message.xml
index ab6466c..6ca4dcd 100644
--- a/core/res/res/layout/notification_template_messaging_message.xml
+++ b/core/res/res/layout/notification_template_messaging_image_message.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
-  ~ Copyright (C) 2017 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.
@@ -14,8 +14,11 @@
   ~ See the License for the specific language governing permissions and
   ~ limitations under the License
   -->
-<com.android.internal.widget.MessagingMessage
+<com.android.internal.widget.MessagingImageMessage
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/message_text"
-    style="@style/Widget.Material.Notification.MessagingText"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:layout_marginTop="@dimen/messaging_image_extra_spacing"
+    android:scaleType="fitStart"
 />
diff --git a/core/res/res/layout/notification_template_messaging_message.xml b/core/res/res/layout/notification_template_messaging_text_message.xml
similarity index 94%
rename from core/res/res/layout/notification_template_messaging_message.xml
rename to core/res/res/layout/notification_template_messaging_text_message.xml
index ab6466c..e728e69 100644
--- a/core/res/res/layout/notification_template_messaging_message.xml
+++ b/core/res/res/layout/notification_template_messaging_text_message.xml
@@ -14,7 +14,7 @@
   ~ See the License for the specific language governing permissions and
   ~ limitations under the License
   -->
-<com.android.internal.widget.MessagingMessage
+<com.android.internal.widget.MessagingTextMessage
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/message_text"
     style="@style/Widget.Material.Notification.MessagingText"
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-mcc302-mnc220/config.xml b/core/res/res/values-mcc302-mnc220/config.xml
index 9a3d736..8774334 100644
--- a/core/res/res/values-mcc302-mnc220/config.xml
+++ b/core/res/res/values-mcc302-mnc220/config.xml
@@ -36,7 +36,7 @@
 
     <!-- Values for GPS configuration (Telus) -->
     <string-array translatable="false" name="config_gpsParameters">
-        <item>SUPL_HOST=supl.telusmobility.com</item>
+        <item>SUPL_HOST=supl.google.com</item>
         <item>SUPL_PORT=7275</item>
         <item>SUPL_VER=0x20000</item>
         <item>SUPL_MODE=1</item>
diff --git a/core/res/res/values-mcc302-mnc221/config.xml b/core/res/res/values-mcc302-mnc221/config.xml
index 007fd04..05896b1 100644
--- a/core/res/res/values-mcc302-mnc221/config.xml
+++ b/core/res/res/values-mcc302-mnc221/config.xml
@@ -34,7 +34,7 @@
 
     <!-- Values for GPS configuration (Telus) -->
     <string-array translatable="false" name="config_gpsParameters">
-        <item>SUPL_HOST=supl.telusmobility.com</item>
+        <item>SUPL_HOST=supl.google.com</item>
         <item>SUPL_PORT=7275</item>
         <item>SUPL_VER=0x20000</item>
         <item>SUPL_MODE=1</item>
diff --git a/core/res/res/values-television/dimens.xml b/core/res/res/values-television/dimens.xml
index 4c25225..aa56251 100644
--- a/core/res/res/values-television/dimens.xml
+++ b/core/res/res/values-television/dimens.xml
@@ -20,4 +20,8 @@
      <item type="dimen" format="float" name="ambient_shadow_alpha">0.15</item>
      <item type="dimen" format="float" name="spot_shadow_alpha">0.3</item>
 
+     <!-- Max width/height of the autofill data set picker as a fraction of the screen width/height -->
+     <dimen name="autofill_dataset_picker_max_width">60%</dimen>
+     <dimen name="autofill_dataset_picker_max_height">70%</dimen>
+
 </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/attrs.xml b/core/res/res/values/attrs.xml
index 005d07d..d26567e 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -7918,6 +7918,10 @@
              android.content.pm.PackageInfo#getLongVersionCode()} for the target package.
         -->
         <attr name="maxLongVersionCode" format="string" />
+        <!-- The resource id of view that contains the URL bar of the HTML page being loaded.
+             Typically used when compatibility mode is used in a browser.
+        -->
+        <attr name="urlBarResourceId" format="string" />
     </declare-styleable>
 
     <!-- =============================== -->
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 287f296..32fe2b2 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -2558,6 +2558,9 @@
         <!-- Package name of base package whose resources will be overlaid. -->
         <attr name="targetPackage" />
 
+        <!-- Category of the resource overlay. -->
+        <attr name="category" format="string"/>
+
         <!-- Load order of overlay package. -->
         <attr name="priority" />
 
diff --git a/core/res/res/values/colors_material.xml b/core/res/res/values/colors_material.xml
index ce4ac61..6e8134b 100644
--- a/core/res/res/values/colors_material.xml
+++ b/core/res/res/values/colors_material.xml
@@ -78,9 +78,9 @@
     <item name="secondary_content_alpha_material_dark" format="float" type="dimen">.7</item>
     <item name="secondary_content_alpha_material_light" format="float" type="dimen">0.54</item>
 
-    <item name="highlight_alpha_material_light" format="float" type="dimen">0.16</item>
-    <item name="highlight_alpha_material_dark" format="float" type="dimen">0.32</item>
-    <item name="highlight_alpha_material_colored" format="float" type="dimen">0.48</item>
+    <item name="highlight_alpha_material_light" format="float" type="dimen">0.10</item>
+    <item name="highlight_alpha_material_dark" format="float" type="dimen">0.10</item>
+    <item name="highlight_alpha_material_colored" format="float" type="dimen">0.10</item>
 
     <!-- Primary & accent colors -->
     <eat-comment />
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 2944ad3..b0f3ad51 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -999,7 +999,7 @@
     <integer name="config_shortPressOnSleepBehavior">0</integer>
 
     <!-- Time to wait while a button is pressed before triggering a very long press. -->
-    <integer name="config_veryLongPressTimeout">6000</integer>
+    <integer name="config_veryLongPressTimeout">3500</integer>
 
     <!-- Package name for default keyguard appwidget [DO NOT TRANSLATE] -->
     <string name="widget_default_package_name" translatable="false"></string>
@@ -1075,6 +1075,14 @@
         <item>10</item>
     </integer-array>
 
+    <!-- The URI to associate with each ringtone effect constant, intended to be used with the
+         android.os.VibrationEffect#get(Uri, Context) API.
+         The position of the string in the string-array determines which ringtone effect is chosen.
+         For example, if the URI passed into get match the third string in the string-array, then
+         RINGTONE_3 will be the returned effect -->
+    <string-array translatable="false" name="config_ringtoneEffectUris">
+    </string-array>
+
     <bool name="config_use_strict_phone_number_comparation">false</bool>
 
     <!-- Display low battery warning when battery level dips to this value.
@@ -2320,6 +2328,10 @@
     <string name="config_customVpnAlwaysOnDisconnectedDialogComponent" translatable="false"
             >com.android.vpndialogs/com.android.vpndialogs.AlwaysOnDisconnectedDialog</string>
 
+    <!-- Name of the dialog that is used to install the carrier app when the SIM is inserted -->
+    <string name="config_carrierAppInstallDialogComponent" translatable="false"
+            >com.android.simappdialog/com.android.simappdialog.InstallCarrierAppActivity</string>
+
     <!-- Apps that are authorized to access shared accounts, overridden by product overlays -->
     <string name="config_appsAuthorizedForSharedAccounts" translatable="false">;com.android.settings;</string>
 
@@ -2486,9 +2498,9 @@
     <string-array translatable="false" name="config_globalActionsList">
         <item>power</item>
         <item>restart</item>
-        <item>screenshot</item>
-        <item>logout</item>
         <item>lockdown</item>
+        <item>logout</item>
+        <item>screenshot</item>
         <item>bugreport</item>
         <item>users</item>
     </string-array>
@@ -2905,8 +2917,8 @@
     <item name="config_pictureInPictureAspectRatioLimitForMinSize" format="float" type="dimen">1.777778</item>
 
     <!-- The default gravity for the picture-in-picture window.
-         Currently, this maps to Gravity.BOTTOM | Gravity.RIGHT -->
-    <integer name="config_defaultPictureInPictureGravity">0x55</integer>
+         Currently, this maps to Gravity.TOP | Gravity.RIGHT -->
+    <integer name="config_defaultPictureInPictureGravity">0x35</integer>
 
     <!-- The minimum aspect ratio (width/height) that is supported for picture-in-picture.  Any
          ratio smaller than this is considered too tall and thin to be usable. Currently, this
@@ -3306,4 +3318,9 @@
 
     <!-- whether to show dual bar -->
     <bool name="config_dual_bar">false</bool>
+    <!-- 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/dimens.xml b/core/res/res/values/dimens.xml
index e610efd..cfaab6a 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -262,6 +262,18 @@
     <!-- The spacing between messages in Notification.MessagingStyle -->
     <dimen name="notification_messaging_spacing">6dp</dimen>
 
+    <!-- The rounding for messaging images -->
+    <dimen name="messaging_image_rounding">4dp</dimen>
+
+    <!-- The minimum size for any image in messaging style in order to be displayed -->
+    <dimen name="messaging_image_min_size">44dp</dimen>
+
+    <!-- The maximum size for any image in messaging style in order to be displayed -->
+    <dimen name="messaging_image_max_height">136dp</dimen>
+
+    <!-- Extra spacing before and after images in messaging style -->
+    <dimen name="messaging_image_extra_spacing">8dp</dimen>
+
     <!-- Preferred width and height of the search view. -->
     <dimen name="search_view_preferred_width">320dip</dimen>
     <dimen name="search_view_preferred_height">48dip</dimen>
@@ -614,7 +626,8 @@
     <dimen name="messaging_avatar_size">@dimen/notification_right_icon_size</dimen>
 
     <!-- Max width/height of the autofill data set picker as a fraction of the screen width/height -->
-    <dimen name="autofill_dataset_picker_max_size">90%</dimen>
+    <dimen name="autofill_dataset_picker_max_width">90%</dimen>
+    <dimen name="autofill_dataset_picker_max_height">90%</dimen>
 
     <!-- Max height of the the autofill save custom subtitle as a fraction of the screen width/height -->
     <dimen name="autofill_save_custom_subtitle_max_height">20%</dimen>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 93f22f25..82fefef 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2869,6 +2869,7 @@
       <public name="outlineSpotShadowColor" />
       <public name="outlineAmbientShadowColor" />
       <public name="maxLongVersionCode" />
+      <public name="urlBarResourceId" />
     </public-group>
 
     <public-group type="style" first-id="0x010302e0">
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index ec81df7..837113d 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -182,6 +182,8 @@
     <string name="notification_channel_voice_mail">Voicemail messages</string>
     <!-- Telephony notification channel name for a channel containing wifi calling status notifications. -->
     <string name="notification_channel_wfc">Wi-Fi calling</string>
+    <!-- Telephony notification channel name for a channel containing SIM notifications -->
+    <string name="notification_channel_sim">SIM status</string>
 
     <!-- Displayed to tell the user that peer changed TTY mode -->
     <string name="peerTtyModeFull">Peer requested TTY Mode FULL</string>
@@ -547,7 +549,7 @@
     <string name="global_action_voice_assist">Voice Assist</string>
 
     <!-- label for item that locks the phone and enforces that it can't be unlocked without strong authentication. [CHAR LIMIT=15] -->
-    <string name="global_action_lockdown">Enter lockdown</string>
+    <string name="global_action_lockdown">Lockdown</string>
 
     <!-- Text to use when the number in a notification info is too large
          (greater than status_bar_notification_info_maxnum, defined in
@@ -2169,6 +2171,9 @@
     <!-- Text to show in the auto complete drop down list on a text view when the WebView can auto fill the entire form but the user has not configured an AutoFill profile [CHAR-LIMIT=19] -->
     <string name="setup_autofill">Set up Autofill</string>
 
+    <!-- Title of fullscreen autofill window [CHAR-LIMIT=80] -->
+    <string name="autofill_window_title">Autofill</string>
+
     <!-- String used to separate FirstName and LastName when writing out a local name
          e.g. John<separator>Smith [CHAR-LIMIT=NONE]-->
     <string name="autofill_address_name_separator">\u0020</string>
@@ -3194,10 +3199,12 @@
     <!-- See SIM_ADDED_DIALOG.  This is the button of that dialog. -->
     <string name="sim_restart_button">Restart</string>
     <!-- See Carrier_App_Dialog. This is the message of that dialog. -->
-    <string name="carrier_app_dialog_message">To get your new SIM working properly, you\'ll need to install and open an app from your carrier.</string>
-    <!-- See Carrier_App_Dialog. This is the button of that dialog. -->
-    <string name="carrier_app_dialog_button">GET THE APP</string>
-    <string name="carrier_app_dialog_not_now">NOT NOW</string>
+    <string name="install_carrier_app_notification_title">Activate mobile service</string>
+    <string name="install_carrier_app_notification_text">
+        Download the carrier app to activate your new SIM
+    </string>
+    <!-- See Carrier_App_Notification. This is the button of that dialog. -->
+    <string name="install_carrier_app_notification_button">Download app</string>
     <!-- See carrier_app_notification. This is the headline. -->
     <string name="carrier_app_notification_title">New SIM inserted</string>
     <string name="carrier_app_notification_text">Tap to set it up</string>
@@ -4854,4 +4861,11 @@
 
     <!-- Notification action for editing a screenshot (drawing on it, cropping it, etc) -->
     <string name="screenshot_edit">Edit</string>
+
+    <!-- Title for the notification channel notifying user of settings system changes (i.e. Do Not Disturb has changed). [CHAR LIMIT=NONE] -->
+    <string name="notification_channel_system_changes">System changes</string>
+    <!-- Title of notification indicating do not disturb settings have changed when upgrading to P -->
+    <string name="zen_upgrade_notification_title">Do Not Disturb has changed</string>
+    <!-- Content of notification indicating users can tap on the notification to go to dnd behavior settings -->
+    <string name="zen_upgrade_notification_content">Tap to check your behavior settings for interruptions</string>
 </resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 1ea62d5..d45fc53 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -574,6 +574,7 @@
   <java-symbol type="string" name="notification_channel_sms" />
   <java-symbol type="string" name="notification_channel_voice_mail" />
   <java-symbol type="string" name="notification_channel_wfc" />
+  <java-symbol type="string" name="notification_channel_sim" />
   <java-symbol type="string" name="SetupCallDefault" />
   <java-symbol type="string" name="accept" />
   <java-symbol type="string" name="activity_chooser_view_see_all" />
@@ -1383,6 +1384,7 @@
 
   <java-symbol type="drawable" name="ic_sim_card_multi_24px_clr" />
   <java-symbol type="drawable" name="ic_sim_card_multi_48px_clr" />
+  <java-symbol type="drawable" name="ic_signal_cellular_alt_24px" />
 
   <java-symbol type="drawable" name="stat_notify_mmcc_indication_icn" />
   <java-symbol type="drawable" name="autofilled_highlight"/>
@@ -1716,6 +1718,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" />
@@ -2071,6 +2074,7 @@
   <java-symbol type="string" name="config_customAdbPublicKeyConfirmationSecondaryUserComponent" />
   <java-symbol type="string" name="config_customVpnConfirmDialogComponent" />
   <java-symbol type="string" name="config_customVpnAlwaysOnDisconnectedDialogComponent" />
+  <java-symbol type="string" name="config_carrierAppInstallDialogComponent" />
   <java-symbol type="string" name="config_defaultNetworkScorerPackageName" />
   <java-symbol type="string" name="config_persistentDataPackageName" />
 
@@ -2770,9 +2774,9 @@
   <java-symbol type="array" name="resolver_target_actions_pin" />
   <java-symbol type="array" name="resolver_target_actions_unpin" />
 
-  <java-symbol type="string" name="carrier_app_dialog_message" />
-  <java-symbol type="string" name="carrier_app_dialog_button" />
-  <java-symbol type="string" name="carrier_app_dialog_not_now" />
+  <java-symbol type="string" name="install_carrier_app_notification_title" />
+  <java-symbol type="string" name="install_carrier_app_notification_text" />
+  <java-symbol type="string" name="install_carrier_app_notification_button" />
   <java-symbol type="string" name="carrier_app_notification_title" />
   <java-symbol type="string" name="carrier_app_notification_text" />
   <java-symbol type="string" name="negative_duration" />
@@ -2986,6 +2990,8 @@
   <!-- com.android.server.autofill -->
   <java-symbol type="layout" name="autofill_save"/>
   <java-symbol type="layout" name="autofill_dataset_picker"/>
+  <java-symbol type="layout" name="autofill_dataset_picker_fullscreen"/>
+  <java-symbol type="id" name="autofill_dataset_container"/>
   <java-symbol type="id" name="autofill_dataset_list"/>
   <java-symbol type="id" name="autofill_dataset_picker"/>
   <java-symbol type="id" name="autofill" />
@@ -3014,7 +3020,8 @@
   <java-symbol type="drawable" name="autofill_dataset_picker_background" />
   <java-symbol type="style" name="AutofillDatasetPicker" />
   <java-symbol type="style" name="AutofillSaveAnimation" />
-  <java-symbol type="dimen" name="autofill_dataset_picker_max_size"/>
+  <java-symbol type="dimen" name="autofill_dataset_picker_max_width"/>
+  <java-symbol type="dimen" name="autofill_dataset_picker_max_height"/>
   <java-symbol type="dimen" name="autofill_save_custom_subtitle_max_height"/>
   <java-symbol type="dimen" name="autofill_save_icon_max_size"/>
 
@@ -3102,6 +3109,7 @@
   <java-symbol type="string" name="notification_channel_retail_mode" />
   <java-symbol type="string" name="notification_channel_usb" />
   <java-symbol type="string" name="notification_channel_heavy_weight_app" />
+  <java-symbol type="string" name="notification_channel_system_changes" />
   <java-symbol type="string" name="config_defaultAutofillService" />
   <java-symbol type="string" name="config_defaultTextClassifierService" />
 
@@ -3168,7 +3176,8 @@
   <java-symbol type="dimen" name="chooser_service_spacing" />
   <java-symbol type="bool" name="config_showSysuiShutdown" />
 
-  <java-symbol type="layout" name="notification_template_messaging_message" />
+  <java-symbol type="layout" name="notification_template_messaging_text_message" />
+  <java-symbol type="layout" name="notification_template_messaging_image_message" />
   <java-symbol type="layout" name="notification_template_messaging_group" />
   <java-symbol type="id" name="message_text" />
   <java-symbol type="id" name="message_name" />
@@ -3183,6 +3192,11 @@
   <java-symbol type="id" name="clip_children_tag" />
   <java-symbol type="drawable" name="ic_reply_notification_large" />
   <java-symbol type="dimen" name="messaging_avatar_size" />
+  <java-symbol type="dimen" name="messaging_image_rounding" />
+  <java-symbol type="dimen" name="messaging_image_min_size" />
+  <java-symbol type="dimen" name="messaging_image_max_height" />
+  <java-symbol type="dimen" name="messaging_image_extra_spacing" />
+  <java-symbol type="id" name="messaging_group_icon_container" />
 
   <java-symbol type="integer" name="config_stableDeviceDisplayWidth" />
   <java-symbol type="integer" name="config_stableDeviceDisplayHeight" />
@@ -3249,4 +3263,12 @@
 
   <!-- whether to show dual bar -->
   <java-symbol type="bool" name="config_dual_bar" />
+  <java-symbol type="array" name="config_ringtoneEffectUris" />
+
+  <!-- For Wear devices -->
+  <java-symbol type="array" name="config_wearActivityModeRadios" />
+
+  <java-symbol type="string" name="zen_upgrade_notification_title" />
+  <java-symbol type="string" name="zen_upgrade_notification_content" />
+
 </resources>
diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index 9c3d8eb..eed0e46 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -41,58 +41,44 @@
          #Theme_Holo} or {@link #Theme_DeviceDefault}.</p>
     -->
     <style name="Theme">
-
         <item name="isLightTheme">false</item>
+
         <item name="colorForeground">@color/bright_foreground_dark</item>
         <item name="colorForegroundInverse">@color/bright_foreground_dark_inverse</item>
         <item name="colorBackground">@color/background_dark</item>
         <item name="colorBackgroundFloating">?attr/colorBackground</item>
         <item name="colorBackgroundCacheHint">?attr/colorBackground</item>
-
-        <item name="colorPressedHighlight">@color/legacy_pressed_highlight</item>
-        <item name="colorLongPressedHighlight">@color/legacy_long_pressed_highlight</item>
-        <item name="colorFocusedHighlight">@color/legacy_selected_highlight</item>
-        <item name="colorMultiSelectHighlight">@color/legacy_selected_highlight</item>
-        <item name="colorActivatedHighlight">@color/legacy_selected_highlight</item>
-
-        <item name="colorPrimaryDark">@color/legacy_primary_dark</item>
-        <item name="colorPrimary">@color/legacy_primary</item>
-        <item name="colorSecondary">?attr/colorPrimary</item>
-        <item name="colorControlActivated">@color/legacy_control_activated</item>
-        <item name="colorControlNormal">@color/legacy_control_normal</item>
-        <item name="colorControlHighlight">@color/legacy_button_pressed</item>
-        <item name="colorButtonNormal">@color/legacy_button_normal</item>
-        <item name="colorEdgeEffect">?attr/colorPrimary</item>
-        <item name="colorError">@color/red</item>
-
         <item name="disabledAlpha">0.5</item>
+        <item name="primaryContentAlpha">@dimen/primary_content_alpha_material_dark</item>
+        <item name="secondaryContentAlpha">@dimen/secondary_content_alpha_material_dark</item>
         <item name="backgroundDimAmount">0.6</item>
+        <item name="colorError">@color/red</item>
 
         <!-- Text styles -->
         <item name="textAppearance">@style/TextAppearance</item>
         <item name="textAppearanceInverse">@style/TextAppearance.Inverse</item>
 
         <item name="textColorPrimary">@color/primary_text_dark</item>
-        <item name="textColorSecondary">@color/secondary_text_dark</item>
-        <item name="textColorTertiary">@color/tertiary_text_dark</item>
         <item name="textColorPrimaryInverse">@color/primary_text_light</item>
-        <item name="textColorSecondaryInverse">@color/secondary_text_light</item>
-        <item name="textColorTertiaryInverse">@color/tertiary_text_light</item>
         <item name="textColorPrimaryActivated">@color/primary_text_dark</item>
-        <item name="textColorSecondaryActivated">@color/secondary_text_dark</item>
         <item name="textColorPrimaryDisableOnly">@color/primary_text_dark_disable_only</item>
         <item name="textColorPrimaryInverseDisableOnly">@color/primary_text_light_disable_only</item>
-        <item name="textColorPrimaryNoDisable">@color/primary_text_dark_nodisable</item>
-        <item name="textColorSecondaryNoDisable">@color/secondary_text_dark_nodisable</item>
         <item name="textColorPrimaryInverseNoDisable">@color/primary_text_light_nodisable</item>
+        <item name="textColorPrimaryNoDisable">@color/primary_text_dark_nodisable</item>
+        <item name="textColorSecondary">@color/secondary_text_dark</item>
+        <item name="textColorSecondaryInverse">@color/secondary_text_light</item>
+        <item name="textColorSecondaryActivated">@color/secondary_text_dark</item>
+        <item name="textColorSecondaryNoDisable">@color/secondary_text_dark_nodisable</item>
         <item name="textColorSecondaryInverseNoDisable">@color/secondary_text_light_nodisable</item>
+        <item name="textColorTertiary">@color/tertiary_text_dark</item>
+        <item name="textColorTertiaryInverse">@color/tertiary_text_light</item>
         <item name="textColorHint">@color/hint_foreground_dark</item>
         <item name="textColorHintInverse">@color/hint_foreground_light</item>
-        <item name="textColorSearchUrl">@color/search_url_text</item>
         <item name="textColorHighlight">@color/highlighted_text_dark</item>
         <item name="textColorHighlightInverse">@color/highlighted_text_light</item>
         <item name="textColorLink">@color/link_text_dark</item>
         <item name="textColorLinkInverse">@color/link_text_light</item>
+        <item name="textColorSearchUrl">@color/search_url_text</item>
         <item name="textColorAlertDialogListItem">@color/primary_text_light_disable_only</item>
 
         <item name="textAppearanceLarge">@style/TextAppearance.Large</item>
@@ -120,14 +106,19 @@
 
         <item name="textAppearanceLargePopupMenu">@style/TextAppearance.Widget.PopupMenu.Large</item>
         <item name="textAppearanceSmallPopupMenu">@style/TextAppearance.Widget.PopupMenu.Small</item>
+        <item name="textAppearancePopupMenuHeader">@null</item>
 
         <!-- Button styles -->
         <item name="buttonStyle">@style/Widget.Button</item>
+
         <item name="buttonStyleSmall">@style/Widget.Button.Small</item>
         <item name="buttonStyleInset">@style/Widget.Button.Inset</item>
+
         <item name="buttonStyleToggle">@style/Widget.Button.Toggle</item>
+        <item name="buttonCornerRadius">0dp</item>
 
         <item name="switchStyle">@style/Widget.CompoundButton.Switch</item>
+        <item name="mediaRouteButtonStyle">@style/Widget.DeviceDefault.MediaRouteButton</item>
 
         <item name="selectableItemBackground">@drawable/item_background</item>
         <item name="selectableItemBackgroundBorderless">?attr/selectableItemBackground</item>
@@ -156,7 +147,6 @@
         <item name="listChoiceIndicatorMultiple">@drawable/btn_check</item>
 
         <item name="listChoiceBackgroundIndicator">@drawable/list_selector_background</item>
-
         <item name="activatedBackgroundIndicator">@drawable/activated_background</item>
 
         <item name="listDividerAlertDialog">@drawable/divider_horizontal_bright</item>
@@ -215,6 +205,7 @@
         <item name="dialogCustomTitleDecorLayout">@layout/dialog_custom_title</item>
         <item name="dialogTitleDecorLayout">@layout/dialog_title</item>
         <item name="dialogPreferredPadding">@dimen/dialog_padding</item>
+        <item name="dialogCornerRadius">0dp</item>
 
         <!-- AlertDialog attributes -->
         <item name="alertDialogTheme">@style/Theme.Dialog.Alert</item>
@@ -239,6 +230,7 @@
 
         <item name="panelMenuIsCompact">false</item>
         <item name="panelMenuListWidth">296dip</item>
+        <item name="panelMenuListTheme">@null</item>
 
         <!-- Scrollbar attributes -->
         <item name="scrollbarFadeDuration">250</item>
@@ -316,8 +308,9 @@
         <item name="quickContactBadgeStyleSmallWindowLarge">@style/Widget.QuickContactBadgeSmall.WindowLarge</item>
         <item name="listPopupWindowStyle">@style/Widget.ListPopupWindow</item>
         <item name="popupMenuStyle">@style/Widget.PopupMenu</item>
+        <item name="popupTheme">@null</item>
+        <item name="stackViewStyle">@null</item>
         <item name="activityChooserViewStyle">@style/Widget.ActivityChooserView</item>
-        <item name="mediaRouteButtonStyle">@style/Widget.DeviceDefault.MediaRouteButton</item>
         <item name="fragmentBreadCrumbsStyle">@style/Widget.FragmentBreadCrumbs</item>
         <item name="contextPopupMenuStyle">?attr/popupMenuStyle</item>
 
@@ -432,6 +425,22 @@
         <item name="fastScrollOverlayPosition">floating</item>
         <item name="fastScrollTextColor">@color/primary_text_dark</item>
 
+
+        <item name="colorPressedHighlight">@color/legacy_pressed_highlight</item>
+        <item name="colorLongPressedHighlight">@color/legacy_long_pressed_highlight</item>
+        <item name="colorFocusedHighlight">@color/legacy_selected_highlight</item>
+        <item name="colorMultiSelectHighlight">@color/legacy_selected_highlight</item>
+        <item name="colorActivatedHighlight">@color/legacy_selected_highlight</item>
+
+        <item name="colorPrimaryDark">@color/legacy_primary_dark</item>
+        <item name="colorPrimary">@color/legacy_primary</item>
+        <item name="colorSecondary">?attr/colorPrimary</item>
+        <item name="colorControlActivated">@color/legacy_control_activated</item>
+        <item name="colorControlNormal">@color/legacy_control_normal</item>
+        <item name="colorControlHighlight">@color/legacy_button_pressed</item>
+        <item name="colorButtonNormal">@color/legacy_button_normal</item>
+        <item name="colorEdgeEffect">?attr/colorPrimary</item>
+
         <!-- Accessibility focused drawable -->
         <item name="accessibilityFocusedDrawable">@drawable/view_accessibility_focused</item>
 
@@ -451,8 +460,8 @@
         <item name="tooltipBackgroundColor">@color/tooltip_background_light</item>
 
         <!-- Autofill: max width/height of the dataset picker as a fraction of screen size -->
-        <item name="autofillDatasetPickerMaxWidth">@dimen/autofill_dataset_picker_max_size</item>
-        <item name="autofillDatasetPickerMaxHeight">@dimen/autofill_dataset_picker_max_size</item>
+        <item name="autofillDatasetPickerMaxWidth">@dimen/autofill_dataset_picker_max_width</item>
+        <item name="autofillDatasetPickerMaxHeight">@dimen/autofill_dataset_picker_max_height</item>
 
         <!-- Autofill: max height of custom save subtitle as a fraction of screen size -->
         <item name="autofillSaveCustomSubtitleMaxHeight">@dimen/autofill_save_custom_subtitle_max_height</item>
diff --git a/core/res/res/values/themes_holo.xml b/core/res/res/values/themes_holo.xml
index 8f73479..3fe7c05 100644
--- a/core/res/res/values/themes_holo.xml
+++ b/core/res/res/values/themes_holo.xml
@@ -29,20 +29,9 @@
 ===============================================================
  -->
 <resources>
-    <!-- The default theme for apps on API level 10 and lower. This is the theme used for
-         activities that have not explicitly set their own theme.
-         <p>You can count on this being a dark
-         background with light text on top, but should try to make no
-         other assumptions about its appearance. In particular, the text
-         inside of widgets using this theme may be completely different,
-         with the widget container being a light color and the text on top
-         of it a dark color.
-         <p>If you're developing for API level 11 and higher, you should instead use {@link
-         #Theme_Holo} or {@link #Theme_DeviceDefault}.</p>
-    -->
 
     <!-- Honeycomb holographic theme (dark version).
-         <p>This is the default system theme for apps that target API level 11 - 13. Starting
+         <p>This is the default system theme for apps that target API level 11 - 20. Starting
          with API level 14, the default system theme is supplied by {@link #Theme_DeviceDefault},
          which might apply a different style on different devices. If you want to ensure that your
          app consistently uses the Holo theme at all times, you must explicitly declare it in your
@@ -60,7 +49,9 @@
          TextAppearance.Holo.Widget.PopupMenu.Large}).
          Specific resources used by Holo are named using the convention @type/foo_bar_baz_holo
          with trailing _dark or _light specifiers if they are not shared between both light and
-         dark versions of the theme. -->
+         dark versions of the theme.
+
+         @deprecated Use Material themes on API 21+ or AppCompat on supported APIs. -->
     <style name="Theme.Holo">
         <item name="colorForeground">@color/bright_foreground_holo_dark</item>
         <item name="colorForegroundInverse">@color/bright_foreground_inverse_holo_dark</item>
@@ -68,21 +59,10 @@
         <item name="colorBackgroundFloating">@color/background_holo_dark</item>
         <item name="colorBackgroundCacheHint">@color/background_cache_hint_selector_holo_dark</item>
         <item name="disabledAlpha">0.5</item>
+        <item name="primaryContentAlpha">@dimen/primary_content_alpha_material_dark</item>
+        <item name="secondaryContentAlpha">@dimen/secondary_content_alpha_material_dark</item>
         <item name="backgroundDimAmount">0.6</item>
-
-        <item name="colorPressedHighlight">@color/holo_gray_light</item>
-        <item name="colorLongPressedHighlight">@color/holo_gray_bright</item>
-        <item name="colorFocusedHighlight">@color/holo_blue_dark</item>
-        <item name="colorMultiSelectHighlight">@color/holo_green_light</item>
-        <item name="colorActivatedHighlight">@color/holo_blue_dark</item>
-
-        <item name="colorPrimaryDark">@color/holo_primary_dark</item>
-        <item name="colorPrimary">@color/holo_primary</item>
-        <item name="colorControlActivated">@color/holo_control_activated</item>
-        <item name="colorControlNormal">@color/holo_control_normal</item>
-        <item name="colorControlHighlight">@color/holo_button_pressed</item>
-        <item name="colorButtonNormal">@color/holo_button_normal</item>
-        <item name="colorEdgeEffect">?attr/colorPrimary</item>
+        <item name="colorError">@color/error_color_material_dark</item>
 
         <!-- Text styles -->
         <item name="textAppearance">@style/TextAppearance.Holo</item>
@@ -132,6 +112,7 @@
 
         <item name="textAppearanceLargePopupMenu">@style/TextAppearance.Holo.Widget.PopupMenu.Large</item>
         <item name="textAppearanceSmallPopupMenu">@style/TextAppearance.Holo.Widget.PopupMenu.Small</item>
+        <item name="textAppearancePopupMenuHeader">@null</item>
 
         <item name="textEditSuggestionItemLayout">@layout/text_edit_suggestion_item</item>
         <item name="textEditSuggestionContainerLayout">@layout/text_edit_suggestion_container</item>
@@ -144,6 +125,8 @@
         <item name="buttonStyleInset">@style/Widget.Holo.Button.Inset</item>
 
         <item name="buttonStyleToggle">@style/Widget.Holo.Button.Toggle</item>
+        <item name="buttonCornerRadius">0dp</item>
+
         <item name="switchStyle">@style/Widget.Holo.CompoundButton.Switch</item>
         <item name="mediaRouteButtonStyle">@style/Widget.Holo.MediaRouteButton</item>
 
@@ -157,6 +140,7 @@
         <item name="listPreferredItemHeightSmall">48dip</item>
         <item name="listPreferredItemHeightLarge">80dip</item>
         <item name="dropdownListPreferredItemHeight">?attr/listPreferredItemHeightSmall</item>
+        <item name="textAppearanceListItem">?attr/textAppearanceLarge</item>
         <item name="textAppearanceListItemSmall">?attr/textAppearanceMedium</item>
         <item name="textAppearanceListItemSecondary">?attr/textAppearanceSmall</item>
         <item name="listPreferredItemPaddingLeft">8dip</item>
@@ -212,6 +196,8 @@
         <item name="dialogTitleIconsDecorLayout">@layout/dialog_title_icons_holo</item>
         <item name="dialogCustomTitleDecorLayout">@layout/dialog_custom_title_holo</item>
         <item name="dialogTitleDecorLayout">@layout/dialog_title_holo</item>
+        <item name="dialogPreferredPadding">@dimen/dialog_padding</item>
+        <item name="dialogCornerRadius">0dp</item>
 
         <!-- AlertDialog attributes -->
         <item name="alertDialogTheme">@style/Theme.Holo.Dialog.Alert</item>
@@ -251,6 +237,9 @@
         <item name="textSelectHandleRight">@drawable/text_select_handle_right_material</item>
         <item name="textSelectHandle">@drawable/text_select_handle_middle_material</item>
         <item name="textSelectHandleWindowStyle">@style/Widget.Holo.TextSelectHandle</item>
+        <item name="textEditSuggestionItemLayout">@layout/text_edit_suggestion_item</item>
+        <item name="textEditSuggestionContainerLayout">@layout/text_edit_suggestion_container</item>
+        <item name="textEditSuggestionHighlightStyle">@style/TextAppearance.Holo.SuggestionHighlight</item>
         <item name="textCursorDrawable">@drawable/text_cursor_holo_dark</item>
 
         <!-- Widget styles -->
@@ -268,6 +257,7 @@
         <item name="gridViewStyle">@style/Widget.Holo.GridView</item>
         <item name="imageButtonStyle">@style/Widget.Holo.ImageButton</item>
         <item name="imageWellStyle">@style/Widget.Holo.ImageWell</item>
+        <item name="listMenuViewStyle">@null</item>
         <item name="listViewStyle">@style/Widget.Holo.ListView</item>
         <item name="listViewWhiteStyle">@style/Widget.Holo.ListView.White</item>
         <item name="popupWindowStyle">@style/Widget.Holo.PopupWindow</item>
@@ -308,9 +298,11 @@
         <item name="quickContactBadgeStyleSmallWindowLarge">@style/Widget.Holo.QuickContactBadgeSmall.WindowLarge</item>
         <item name="listPopupWindowStyle">@style/Widget.Holo.ListPopupWindow</item>
         <item name="popupMenuStyle">@style/Widget.Holo.PopupMenu</item>
+        <item name="popupTheme">@null</item>
         <item name="stackViewStyle">@style/Widget.Holo.StackView</item>
         <item name="activityChooserViewStyle">@style/Widget.Holo.ActivityChooserView</item>
         <item name="fragmentBreadCrumbsStyle">@style/Widget.Holo.FragmentBreadCrumbs</item>
+        <item name="contextPopupMenuStyle">?attr/popupMenuStyle</item>
 
         <!-- Preference styles -->
         <item name="preferenceScreenStyle">@style/Preference.Holo.PreferenceScreen</item>
@@ -327,8 +319,16 @@
         <item name="editTextPreferenceStyle">@style/Preference.Holo.DialogPreference.EditTextPreference</item>
         <item name="ringtonePreferenceStyle">@style/Preference.Holo.RingtonePreference</item>
         <item name="preferenceLayoutChild">@layout/preference_child_holo</item>
+        <item name="preferencePanelStyle">@null</item>
+        <item name="preferenceHeaderPanelStyle">@null</item>
+        <item name="preferenceListStyle">@null</item>
+        <item name="preferenceFragmentListStyle">@null</item>
+        <item name="preferenceFragmentPaddingSide">@null</item>
         <item name="detailsElementBackground">@drawable/panel_bg_holo_dark</item>
 
+        <!-- PreferenceFrameLayout attributes -->
+        <item name="preferenceFrameLayoutStyle">@style/Widget.Holo.PreferenceFrameLayout</item>
+
         <!-- Search widget styles -->
         <item name="searchWidgetCorpusItemBackground">@color/search_widget_corpus_item_background</item>
 
@@ -348,9 +348,13 @@
         <item name="actionBarStyle">@style/Widget.Holo.ActionBar</item>
         <item name="actionBarSize">@dimen/action_bar_default_height</item>
         <item name="actionModePopupWindowStyle">@style/Widget.Holo.PopupWindow.ActionMode</item>
+        <item name="actionMenuTextAppearance">@null</item>
+        <item name="actionMenuTextColor">@null</item>
         <item name="actionBarWidgetTheme">@null</item>
-        <item name="actionBarPopupTheme">@null</item>
+        <item name="actionBarPopupTheme">?attr/popupTheme</item>
         <item name="actionBarTheme">@null</item>
+        <item name="actionBarDivider">?attr/dividerVertical</item>
+        <item name="actionBarItemBackground">@null</item>
 
         <item name="actionModeCutDrawable">@drawable/ic_menu_cut_holo_dark</item>
         <item name="actionModeCopyDrawable">@drawable/ic_menu_copy_holo_dark</item>
@@ -360,6 +364,8 @@
         <item name="actionModeFindDrawable">@drawable/ic_menu_find_holo_dark</item>
         <item name="actionModeWebSearchDrawable">@drawable/ic_menu_search_holo_dark</item>
 
+        <item name="toolbarStyle">@null</item>
+
         <item name="dividerVertical">?attr/listDivider</item>
         <item name="dividerHorizontal">?attr/listDivider</item>
         <item name="buttonBarStyle">@style/Holo.ButtonBar</item>
@@ -397,13 +403,39 @@
         <item name="fastScrollTrackDrawable">@drawable/fastscroll_track_holo_dark</item>
         <item name="fastScrollOverlayPosition">atThumb</item>
 
+
+        <item name="colorPrimaryDark">@color/holo_primary_dark</item>
+        <item name="colorPrimary">@color/holo_primary</item>
+        <item name="colorAccent">@color/holo_blue_dark</item>
+        <item name="colorEdgeEffect">?attr/colorPrimary</item>
+
+        <item name="colorControlNormal">@color/holo_control_normal</item>
+        <item name="colorControlActivated">@color/holo_control_activated</item>
+
+        <item name="colorControlHighlight">@color/holo_button_pressed</item>
+        <item name="colorButtonNormal">@color/holo_button_normal</item>
+        <item name="colorSwitchThumbNormal">@color/switch_thumb_material_light</item>
+
+        <!-- Tooltip popup properties -->
+        <item name="tooltipForegroundColor">@null</item>
+        <item name="tooltipBackgroundColor">@null</item>
+
+        <!-- Holo-only color attributes -->
+        <item name="colorPressedHighlight">@color/holo_gray_light</item>
+        <item name="colorLongPressedHighlight">@color/holo_gray_bright</item>
+        <item name="colorFocusedHighlight">@color/holo_blue_dark</item>
+        <item name="colorMultiSelectHighlight">@color/holo_green_light</item>
+        <item name="colorActivatedHighlight">@color/holo_blue_dark</item>
+
     </style>
 
     <!-- Honeycomb holographic theme (light version).  The widgets in the
          holographic theme are translucent on their brackground, so applications
          must ensure that any background they use with this theme is itself
          light; otherwise, it will be difficult to see the widgets.  This
-         UI style also includes a full action bar by default. -->
+         UI style also includes a full action bar by default.
+
+         @deprecated Use Material themes on API 21+ or AppCompat on supported APIs. -->
     <style name="Theme.Holo.Light" parent="Theme.Light">
         <item name="colorForeground">@color/bright_foreground_holo_light</item>
         <item name="colorForegroundInverse">@color/bright_foreground_inverse_holo_light</item>
@@ -411,46 +443,36 @@
         <item name="colorBackgroundFloating">@color/background_holo_light</item>
         <item name="colorBackgroundCacheHint">@color/background_cache_hint_selector_holo_light</item>
         <item name="disabledAlpha">0.5</item>
+        <item name="primaryContentAlpha">@dimen/primary_content_alpha_material_dark</item>
+        <item name="secondaryContentAlpha">@dimen/secondary_content_alpha_material_dark</item>
         <item name="backgroundDimAmount">0.6</item>
-
-        <item name="colorPressedHighlight">@color/holo_gray_light</item>
-        <item name="colorLongPressedHighlight">@color/holo_gray_bright</item>
-        <item name="colorFocusedHighlight">@color/holo_blue_dark</item>
-        <item name="colorMultiSelectHighlight">@color/holo_green_light</item>
-        <item name="colorActivatedHighlight">@color/holo_blue_dark</item>
-
-        <item name="colorPrimaryDark">@color/holo_light_primary_dark</item>
-        <item name="colorPrimary">@color/holo_light_primary</item>
-        <item name="colorControlActivated">@color/holo_light_control_activated</item>
-        <item name="colorControlNormal">@color/holo_light_control_normal</item>
-        <item name="colorControlHighlight">@color/holo_light_button_pressed</item>
-        <item name="colorButtonNormal">@color/holo_light_button_normal</item>
+        <item name="colorError">@color/error_color_material_light</item>
 
         <!-- Text styles -->
         <item name="textAppearance">@style/TextAppearance.Holo.Light</item>
         <item name="textAppearanceInverse">@style/TextAppearance.Holo.Light.Inverse</item>
 
         <item name="textColorPrimary">@color/primary_text_holo_light</item>
-        <item name="textColorSecondary">@color/secondary_text_holo_light</item>
-        <item name="textColorTertiary">@color/tertiary_text_holo_light</item>
         <item name="textColorPrimaryInverse">@color/primary_text_holo_dark</item>
-        <item name="textColorSecondaryInverse">@color/secondary_text_holo_dark</item>
-        <item name="textColorTertiaryInverse">@color/tertiary_text_holo_dark</item>
         <item name="textColorPrimaryActivated">@color/primary_text_holo_light</item>
-        <item name="textColorSecondaryActivated">@color/secondary_text_holo_light</item>
         <item name="textColorPrimaryDisableOnly">@color/primary_text_disable_only_holo_light</item>
         <item name="textColorPrimaryInverseDisableOnly">@color/primary_text_disable_only_holo_dark</item>
-        <item name="textColorPrimaryNoDisable">@color/primary_text_nodisable_holo_light</item>
-        <item name="textColorSecondaryNoDisable">@color/secondary_text_nodisable_holo_light</item>
         <item name="textColorPrimaryInverseNoDisable">@color/primary_text_nodisable_holo_dark</item>
+        <item name="textColorPrimaryNoDisable">@color/primary_text_nodisable_holo_light</item>
+        <item name="textColorSecondary">@color/secondary_text_holo_light</item>
+        <item name="textColorSecondaryInverse">@color/secondary_text_holo_dark</item>
+        <item name="textColorSecondaryActivated">@color/secondary_text_holo_light</item>
+        <item name="textColorSecondaryNoDisable">@color/secondary_text_nodisable_holo_light</item>
         <item name="textColorSecondaryInverseNoDisable">@color/secondary_text_nodisable_holo_dark</item>
+        <item name="textColorTertiary">@color/tertiary_text_holo_light</item>
+        <item name="textColorTertiaryInverse">@color/tertiary_text_holo_dark</item>
         <item name="textColorHint">@color/hint_foreground_holo_light</item>
         <item name="textColorHintInverse">@color/hint_foreground_holo_dark</item>
-        <item name="textColorSearchUrl">@color/search_url_text_holo</item>
         <item name="textColorHighlight">@color/highlighted_text_holo_light</item>
         <item name="textColorHighlightInverse">@color/highlighted_text_holo_dark</item>
         <item name="textColorLink">@color/holo_blue_light</item>
         <item name="textColorLinkInverse">@color/holo_blue_light</item>
+        <item name="textColorSearchUrl">@color/search_url_text_holo</item>
         <item name="textColorAlertDialogListItem">@color/primary_text_holo_light</item>
 
         <item name="textAppearanceLarge">@style/TextAppearance.Holo.Light.Large</item>
@@ -466,9 +488,6 @@
 
         <item name="editTextColor">?attr/textColorPrimary</item>
         <item name="editTextBackground">@drawable/edit_text_holo_light</item>
-        <item name="textEditSuggestionItemLayout">@layout/text_edit_suggestion_item</item>
-        <item name="textEditSuggestionContainerLayout">@layout/text_edit_suggestion_container</item>
-        <item name="textEditSuggestionHighlightStyle">@style/TextAppearance.Holo.SuggestionHighlight</item>
 
         <item name="candidatesTextStyleSpans">@string/candidates_style</item>
 
@@ -477,6 +496,7 @@
 
         <item name="textAppearanceLargePopupMenu">@style/TextAppearance.Holo.Light.Widget.PopupMenu.Large</item>
         <item name="textAppearanceSmallPopupMenu">@style/TextAppearance.Holo.Light.Widget.PopupMenu.Small</item>
+        <item name="textAppearancePopupMenuHeader">@null</item>
 
         <!-- Button styles -->
         <item name="buttonStyle">@style/Widget.Holo.Light.Button</item>
@@ -485,6 +505,8 @@
         <item name="buttonStyleInset">@style/Widget.Holo.Light.Button.Inset</item>
 
         <item name="buttonStyleToggle">@style/Widget.Holo.Light.Button.Toggle</item>
+        <item name="buttonCornerRadius">0dp</item>
+
         <item name="switchStyle">@style/Widget.Holo.Light.CompoundButton.Switch</item>
         <item name="mediaRouteButtonStyle">@style/Widget.Holo.Light.MediaRouteButton</item>
 
@@ -498,6 +520,7 @@
         <item name="listPreferredItemHeightSmall">48dip</item>
         <item name="listPreferredItemHeightLarge">80dip</item>
         <item name="dropdownListPreferredItemHeight">?attr/listPreferredItemHeightSmall</item>
+        <item name="textAppearanceListItem">?attr/textAppearanceLarge</item>
         <item name="textAppearanceListItemSmall">?attr/textAppearanceMedium</item>
         <item name="textAppearanceListItemSecondary">?attr/textAppearanceSmall</item>
         <item name="listPreferredItemPaddingLeft">8dip</item>
@@ -514,9 +537,10 @@
         <item name="listChoiceIndicatorMultiple">@drawable/btn_check_holo_light</item>
 
         <item name="listChoiceBackgroundIndicator">@drawable/list_selector_holo_light</item>
-
         <item name="activatedBackgroundIndicator">@drawable/activated_background_holo_light</item>
 
+        <item name="listDividerAlertDialog">@drawable/list_divider_holo_light</item>
+
         <item name="expandableListPreferredItemPaddingLeft">40dip</item>
         <item name="expandableListPreferredChildPaddingLeft">?attr/expandableListPreferredItemPaddingLeft</item>
 
@@ -524,8 +548,6 @@
         <item name="expandableListPreferredItemIndicatorRight">0dip</item>
         <item name="expandableListPreferredChildIndicatorLeft">?attr/expandableListPreferredItemIndicatorLeft</item>
         <item name="expandableListPreferredChildIndicatorRight">?attr/expandableListPreferredItemIndicatorRight</item>
-
-        <item name="listDividerAlertDialog">@drawable/list_divider_holo_light</item>
         <item name="findOnPageNextDrawable">@drawable/ic_find_next_holo_light</item>
         <item name="findOnPagePreviousDrawable">@drawable/ic_find_previous_holo_light</item>
 
@@ -553,6 +575,8 @@
         <item name="dialogTitleIconsDecorLayout">@layout/dialog_title_icons_holo</item>
         <item name="dialogCustomTitleDecorLayout">@layout/dialog_custom_title_holo</item>
         <item name="dialogTitleDecorLayout">@layout/dialog_title_holo</item>
+        <item name="dialogPreferredPadding">@dimen/dialog_padding</item>
+        <item name="dialogCornerRadius">0dp</item>
 
         <!-- AlertDialog attributes -->
         <item name="alertDialogTheme">@style/Theme.Holo.Light.Dialog.Alert</item>
@@ -592,6 +616,9 @@
         <item name="textSelectHandleRight">@drawable/text_select_handle_right_material</item>
         <item name="textSelectHandle">@drawable/text_select_handle_middle_material</item>
         <item name="textSelectHandleWindowStyle">@style/Widget.Holo.TextSelectHandle</item>
+        <item name="textEditSuggestionItemLayout">@layout/text_edit_suggestion_item</item>
+        <item name="textEditSuggestionContainerLayout">@layout/text_edit_suggestion_container</item>
+        <item name="textEditSuggestionHighlightStyle">@style/TextAppearance.Holo.SuggestionHighlight</item>
         <item name="textCursorDrawable">@drawable/text_cursor_holo_light</item>
 
         <!-- Widget styles -->
@@ -609,6 +636,7 @@
         <item name="gridViewStyle">@style/Widget.Holo.Light.GridView</item>
         <item name="imageButtonStyle">@style/Widget.Holo.Light.ImageButton</item>
         <item name="imageWellStyle">@style/Widget.Holo.Light.ImageWell</item>
+        <item name="listMenuViewStyle">@null</item>
         <item name="listViewStyle">@style/Widget.Holo.Light.ListView</item>
         <item name="listViewWhiteStyle">@style/Widget.Holo.Light.ListView.White</item>
         <item name="popupWindowStyle">@style/Widget.Holo.Light.PopupWindow</item>
@@ -649,9 +677,11 @@
         <item name="quickContactBadgeStyleSmallWindowLarge">@style/Widget.Holo.QuickContactBadgeSmall.WindowLarge</item>
         <item name="listPopupWindowStyle">@style/Widget.Holo.Light.ListPopupWindow</item>
         <item name="popupMenuStyle">@style/Widget.Holo.Light.PopupMenu</item>
+        <item name="popupTheme">@null</item>
         <item name="stackViewStyle">@style/Widget.Holo.StackView</item>
         <item name="activityChooserViewStyle">@style/Widget.Holo.Light.ActivityChooserView</item>
         <item name="fragmentBreadCrumbsStyle">@style/Widget.Holo.Light.FragmentBreadCrumbs</item>
+        <item name="contextPopupMenuStyle">@null</item>
 
         <!-- Preference styles -->
         <item name="preferenceScreenStyle">@style/Preference.Holo.PreferenceScreen</item>
@@ -668,6 +698,11 @@
         <item name="editTextPreferenceStyle">@style/Preference.Holo.DialogPreference.EditTextPreference</item>
         <item name="ringtonePreferenceStyle">@style/Preference.Holo.RingtonePreference</item>
         <item name="preferenceLayoutChild">@layout/preference_child_holo</item>
+        <item name="preferencePanelStyle">@null</item>
+        <item name="preferenceHeaderPanelStyle">@null</item>
+        <item name="preferenceListStyle">@null</item>
+        <item name="preferenceFragmentListStyle">@null</item>
+        <item name="preferenceFragmentPaddingSide">@null</item>
         <item name="detailsElementBackground">@drawable/panel_bg_holo_light</item>
 
         <!-- PreferenceFrameLayout attributes -->
@@ -680,6 +715,7 @@
         <item name="actionDropDownStyle">@style/Widget.Holo.Light.Spinner.DropDown.ActionBar</item>
         <item name="actionButtonStyle">@style/Widget.Holo.Light.ActionButton</item>
         <item name="actionOverflowButtonStyle">@style/Widget.Holo.Light.ActionButton.Overflow</item>
+        <item name="actionOverflowMenuStyle">?attr/popupMenuStyle</item>
         <item name="actionModeBackground">@drawable/cab_background_top_holo_light</item>
         <item name="actionModeSplitBackground">@drawable/cab_background_bottom_holo_light</item>
         <item name="actionModeCloseDrawable">@drawable/ic_cab_done_holo_light</item>
@@ -691,8 +727,12 @@
         <item name="actionBarStyle">@style/Widget.Holo.Light.ActionBar.Solid</item>
         <item name="actionBarSize">@dimen/action_bar_default_height</item>
         <item name="actionModePopupWindowStyle">@style/Widget.Holo.Light.PopupWindow.ActionMode</item>
+        <item name="actionMenuTextAppearance">@null</item>
+        <item name="actionMenuTextColor">@null</item>
         <item name="actionBarWidgetTheme">@null</item>
+        <item name="actionBarPopupTheme">?attr/popupTheme</item>
         <item name="actionBarTheme">@null</item>
+        <item name="actionBarItemBackground">@null</item>
 
         <item name="actionModeCutDrawable">@drawable/ic_menu_cut_holo_light</item>
         <item name="actionModeCopyDrawable">@drawable/ic_menu_copy_holo_light</item>
@@ -702,6 +742,8 @@
         <item name="actionModeFindDrawable">@drawable/ic_menu_find_holo_light</item>
         <item name="actionModeWebSearchDrawable">@drawable/ic_menu_search_holo_light</item>
 
+        <item name="toolbarStyle">@null</item>
+
         <item name="dividerVertical">?attr/listDivider</item>
         <item name="dividerHorizontal">?attr/listDivider</item>
         <item name="buttonBarStyle">@style/Holo.Light.ButtonBar</item>
@@ -736,11 +778,37 @@
         <item name="fastScrollTrackDrawable">@drawable/fastscroll_track_holo_light</item>
         <item name="fastScrollOverlayPosition">atThumb</item>
 
+        <!-- Color palette -->
+        <item name="colorPrimaryDark">@color/holo_light_primary_dark</item>
+        <item name="colorPrimary">@color/holo_light_primary</item>
+        <item name="colorAccent">@color/holo_blue_light</item>
+        <item name="colorEdgeEffect">?attr/colorPrimary</item>
+
+        <item name="colorControlNormal">@color/holo_light_control_normal</item>
+        <item name="colorControlActivated">@color/holo_light_control_activated</item>
+
+        <item name="colorControlHighlight">@color/holo_light_button_pressed</item>
+        <item name="colorButtonNormal">@color/holo_light_button_normal</item>
+        <item name="colorSwitchThumbNormal">@color/switch_thumb_material_light</item>
+
+        <!-- Tooltip popup properties -->
+        <item name="tooltipForegroundColor">@null</item>
+        <item name="tooltipBackgroundColor">@null</item>
+
+        <!-- Holo-only color attributes -->
+        <item name="colorPressedHighlight">@color/holo_gray_light</item>
+        <item name="colorLongPressedHighlight">@color/holo_gray_bright</item>
+        <item name="colorFocusedHighlight">@color/holo_blue_dark</item>
+        <item name="colorMultiSelectHighlight">@color/holo_green_light</item>
+        <item name="colorActivatedHighlight">@color/holo_blue_dark</item>
+
     </style>
 
     <!-- Variant of the holographic (light) theme that has a solid (opaque) action bar
          with an inverse color profile. The dark action bar sharply stands out against
-         the light content. -->
+         the light content.
+
+         @deprecated Use Material themes on API 21+ or AppCompat on supported APIs. -->
     <style name="Theme.Holo.Light.DarkActionBar">
         <item name="windowContentOverlay">@drawable/ab_solid_shadow_holo</item>
         <item name="actionBarStyle">@style/Widget.Holo.Light.ActionBar.Solid.Inverse</item>
@@ -773,7 +841,9 @@
         <item name="actionModeWebSearchDrawable">@drawable/ic_menu_search_holo_dark</item>
     </style>
 
-    <!-- Variant of the holographic (dark) theme with no action bar. -->
+    <!-- Variant of the holographic (dark) theme with no action bar.
+
+         @deprecated Use Material themes on API 21+ or AppCompat on supported APIs. -->
     <style name="Theme.Holo.NoActionBar">
         <item name="windowActionBar">false</item>
         <item name="windowNoTitle">true</item>
@@ -781,7 +851,9 @@
 
     <!-- Variant of the holographic (dark) theme that has no title bar and fills
          the entire screen.  This theme
-         sets {@link android.R.attr#windowFullscreen} to true.  -->
+         sets {@link android.R.attr#windowFullscreen} to true.
+
+         @deprecated Use Material themes on API 21+ or AppCompat on supported APIs. -->
     <style name="Theme.Holo.NoActionBar.Fullscreen">
         <item name="windowFullscreen">true</item>
         <item name="windowContentOverlay">@null</item>
@@ -790,7 +862,9 @@
     <!-- Variant of the holographic (dark) theme that has no title bar and fills
          the entire screen and extends into the display overscan region.  This theme
          sets {@link android.R.attr#windowFullscreen} and {@link android.R.attr#windowOverscan}
-         to true. -->
+         to true.
+
+         @deprecated Use Material themes on API 21+ or AppCompat on supported APIs. -->
     <style name="Theme.Holo.NoActionBar.Overscan">
         <item name="windowFullscreen">true</item>
         <item name="windowOverscan">true</item>
@@ -799,14 +873,18 @@
 
     <!-- Variant of the holographic (dark) theme that has no title bar and translucent
          system decor.  This theme sets {@link android.R.attr#windowTranslucentStatus} and
-         {@link android.R.attr#windowTranslucentNavigation} to true. -->
+         {@link android.R.attr#windowTranslucentNavigation} to true.
+
+         @deprecated Use Material themes on API 21+ or AppCompat on supported APIs. -->
     <style name="Theme.Holo.NoActionBar.TranslucentDecor">
         <item name="windowTranslucentStatus">true</item>
         <item name="windowTranslucentNavigation">true</item>
         <item name="windowContentOverlay">@null</item>
     </style>
 
-    <!-- Variant of the holographic (light) theme with no action bar. -->
+    <!-- Variant of the holographic (light) theme with no action bar.
+
+         @deprecated Use Material themes on API 21+ or AppCompat on supported APIs. -->
     <style name="Theme.Holo.Light.NoActionBar">
         <item name="windowActionBar">false</item>
         <item name="windowNoTitle">true</item>
@@ -814,7 +892,9 @@
 
     <!-- Variant of the holographic (light) theme that has no title bar and fills
          the entire screen.  This theme
-         sets {@link android.R.attr#windowFullscreen} to true.  -->
+         sets {@link android.R.attr#windowFullscreen} to true.
+
+         @deprecated Use Material themes on API 21+ or AppCompat on supported APIs. -->
     <style name="Theme.Holo.Light.NoActionBar.Fullscreen">
         <item name="windowFullscreen">true</item>
         <item name="windowContentOverlay">@null</item>
@@ -823,7 +903,9 @@
     <!-- Variant of the holographic (light) theme that has no title bar and fills
          the entire screen and extends into the display overscan region.  This theme
          sets {@link android.R.attr#windowFullscreen} and {@link android.R.attr#windowOverscan}
-         to true. -->
+         to true.
+
+         @deprecated Use Material themes on API 21+ or AppCompat on supported APIs. -->
     <style name="Theme.Holo.Light.NoActionBar.Overscan">
         <item name="windowFullscreen">true</item>
         <item name="windowOverscan">true</item>
@@ -832,7 +914,9 @@
 
     <!-- Variant of the holographic (light) theme that has no title bar and translucent
          system decor.  This theme sets {@link android.R.attr#windowTranslucentStatus} and
-         {@link android.R.attr#windowTranslucentNavigation} to true. -->
+         {@link android.R.attr#windowTranslucentNavigation} to true.
+
+         @deprecated Use Material themes on API 21+ or AppCompat on supported APIs. -->
     <style name="Theme.Holo.Light.NoActionBar.TranslucentDecor">
         <item name="windowTranslucentStatus">true</item>
         <item name="windowTranslucentNavigation">true</item>
@@ -848,7 +932,9 @@
          contents.  You can set this theme on an activity if you would like to
          make an activity that looks like a Dialog.
          This is the default Dialog theme for applications targeting Honeycomb
-         or newer. -->
+         or newer.
+
+         @deprecated Use Material themes on API 21+ or AppCompat on supported APIs. -->
     <style name="Theme.Holo.Dialog">
         <item name="windowFrame">@null</item>
         <item name="windowTitleStyle">@style/DialogWindowTitle.Holo</item>
@@ -878,26 +964,34 @@
     </style>
 
     <!-- Variant of Theme.Holo.Dialog that has a nice minimum width for
-         a regular dialog. -->
+         a regular dialog.
+
+         @deprecated Use Material themes on API 21+ or AppCompat on supported APIs. -->
     <style name="Theme.Holo.Dialog.MinWidth">
         <item name="windowMinWidthMajor">@dimen/dialog_min_width_major</item>
         <item name="windowMinWidthMinor">@dimen/dialog_min_width_minor</item>
     </style>
 
-    <!-- Variant of Theme.Holo.Dialog that does not include a title bar. -->
+    <!-- Variant of Theme.Holo.Dialog that does not include a title bar.
+
+         @deprecated Use Material themes on API 21+ or AppCompat on supported APIs. -->
     <style name="Theme.Holo.Dialog.NoActionBar">
         <item name="windowActionBar">false</item>
         <item name="windowNoTitle">true</item>
     </style>
 
     <!-- Variant of Theme.Holo.Dialog.NoActionBar that has a nice minimum width for
-         a regular dialog. -->
+         a regular dialog.
+
+         @deprecated Use Material themes on API 21+ or AppCompat on supported APIs. -->
     <style name="Theme.Holo.Dialog.NoActionBar.MinWidth">
         <item name="windowMinWidthMajor">@dimen/dialog_min_width_major</item>
         <item name="windowMinWidthMinor">@dimen/dialog_min_width_minor</item>
     </style>
 
-    <!-- Variant of Theme.Holo.Dialog that has a fixed size. -->
+    <!-- Variant of Theme.Holo.Dialog that has a fixed size.
+
+         @deprecated Use Material themes on API 21+ or AppCompat on supported APIs. -->
     <style name="Theme.Holo.Dialog.FixedSize">
         <item name="windowFixedWidthMajor">@dimen/dialog_fixed_width_major</item>
         <item name="windowFixedWidthMinor">@dimen/dialog_fixed_width_minor</item>
@@ -905,7 +999,9 @@
         <item name="windowFixedHeightMinor">@dimen/dialog_fixed_height_minor</item>
     </style>
 
-    <!-- Variant of Theme.Holo.Dialog.NoActionBar that has a fixed size. -->
+    <!-- Variant of Theme.Holo.Dialog.NoActionBar that has a fixed size.
+
+         @deprecated Use Material themes on API 21+ or AppCompat on supported APIs. -->
     <style name="Theme.Holo.Dialog.NoActionBar.FixedSize">
         <item name="windowFixedWidthMajor">@dimen/dialog_fixed_width_major</item>
         <item name="windowFixedWidthMinor">@dimen/dialog_fixed_width_minor</item>
@@ -915,7 +1011,9 @@
 
     <!-- Variant of Theme.Holo.Dialog that does not include a frame (or background).
          The view hierarchy of the dialog is responsible for drawing all of
-         its pixels. -->
+         its pixels.
+
+         @deprecated Use Material themes on API 21+ or AppCompat on supported APIs. -->
     <style name="Theme.Holo.Dialog.NoFrame">
         <item name="windowBackground">@color/transparent</item>
         <item name="windowFrame">@null</item>
@@ -939,20 +1037,28 @@
          {@link android.app.AlertDialog} class.  This is basically a dialog
          but sets the background to empty so it can do two-tone backgrounds.
          For applications targeting Honeycomb or newer, this is the default
-         AlertDialog theme. -->
+         AlertDialog theme.
+
+         @deprecated Use Material themes on API 21+ or AppCompat on supported APIs. -->
     <style name="Theme.Holo.Dialog.Alert" parent="Theme.Holo.Dialog.BaseAlert" />
 
     <!-- Theme for a window that will be displayed either full-screen on
          smaller screens (small, normal) or as a dialog on larger screens
-         (large, xlarge). -->
+         (large, xlarge).
+
+         @deprecated Use Material themes on API 21+ or AppCompat on supported APIs. -->
     <style name="Theme.Holo.DialogWhenLarge" parent="Theme.Holo" />
 
     <!-- Theme for a window without a title bar that will be displayed either
          full-screen on smaller screens (small, normal) or as a dialog on larger screens
-         (large, xlarge). -->
+         (large, xlarge).
+
+         @deprecated Use Material themes on API 21+ or AppCompat on supported APIs. -->
     <style name="Theme.Holo.DialogWhenLarge.NoActionBar" parent="Theme.Holo.NoActionBar" />
 
-    <!-- Theme for a presentation window on a secondary display. -->
+    <!-- Theme for a presentation window on a secondary display.
+
+         @deprecated Use Material themes on API 21+ or AppCompat on supported APIs. -->
     <style name="Theme.Holo.Dialog.Presentation" parent="Theme.Holo.NoActionBar.Fullscreen" />
 
     <!-- Light holo dialog themes -->
@@ -963,7 +1069,9 @@
          contents.  You can set this theme on an activity if you would like to
          make an activity that looks like a Dialog.
          This is the default Dialog theme for applications targeting Honeycomb
-         or newer. -->
+         or newer.
+
+         @deprecated Use Material themes on API 21+ or AppCompat on supported APIs. -->
     <style name="Theme.Holo.Light.Dialog">
         <item name="windowFrame">@null</item>
         <item name="windowTitleStyle">@style/DialogWindowTitle.Holo.Light</item>
@@ -993,26 +1101,34 @@
     </style>
 
     <!-- Variant of Theme.Holo.Light.Dialog that has a nice minimum width for
-         a regular dialog. -->
+         a regular dialog.
+
+         @deprecated Use Material themes on API 21+ or AppCompat on supported APIs. -->
     <style name="Theme.Holo.Light.Dialog.MinWidth">
         <item name="windowMinWidthMajor">@dimen/dialog_min_width_major</item>
         <item name="windowMinWidthMinor">@dimen/dialog_min_width_minor</item>
     </style>
 
-    <!-- Variant of Theme.Holo.Light.Dialog that does not include a title bar. -->
+    <!-- Variant of Theme.Holo.Light.Dialog that does not include a title bar.
+
+         @deprecated Use Material themes on API 21+ or AppCompat on supported APIs. -->
     <style name="Theme.Holo.Light.Dialog.NoActionBar">
         <item name="windowActionBar">false</item>
         <item name="windowNoTitle">true</item>
     </style>
 
     <!-- Variant of Theme.Holo.Light.Dialog.NoActionBar that has a nice minimum width for
-         a regular dialog. -->
+         a regular dialog.
+
+         @deprecated Use Material themes on API 21+ or AppCompat on supported APIs. -->
     <style name="Theme.Holo.Light.Dialog.NoActionBar.MinWidth">
         <item name="windowMinWidthMajor">@dimen/dialog_min_width_major</item>
         <item name="windowMinWidthMinor">@dimen/dialog_min_width_minor</item>
     </style>
 
-    <!-- Variant of Theme.Holo.Light.Dialog that has a fixed size. -->
+    <!-- Variant of Theme.Holo.Light.Dialog that has a fixed size.
+
+         @deprecated Use Material themes on API 21+ or AppCompat on supported APIs. -->
     <style name="Theme.Holo.Light.Dialog.FixedSize">
         <item name="windowFixedWidthMajor">@dimen/dialog_fixed_width_major</item>
         <item name="windowFixedWidthMinor">@dimen/dialog_fixed_width_minor</item>
@@ -1020,7 +1136,9 @@
         <item name="windowFixedHeightMinor">@dimen/dialog_fixed_height_minor</item>
     </style>
 
-    <!-- Variant of Theme.Holo.Light.Dialog.NoActionBar that has a fixed size. -->
+    <!-- Variant of Theme.Holo.Light.Dialog.NoActionBar that has a fixed size.
+
+         @deprecated Use Material themes on API 21+ or AppCompat on supported APIs. -->
     <style name="Theme.Holo.Light.Dialog.NoActionBar.FixedSize">
         <item name="windowFixedWidthMajor">@dimen/dialog_fixed_width_major</item>
         <item name="windowFixedWidthMinor">@dimen/dialog_fixed_width_minor</item>
@@ -1030,12 +1148,16 @@
 
     <!-- Theme for a window that will be displayed either full-screen on
          smaller screens (small, normal) or as a dialog on larger screens
-         (large, xlarge). -->
+         (large, xlarge).
+
+         @deprecated Use Material themes on API 21+ or AppCompat on supported APIs. -->
     <style name="Theme.Holo.Light.DialogWhenLarge" parent="Theme.Holo.Light" />
 
     <!-- Theme for a window without an action bar that will be displayed either full-screen
          on smaller screens (small, normal) or as a dialog on larger screens
-         (large, xlarge). -->
+         (large, xlarge).
+
+         @deprecated Use Material themes on API 21+ or AppCompat on supported APIs. -->
     <style name="Theme.Holo.Light.DialogWhenLarge.NoActionBar" parent="Theme.Holo.Light.NoActionBar" />
 
     <style name="Theme.Holo.Light.Dialog.BaseAlert">
@@ -1050,14 +1172,20 @@
          {@link android.app.AlertDialog} class.  This is basically a dialog
          but sets the background to empty so it can do two-tone backgrounds.
          For applications targeting Honeycomb or newer, this is the default
-         AlertDialog theme. -->
+         AlertDialog theme.
+
+         @deprecated Use Material themes on API 21+ or AppCompat on supported APIs. -->
     <style name="Theme.Holo.Light.Dialog.Alert" parent="Theme.Holo.Light.Dialog.BaseAlert" />
 
-    <!-- Theme for a presentation window on a secondary display. -->
+    <!-- Theme for a presentation window on a secondary display.
+
+         @deprecated Use Material themes on API 21+ or AppCompat on supported APIs. -->
     <style name="Theme.Holo.Light.Dialog.Presentation" parent="Theme.Holo.Light.NoActionBar.Fullscreen" />
 
     <!-- Default holographic (dark) for windows that want to have the user's selected
-         wallpaper appear behind them.  -->
+         wallpaper appear behind them.
+
+         @deprecated Use Material themes on API 21+ or AppCompat on supported APIs. -->
     <style name="Theme.Holo.Wallpaper">
         <item name="windowBackground">@color/transparent</item>
         <item name="colorBackgroundCacheHint">@null</item>
@@ -1065,7 +1193,9 @@
     </style>
 
     <!--Default holographic (dark) for windows that want to have the user's selected
-         wallpaper appear behind them and without an action bar. -->
+         wallpaper appear behind them and without an action bar.
+
+         @deprecated Use Material themes on API 21+ or AppCompat on supported APIs. -->
     <style name="Theme.Holo.Wallpaper.NoTitleBar">
         <item name="windowNoTitle">true</item>
     </style>
@@ -1073,7 +1203,9 @@
     <!-- Default holo dark theme for panel windows.  This removes all extraneous
          window decorations, so you basically have an empty rectangle in which
          to place your content.  It makes the window floating, with a transparent
-         background, and turns off dimming behind the window. -->
+         background, and turns off dimming behind the window.
+
+         @deprecated Use Material themes on API 21+ or AppCompat on supported APIs. -->
     <style name="Theme.Holo.Panel">
         <item name="windowBackground">@color/transparent</item>
         <item name="colorBackgroundCacheHint">@null</item>
@@ -1089,7 +1221,9 @@
     <!-- Default holo light theme for panel windows.  This removes all extraneous
          window decorations, so you basically have an empty rectangle in which
          to place your content.  It makes the window floating, with a transparent
-         background, and turns off dimming behind the window. -->
+         background, and turns off dimming behind the window.
+
+         @deprecated Use Material themes on API 21+ or AppCompat on supported APIs. -->
     <style name="Theme.Holo.Light.Panel">
         <item name="windowBackground">@color/transparent</item>
         <item name="colorBackgroundCacheHint">@null</item>
@@ -1105,7 +1239,9 @@
     <!-- Default theme for holo style input methods, which is used by the
          {@link android.inputmethodservice.InputMethodService} class.
          this inherits from Theme.Panel, but sets up IME appropriate animations
-         and a few custom attributes. -->
+         and a few custom attributes.
+
+         @deprecated Use Material themes on API 21+ or AppCompat on supported APIs. -->
     <style name="Theme.Holo.InputMethod" parent="Theme.Holo.Light.Panel">
         <item name="windowAnimationStyle">@style/Animation.InputMethod</item>
         <item name="imeFullscreenBackground">@drawable/screen_background_selector_light</item>
@@ -1113,17 +1249,19 @@
         <item name="imeExtractExitAnimation">@anim/input_method_extract_exit</item>
     </style>
 
-
+    <!-- @deprecated Use Material themes on API 21+ or AppCompat on supported APIs. -->
     <style name="Theme.Holo.SearchBar" parent="Theme.Holo.Panel">
         <item name="actionModeBackground">@drawable/cab_background_top_holo_dark</item>
         <item name="actionModeSplitBackground">@drawable/cab_background_bottom_holo_light</item>
     </style>
 
+    <!-- @deprecated Use Material themes on API 21+ or AppCompat on supported APIs. -->
     <style name="Theme.Holo.Light.SearchBar" parent="Theme.Holo.Light.Panel">
         <item name="actionModeBackground">@drawable/cab_background_top_holo_light</item>
         <item name="actionModeSplitBackground">@drawable/cab_background_bottom_holo_light</item>
     </style>
 
+    <!-- @deprecated Use Material themes on API 21+ or AppCompat on supported APIs. -->
     <style name="Theme.Holo.CompactMenu">
         <!-- Menu/item attributes -->
         <item name="itemTextAppearance">?attr/textAppearanceMedium</item>
@@ -1132,6 +1270,7 @@
         <item name="background">@null</item>
     </style>
 
+    <!-- @deprecated Use Material themes on API 21+ or AppCompat on supported APIs. -->
     <style name="Theme.Holo.Light.CompactMenu">
         <!-- Menu/item attributes -->
         <item name="itemTextAppearance">?attr/textAppearanceMedium</item>
diff --git a/core/res/res/values/themes_material.xml b/core/res/res/values/themes_material.xml
index 15d8fb7..6ae0ef3 100644
--- a/core/res/res/values/themes_material.xml
+++ b/core/res/res/values/themes_material.xml
@@ -384,7 +384,6 @@
         <!-- DatePicker dialog theme -->
         <item name="datePickerDialogTheme">@style/ThemeOverlay.Material.Dialog.DatePicker</item>
 
-        <!-- TODO: This belongs in a FastScroll style -->
         <item name="fastScrollThumbDrawable">@drawable/fastscroll_thumb_material</item>
         <item name="fastScrollPreviewBackgroundLeft">@drawable/fastscroll_label_left_material</item>
         <item name="fastScrollPreviewBackgroundRight">@drawable/fastscroll_label_right_material</item>
diff --git a/core/res/res/xml/color_extraction.xml b/core/res/res/xml/color_extraction.xml
index 7d52b20..93ab0ff 100644
--- a/core/res/res/xml/color_extraction.xml
+++ b/core/res/res/xml/color_extraction.xml
@@ -257,52 +257,58 @@
         <!-- Red Orange -->
         <range h="20, 40"
                s="0.7, 1"
-               l="0.28, 0.643"/>
+               l="0.2, 0.643"/>
         <range h="20, 40"
                s="0.3, 0.7"
                l="0.414, 0.561"/>
         <range h="20, 40"
-               s="0, 3"
+               s="0, 0.3"
                l="0.343, 0.584"/>
         <!-- Orange -->
         <range h="40, 60"
                s="0.7, 1"
-               l="0.173, 0.349"/>
+               l="0.173, 0.38"/>
         <range h="40, 60"
                s="0.3, 0.7"
                l="0.233, 0.427"/>
         <range h="40, 60"
                s="0, 0.3"
-               l="0.231, 0.484"/>
+               l="0.231, 0.48"/>
         <!-- Yellow 60 -->
         <range h="60, 80"
                s="0.7, 1"
-               l="0.488, 0.737"/>
+               l="0.15, 0.40"/>
         <range h="60, 80"
                s="0.3, 0.7"
-               l="0.673, 0.837"/>
+               l="0.15, 0.42"/>
+        <range h="60, 80"
+               s="0, 0.3"
+               l="0.35, 0.57"/>
         <!-- Yellow Green 80 -->
         <range h="80, 100"
                s="0.7, 1"
-               l="0.469, 0.61"/>
+               l="0.36, 0.65"/>
+        <range h="80, 100"
+               s="0.3, 0.7"
+               l="0.48, 0.57"/>
         <!-- Yellow green 100 -->
         <range h="100, 120"
                s="0.7, 1"
-               l="0.388, 0.612"/>
+               l="0.388, 0.67"/>
         <range h="100, 120"
                s="0.3, 0.7"
-               l="0.424, 0.541"/>
+               l="0.424, 0.58"/>
         <!-- Green -->
         <range h="120, 140"
                s="0.7, 1"
-               l="0.375, 0.52"/>
+               l="0.37, 0.65"/>
         <range h="120, 140"
                s="0.3, 0.7"
-               l="0.435, 0.524"/>
+               l="0.435, 0.58"/>
         <!-- Green Blue 140 -->
         <range h="140, 160"
                s="0.7, 1"
-               l="0.496, 0.641"/>
+               l="0.43, 0.641"/>
         <!-- Seaoam -->
         <range h="160, 180"
                s="0.7, 1"
diff --git a/core/res/res/xml/default_zen_mode_config.xml b/core/res/res/xml/default_zen_mode_config.xml
index a446088..7849a2a 100644
--- a/core/res/res/xml/default_zen_mode_config.xml
+++ b/core/res/res/xml/default_zen_mode_config.xml
@@ -18,7 +18,7 @@
 -->
 
 <!-- Default configuration for zen mode.  See android.service.notification.ZenModeConfig. -->
-<zen version="2">
+<zen version="3">
     <allow alarms="true" media_system_other="true" calls="false" messages="false" reminders="false"
            events="false" />
 </zen>
diff --git a/core/tests/coretests/res/layout/activity_text_view.xml b/core/tests/coretests/res/layout/activity_text_view.xml
index dca1656..d5be87d 100644
--- a/core/tests/coretests/res/layout/activity_text_view.xml
+++ b/core/tests/coretests/res/layout/activity_text_view.xml
@@ -24,6 +24,9 @@
             android:id="@+id/textview"
             android:layout_width="match_parent"
             android:layout_height="wrap_content" />
+    <Space
+        android:layout_width="1dp"
+        android:layout_height="60dp"/>
 
     <TextView
         android:id="@+id/nonselectable_textview"
diff --git a/core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java b/core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java
index aefc47e..fb0f534 100644
--- a/core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java
+++ b/core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java
@@ -17,6 +17,7 @@
 package android.app.servertransaction;
 
 import static android.app.servertransaction.TestUtils.config;
+import static android.app.servertransaction.TestUtils.mergedConfig;
 import static android.app.servertransaction.TestUtils.referrerIntentList;
 import static android.app.servertransaction.TestUtils.resultInfoList;
 
@@ -151,6 +152,25 @@
     }
 
     @Test
+    public void testRecycleActivityRelaunchItem() {
+        ActivityRelaunchItem emptyItem = ActivityRelaunchItem.obtain(null, null, 0, null, false);
+        Configuration overrideConfig = new Configuration();
+        overrideConfig.assetsSeq = 5;
+        ActivityRelaunchItem item = ActivityRelaunchItem.obtain(resultInfoList(),
+                referrerIntentList(), 42, mergedConfig(), true);
+        assertNotSame(item, emptyItem);
+        assertFalse(item.equals(emptyItem));
+
+        item.recycle();
+        assertEquals(item, emptyItem);
+
+        ActivityRelaunchItem item2 = ActivityRelaunchItem.obtain(resultInfoList(),
+                referrerIntentList(), 42, mergedConfig(), true);
+        assertSame(item, item2);
+        assertFalse(item2.equals(emptyItem));
+    }
+
+    @Test
     public void testRecycleMoveToDisplayItem() {
         MoveToDisplayItem emptyItem = MoveToDisplayItem.obtain(0, null);
         MoveToDisplayItem item = MoveToDisplayItem.obtain(4, config());
diff --git a/core/tests/coretests/src/android/app/servertransaction/TestUtils.java b/core/tests/coretests/src/android/app/servertransaction/TestUtils.java
index e923516..d125fe7 100644
--- a/core/tests/coretests/src/android/app/servertransaction/TestUtils.java
+++ b/core/tests/coretests/src/android/app/servertransaction/TestUtils.java
@@ -21,6 +21,7 @@
 import android.app.ResultInfo;
 import android.content.Intent;
 import android.content.res.Configuration;
+import android.util.MergedConfiguration;
 
 import com.android.internal.content.ReferrerIntent;
 
@@ -38,6 +39,15 @@
         return config;
     }
 
+    static MergedConfiguration mergedConfig() {
+        Configuration config = config();
+        Configuration overrideConfig = new Configuration();
+        overrideConfig.densityDpi = 30;
+        overrideConfig.screenWidthDp = 40;
+        overrideConfig.smallestScreenWidthDp = 15;
+        return new MergedConfiguration(config, overrideConfig);
+    }
+
     static List<ResultInfo> resultInfoList() {
         String resultWho1 = "resultWho1";
         int requestCode1 = 7;
diff --git a/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java b/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java
index 77aaa2d..0906435 100644
--- a/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java
+++ b/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java
@@ -17,6 +17,7 @@
 package android.app.servertransaction;
 
 import static android.app.servertransaction.TestUtils.config;
+import static android.app.servertransaction.TestUtils.mergedConfig;
 import static android.app.servertransaction.TestUtils.referrerIntentList;
 import static android.app.servertransaction.TestUtils.resultInfoList;
 
@@ -27,7 +28,6 @@
 import android.app.IInstrumentationWatcher;
 import android.app.IUiAutomationConnection;
 import android.app.ProfilerInfo;
-import android.app.ResultInfo;
 import android.content.ComponentName;
 import android.content.IIntentReceiver;
 import android.content.Intent;
@@ -53,7 +53,6 @@
 import android.support.test.runner.AndroidJUnit4;
 
 import com.android.internal.app.IVoiceInteractor;
-import com.android.internal.content.ReferrerIntent;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -243,6 +242,22 @@
     }
 
     @Test
+    public void testRelaunch() {
+        // Write to parcel
+        Configuration overrideConfig = new Configuration();
+        overrideConfig.assetsSeq = 5;
+        ActivityRelaunchItem item = ActivityRelaunchItem.obtain(resultInfoList(),
+                referrerIntentList(), 35, mergedConfig(), true);
+        writeAndPrepareForReading(item);
+
+        // Read from parcel and assert
+        ActivityRelaunchItem result = ActivityRelaunchItem.CREATOR.createFromParcel(mParcel);
+
+        assertEquals(item.hashCode(), result.hashCode());
+        assertTrue(item.equals(result));
+    }
+
+    @Test
     public void testPause() {
         // Write to parcel
         PauseActivityItem item = PauseActivityItem.obtain(true /* finished */,
@@ -435,12 +450,6 @@
         }
 
         @Override
-        public void scheduleRelaunchActivity(IBinder iBinder, List<ResultInfo> list,
-                List<ReferrerIntent> list1, int i, boolean b, Configuration configuration,
-                Configuration configuration1, boolean b1) throws RemoteException {
-        }
-
-        @Override
         public void scheduleSleeping(IBinder iBinder, boolean b) throws RemoteException {
         }
 
diff --git a/core/tests/coretests/src/android/os/VibrationEffectTest.java b/core/tests/coretests/src/android/os/VibrationEffectTest.java
new file mode 100644
index 0000000..c7fdf0f
--- /dev/null
+++ b/core/tests/coretests/src/android/os/VibrationEffectTest.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.assertNull;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.net.Uri;
+
+import com.android.internal.R;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.junit.MockitoJUnitRunner;
+
+@RunWith(MockitoJUnitRunner.class)
+public class VibrationEffectTest {
+    private static final String RINGTONE_URI_1 = "content://test/system/ringtone_1";
+    private static final String RINGTONE_URI_2 = "content://test/system/ringtone_2";
+    private static final String RINGTONE_URI_3 = "content://test/system/ringtone_3";
+    private static final String UNKNOWN_URI = "content://test/system/other_audio";
+
+    @Test
+    public void getRingtones_noPrebakedRingtones() {
+        Resources r = mockRingtoneResources(new String[0]);
+        Context context = mockContext(r);
+        VibrationEffect effect = VibrationEffect.get(Uri.parse(RINGTONE_URI_1), context);
+        assertNull(effect);
+    }
+
+    @Test
+    public void getRingtones_noPrebakedRingtoneForUri() {
+        Resources r = mockRingtoneResources();
+        Context context = mockContext(r);
+        VibrationEffect effect = VibrationEffect.get(Uri.parse(UNKNOWN_URI), context);
+        assertNull(effect);
+    }
+
+    @Test
+    public void getRingtones_getPrebakedRingtone() {
+        Resources r = mockRingtoneResources();
+        Context context = mockContext(r);
+        VibrationEffect effect = VibrationEffect.get(Uri.parse(RINGTONE_URI_2), context);
+        VibrationEffect expectedEffect = VibrationEffect.get(VibrationEffect.RINGTONES[1]);
+        assertNotNull(expectedEffect);
+        assertEquals(expectedEffect, effect);
+    }
+
+
+    private Resources mockRingtoneResources() {
+        return mockRingtoneResources(new String[] {
+                RINGTONE_URI_1,
+                RINGTONE_URI_2,
+                RINGTONE_URI_3
+        });
+    }
+
+    private Resources mockRingtoneResources(String[] ringtoneUris) {
+        Resources mockResources = mock(Resources.class);
+        when(mockResources.getStringArray(R.array.config_ringtoneEffectUris))
+                .thenReturn(ringtoneUris);
+        return mockResources;
+    }
+
+    private Context mockContext(Resources r) {
+        Context ctx = mock(Context.class);
+        when(ctx.getResources()).thenReturn(r);
+        return ctx;
+    }
+}
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index 32d7ddd..38e20a1 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,
@@ -354,6 +354,7 @@
                     Settings.Global.SHOW_NOTIFICATION_CHANNEL_WARNINGS,
                     Settings.Global.SHOW_RESTART_IN_CRASH_DIALOG,
                     Settings.Global.SHOW_TEMPERATURE_WARNING,
+                    Settings.Global.SHOW_ZEN_UPGRADE_NOTIFICATION,
                     Settings.Global.SMART_SELECTION_UPDATE_CONTENT_URL,
                     Settings.Global.SMART_SELECTION_UPDATE_METADATA_URL,
                     Settings.Global.SMS_OUTGOING_CHECK_INTERVAL_MS,
@@ -366,6 +367,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,
@@ -400,6 +402,8 @@
                     Settings.Global.GPU_DEBUG_APP,
                     Settings.Global.GPU_DEBUG_LAYERS,
                     Settings.Global.ENABLE_GNSS_RAW_MEAS_FULL_TRACKING,
+                    Settings.Global.INSTALL_CARRIER_APP_NOTIFICATION_PERSISTENT,
+                    Settings.Global.INSTALL_CARRIER_APP_NOTIFICATION_SLEEP_MILLIS,
                     Settings.Global.NETWORK_ACCESS_TIMEOUT_MS,
                     Settings.Global.WARNING_TEMPERATURE,
                     Settings.Global.WEBVIEW_DATA_REDUCTION_PROXY_KEY,
@@ -443,14 +447,15 @@
                     Settings.Global.WIFI_WATCHDOG_ON,
                     Settings.Global.WIMAX_NETWORKS_AVAILABLE_NOTIFICATION_ON,
                     Settings.Global.WINDOW_ANIMATION_SCALE,
-                    Settings.Global.WIRELESS_CHARGING_STARTED_SOUND,
+                    Settings.Global.CHARGING_STARTED_SOUND,
                     Settings.Global.WTF_IS_FATAL,
                     Settings.Global.ZEN_MODE,
                     Settings.Global.ZEN_MODE_CONFIG_ETAG,
                     Settings.Global.ZEN_MODE_RINGER_LEVEL,
                     Settings.Global.ZRAM_ENABLED,
                     Settings.Global.OVERRIDE_SETTINGS_PROVIDER_RESTORE_ANY_VERSION,
-                    Settings.Global.CHAINED_BATTERY_ATTRIBUTION_ENABLED);
+                    Settings.Global.CHAINED_BATTERY_ATTRIBUTION_ENABLED,
+                    Settings.Global.HIDDEN_API_BLACKLIST_EXEMPTIONS);
 
     private static final Set<String> BACKUP_BLACKLISTED_SECURE_SETTINGS =
              newHashSet(
@@ -465,6 +470,7 @@
                  Settings.Secure.ASSIST_SCREENSHOT_ENABLED,
                  Settings.Secure.ASSIST_STRUCTURE_ENABLED,
                  Settings.Secure.AUTOFILL_FEATURE_FIELD_CLASSIFICATION,
+                 Settings.Secure.AUTOFILL_USER_DATA_MAX_CATEGORY_COUNT,
                  Settings.Secure.AUTOFILL_USER_DATA_MAX_FIELD_CLASSIFICATION_IDS_SIZE,
                  Settings.Secure.AUTOFILL_USER_DATA_MAX_USER_DATA_SIZE,
                  Settings.Secure.AUTOFILL_USER_DATA_MAX_VALUE_LENGTH,
@@ -492,6 +498,7 @@
                  Settings.Secure.DOZE_ALWAYS_ON,
                  Settings.Secure.DOZE_PULSE_ON_LONG_PRESS,
                  Settings.Secure.EMERGENCY_ASSISTANCE_APPLICATION,
+                 Settings.Secure.ENABLED_INPUT_METHODS,  // Intentionally removed in P
                  Settings.Secure.ENABLED_NOTIFICATION_ASSISTANT,
                  Settings.Secure.ENABLED_NOTIFICATION_LISTENERS,
                  Settings.Secure.ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES,
@@ -558,6 +565,7 @@
                  Settings.Secure.VOICE_RECOGNITION_SERVICE,
                  Settings.Secure.INSTANT_APPS_ENABLED,
                  Settings.Secure.BACKUP_MANAGER_CONSTANTS,
+                 Settings.Secure.BACKUP_LOCAL_TRANSPORT_PARAMETERS,
                  Settings.Secure.KEYGUARD_SLICE_URI,
                  Settings.Secure.PARENTAL_CONTROL_ENABLED,
                  Settings.Secure.PARENTAL_CONTROL_REDIRECT_URL,
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/text/OWNERS b/core/tests/coretests/src/android/text/OWNERS
index 0f85e1f..a35c604 100644
--- a/core/tests/coretests/src/android/text/OWNERS
+++ b/core/tests/coretests/src/android/text/OWNERS
@@ -1,4 +1,5 @@
+set noparent
+
 siyamed@google.com
 nona@google.com
-clarabayarri@google.com
-toki@google.com
+clarabayarri@google.com
\ No newline at end of file
diff --git a/core/tests/coretests/src/android/view/menu/ContextMenuTest.java b/core/tests/coretests/src/android/view/menu/ContextMenuTest.java
index 59d4e55..657a7fc 100644
--- a/core/tests/coretests/src/android/view/menu/ContextMenuTest.java
+++ b/core/tests/coretests/src/android/view/menu/ContextMenuTest.java
@@ -41,6 +41,13 @@
         testMenuPosition(getActivity().getTargetRtl());
     }
 
+    public void testContextMenuPositionRepetitive() throws InterruptedException {
+        // Regression test for b/72507876
+        testMenuPosition(getActivity().getTargetLtr());
+        testMenuPosition(getActivity().getTargetRtl());
+        testMenuPosition(getActivity().getTargetLtr());
+    }
+
     private void testMenuPosition(View target) throws InterruptedException {
         final int minScreenDimension = getMinScreenDimension();
         if (minScreenDimension < 320) {
diff --git a/core/tests/coretests/src/android/view/textclassifier/TextClassificationManagerTest.java b/core/tests/coretests/src/android/view/textclassifier/TextClassificationManagerTest.java
index a8de374..430b30f 100644
--- a/core/tests/coretests/src/android/view/textclassifier/TextClassificationManagerTest.java
+++ b/core/tests/coretests/src/android/view/textclassifier/TextClassificationManagerTest.java
@@ -19,6 +19,7 @@
 import static org.hamcrest.CoreMatchers.not;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
 import static org.mockito.Mockito.mock;
 
 import android.os.LocaleList;
@@ -33,6 +34,8 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.util.Arrays;
+
 @SmallTest
 @RunWith(AndroidJUnit4.class)
 public class TextClassificationManagerTest {
@@ -183,6 +186,7 @@
     @Test
     public void testGenerateLinks_none_config() {
         if (isTextClassifierDisabled()) return;
+
         String text = "The number is +12122537077. See you tonight!";
         assertThat(mClassifier.generateLinks(text, mLinksOptions.setEntityConfig(
                 new TextClassifier.EntityConfig(TextClassifier.ENTITY_PRESET_NONE))),
@@ -210,6 +214,25 @@
     }
 
     @Test
+    public void testGenerateLinks_maxLength() {
+        if (isTextClassifierDisabled()) return;
+        char[] manySpaces = new char[mClassifier.getMaxGenerateLinksTextLength()];
+        Arrays.fill(manySpaces, ' ');
+        TextLinks links = mClassifier.generateLinks(new String(manySpaces), null);
+        assertTrue(links.getLinks().isEmpty());
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testGenerateLinks_tooLong() {
+        if (isTextClassifierDisabled()) {
+            throw new IllegalArgumentException("pass if disabled");
+        }
+        char[] manySpaces = new char[mClassifier.getMaxGenerateLinksTextLength() + 1];
+        Arrays.fill(manySpaces, ' ');
+        mClassifier.generateLinks(new String(manySpaces), null);
+    }
+
+    @Test
     public void testSetTextClassifier() {
         TextClassifier classifier = mock(TextClassifier.class);
         mTcm.setTextClassifier(classifier);
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/android/widget/TextViewActivityTest.java b/core/tests/coretests/src/android/widget/TextViewActivityTest.java
index 69e5670..79433ac 100644
--- a/core/tests/coretests/src/android/widget/TextViewActivityTest.java
+++ b/core/tests/coretests/src/android/widget/TextViewActivityTest.java
@@ -66,6 +66,7 @@
 import android.support.test.filters.MediumTest;
 import android.support.test.rule.ActivityTestRule;
 import android.support.test.runner.AndroidJUnit4;
+import android.support.test.uiautomator.UiDevice;
 import android.test.suitebuilder.annotation.Suppress;
 import android.text.InputType;
 import android.text.Selection;
@@ -311,15 +312,69 @@
 
     @Test
     public void testToolbarAppearsAfterLinkClicked() throws Throwable {
-        runToolbarAppearsAfterLinkClickedTest(R.id.textview);
+        TextLinks.TextLink textLink = addLinkifiedTextToTextView(R.id.textview);
+        int position = (textLink.getStart() + textLink.getEnd()) / 2;
+        onView(withId(R.id.textview)).perform(clickOnTextAtIndex(position));
+        sleepForFloatingToolbarPopup();
+        assertFloatingToolbarIsDisplayed();
+
     }
 
     @Test
     public void testToolbarAppearsAfterLinkClickedNonselectable() throws Throwable {
-        runToolbarAppearsAfterLinkClickedTest(R.id.nonselectable_textview);
+        TextLinks.TextLink textLink = addLinkifiedTextToTextView(R.id.nonselectable_textview);
+        int position = (textLink.getStart() + textLink.getEnd()) / 2;
+        onView(withId(R.id.nonselectable_textview)).perform(clickOnTextAtIndex(position));
+        sleepForFloatingToolbarPopup();
+        assertFloatingToolbarIsDisplayed();
     }
 
-    private void runToolbarAppearsAfterLinkClickedTest(int id) throws Throwable {
+    @Test
+    public void testSelectionRemovedWhenNonselectableTextLosesFocus() throws Throwable {
+        // Add a link to both selectable and nonselectable TextViews:
+        TextLinks.TextLink textLink = addLinkifiedTextToTextView(R.id.textview);
+        int selectablePosition = (textLink.getStart() + textLink.getEnd()) / 2;
+        textLink = addLinkifiedTextToTextView(R.id.nonselectable_textview);
+        int nonselectablePosition = (textLink.getStart() + textLink.getEnd()) / 2;
+        TextView selectableTextView = mActivity.findViewById(R.id.textview);
+        TextView nonselectableTextView = mActivity.findViewById(R.id.nonselectable_textview);
+
+        onView(withId(R.id.nonselectable_textview))
+                .perform(clickOnTextAtIndex(nonselectablePosition));
+        sleepForFloatingToolbarPopup();
+        assertFloatingToolbarIsDisplayed();
+        assertTrue(nonselectableTextView.hasSelection());
+
+        onView(withId(R.id.textview)).perform(clickOnTextAtIndex(selectablePosition));
+        sleepForFloatingToolbarPopup();
+        assertFloatingToolbarIsDisplayed();
+
+        assertTrue(selectableTextView.hasSelection());
+        assertFalse(nonselectableTextView.hasSelection());
+    }
+
+    @Test
+    public void testSelectionRemovedFromNonselectableTextWhenWindowLosesFocus() throws Throwable {
+        TextLinks.TextLink textLink = addLinkifiedTextToTextView(R.id.nonselectable_textview);
+        int nonselectablePosition = (textLink.getStart() + textLink.getEnd()) / 2;
+        TextView nonselectableTextView = mActivity.findViewById(R.id.nonselectable_textview);
+
+        onView(withId(R.id.nonselectable_textview))
+                .perform(clickOnTextAtIndex(nonselectablePosition));
+        sleepForFloatingToolbarPopup();
+        assertFloatingToolbarIsDisplayed();
+        assertTrue(nonselectableTextView.hasSelection());
+
+        UiDevice device = UiDevice.getInstance(mInstrumentation);
+        device.openNotification();
+        Thread.sleep(2000);
+        device.pressBack();
+        Thread.sleep(2000);
+
+        assertFalse(nonselectableTextView.hasSelection());
+    }
+
+    private TextLinks.TextLink addLinkifiedTextToTextView(int id) throws Throwable {
         TextView textView = mActivity.findViewById(id);
         useSystemDefaultTextClassifier();
         TextClassificationManager textClassificationManager =
@@ -327,7 +382,7 @@
         TextClassifier textClassifier = textClassificationManager.getTextClassifier();
         Spannable content = new SpannableString("Call me at +19148277737");
         TextLinks links = textClassifier.generateLinks(content);
-        links.apply(content, TextLinks.APPLY_STRATEGY_REPLACE, null);
+        links.apply(content, TextLinks.APPLY_STRATEGY_REPLACE, null, false /* allowPrefix */);
 
         mActivityRule.runOnUiThread(() -> {
             textView.setText(content);
@@ -338,11 +393,7 @@
         // Wait for the UI thread to refresh
         Thread.sleep(1000);
 
-        TextLinks.TextLink textLink = links.getLinks().iterator().next();
-        int position = (textLink.getStart() + textLink.getEnd()) / 2;
-        onView(withId(id)).perform(clickOnTextAtIndex(position));
-        sleepForFloatingToolbarPopup();
-        assertFloatingToolbarIsDisplayed();
+        return links.getLinks().iterator().next();
     }
 
     @Test
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsCpuTimesTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsCpuTimesTest.java
index 32053e3..cb049b7 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsCpuTimesTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsCpuTimesTest.java
@@ -114,7 +114,7 @@
         when(mKernelUidCpuFreqTimeReader.readFreqs(mPowerProfile)).thenReturn(freqs);
 
         // RUN
-        mBatteryStatsImpl.updateCpuTimeLocked();
+        mBatteryStatsImpl.updateCpuTimeLocked(false, false);
 
         // VERIFY
         assertArrayEquals("Unexpected cpu freqs", freqs, mBatteryStatsImpl.getCpuFreqs());
@@ -134,7 +134,7 @@
         mBatteryStatsImpl.setOnBatteryInternal(true);
 
         // RUN
-        mBatteryStatsImpl.updateCpuTimeLocked();
+        mBatteryStatsImpl.updateCpuTimeLocked(true, false);
 
         // VERIFY
         verify(mUserInfoProvider).refreshUserIds();
@@ -213,7 +213,7 @@
         }
 
         // RUN
-        mBatteryStatsImpl.updateClusterSpeedTimes(updatedUids);
+        mBatteryStatsImpl.updateClusterSpeedTimes(updatedUids, true);
 
         // VERIFY
         int totalClustersTimeMs = 0;
@@ -261,7 +261,7 @@
 
         // RUN
         final SparseLongArray updatedUids = new SparseLongArray();
-        mBatteryStatsImpl.readKernelUidCpuTimesLocked(null, updatedUids);
+        mBatteryStatsImpl.readKernelUidCpuTimesLocked(null, updatedUids, true);
 
         // VERIFY
         for (int i = 0; i < testUids.length; ++i) {
@@ -294,7 +294,7 @@
         }).when(mKernelUidCpuTimeReader).readDelta(any(KernelUidCpuTimeReader.Callback.class));
 
         // RUN
-        mBatteryStatsImpl.readKernelUidCpuTimesLocked(null, null);
+        mBatteryStatsImpl.readKernelUidCpuTimesLocked(null, null, true);
 
         // VERIFY
         for (int i = 0; i < testUids.length; ++i) {
@@ -333,7 +333,7 @@
         }).when(mKernelUidCpuTimeReader).readDelta(any(KernelUidCpuTimeReader.Callback.class));
 
         // RUN
-        mBatteryStatsImpl.readKernelUidCpuTimesLocked(null, null);
+        mBatteryStatsImpl.readKernelUidCpuTimesLocked(null, null, true);
 
         // VERIFY
         for (int i = 0; i < testUids.length; ++i) {
@@ -368,7 +368,7 @@
         }).when(mKernelUidCpuTimeReader).readDelta(any(KernelUidCpuTimeReader.Callback.class));
 
         // RUN
-        mBatteryStatsImpl.readKernelUidCpuTimesLocked(null, null);
+        mBatteryStatsImpl.readKernelUidCpuTimesLocked(null, null, true);
 
         // VERIFY
         for (int i = 0; i < testUids.length; ++i) {
@@ -423,7 +423,7 @@
         }).when(mKernelUidCpuTimeReader).readDelta(any(KernelUidCpuTimeReader.Callback.class));
 
         // RUN
-        mBatteryStatsImpl.readKernelUidCpuTimesLocked(null, null);
+        mBatteryStatsImpl.readKernelUidCpuTimesLocked(null, null, true);
 
         // VERIFY
         for (int i = 0; i < testUids.length; ++i) {
@@ -470,7 +470,7 @@
 
         // RUN
         final SparseLongArray updatedUids = new SparseLongArray();
-        mBatteryStatsImpl.readKernelUidCpuTimesLocked(partialTimers, updatedUids);
+        mBatteryStatsImpl.readKernelUidCpuTimesLocked(partialTimers, updatedUids, true);
 
         // VERIFY
         long totalUserTimeUs = 0;
@@ -549,7 +549,7 @@
                 any(KernelUidCpuFreqTimeReader.Callback.class));
 
         // RUN
-        mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null);
+        mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null, true, false);
 
         // VERIFY
         for (int i = 0; i < testUids.length; ++i) {
@@ -582,7 +582,7 @@
                 any(KernelUidCpuFreqTimeReader.Callback.class));
 
         // RUN
-        mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null);
+        mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null, true, true);
 
         // VERIFY
         for (int i = 0; i < testUids.length; ++i) {
@@ -633,7 +633,7 @@
         when(mKernelUidCpuFreqTimeReader.perClusterTimesAvailable()).thenReturn(true);
 
         // RUN
-        mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null);
+        mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null, true, false);
 
         // VERIFY
         for (int i = 0; i < testUids.length; ++i) {
@@ -676,7 +676,7 @@
                 any(KernelUidCpuFreqTimeReader.Callback.class));
 
         // RUN
-        mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null);
+        mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null, true, true);
 
         // VERIFY
         for (int i = 0; i < testUids.length; ++i) {
@@ -743,7 +743,7 @@
         when(mKernelUidCpuFreqTimeReader.perClusterTimesAvailable()).thenReturn(true);
 
         // RUN
-        mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(partialTimers);
+        mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(partialTimers, true, false);
 
         // VERIFY
         final long[][] expectedWakeLockUidTimesUs = new long[clusterFreqs.length][];
@@ -832,7 +832,7 @@
                 any(KernelUidCpuFreqTimeReader.Callback.class));
 
         // RUN
-        mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null);
+        mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null, true, false);
 
         // VERIFY
         for (int i = 0; i < testUids.length; ++i) {
@@ -865,7 +865,7 @@
                 any(KernelUidCpuFreqTimeReader.Callback.class));
 
         // RUN
-        mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null);
+        mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null, true, true);
 
         // VERIFY
         for (int i = 0; i < testUids.length; ++i) {
@@ -909,7 +909,7 @@
                 any(KernelUidCpuFreqTimeReader.Callback.class));
 
         // RUN
-        mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null);
+        mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null, true, false);
 
         // VERIFY
         for (int i = 0; i < testUids.length; ++i) {
@@ -949,7 +949,7 @@
                 any(KernelUidCpuFreqTimeReader.Callback.class));
 
         // RUN
-        mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null);
+        mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null, true, false);
 
         // VERIFY
         for (int i = 0; i < testUids.length; ++i) {
@@ -1006,7 +1006,7 @@
                 any(KernelUidCpuFreqTimeReader.Callback.class));
 
         // RUN
-        mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null);
+        mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null, true, false);
 
         // VERIFY
         for (int i = 0; i < testUids.length; ++i) {
@@ -1047,7 +1047,7 @@
                 any(KernelUidCpuActiveTimeReader.Callback.class));
 
         // RUN
-        mBatteryStatsImpl.readKernelUidCpuActiveTimesLocked();
+        mBatteryStatsImpl.readKernelUidCpuActiveTimesLocked(true);
 
         // VERIFY
         for (int i = 0; i < testUids.length; ++i) {
@@ -1073,7 +1073,7 @@
                 any(KernelUidCpuActiveTimeReader.Callback.class));
 
         // RUN
-        mBatteryStatsImpl.readKernelUidCpuActiveTimesLocked();
+        mBatteryStatsImpl.readKernelUidCpuActiveTimesLocked(true);
 
         // VERIFY
         for (int i = 0; i < testUids.length; ++i) {
@@ -1112,7 +1112,7 @@
                 any(KernelUidCpuClusterTimeReader.Callback.class));
 
         // RUN
-        mBatteryStatsImpl.readKernelUidCpuClusterTimesLocked();
+        mBatteryStatsImpl.readKernelUidCpuClusterTimesLocked(true);
 
         // VERIFY
         for (int i = 0; i < testUids.length; ++i) {
@@ -1142,7 +1142,7 @@
                 any(KernelUidCpuClusterTimeReader.Callback.class));
 
         // RUN
-        mBatteryStatsImpl.readKernelUidCpuClusterTimesLocked();
+        mBatteryStatsImpl.readKernelUidCpuClusterTimesLocked(true);
 
         // VERIFY
         for (int i = 0; i < testUids.length; ++i) {
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java
index 82ac9da..01ddc15 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java
@@ -161,9 +161,7 @@
 
         actualRunTimeUs = uid.getProcessStateTime(BatteryStats.Uid.PROCESS_STATE_FOREGROUND_SERVICE,
                 elapsedTimeUs, STATS_SINCE_CHARGED);
-        expectedRunTimeMs = stateRuntimeMap.get(
-                ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE)
-                + stateRuntimeMap.get(ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE);
+        expectedRunTimeMs = stateRuntimeMap.get(ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE);
         assertEquals(expectedRunTimeMs * 1000, actualRunTimeUs);
 
         actualRunTimeUs = uid.getProcessStateTime(BatteryStats.Uid.PROCESS_STATE_TOP_SLEEPING,
@@ -173,7 +171,8 @@
 
         actualRunTimeUs = uid.getProcessStateTime(BatteryStats.Uid.PROCESS_STATE_FOREGROUND,
                 elapsedTimeUs, STATS_SINCE_CHARGED);
-        expectedRunTimeMs = stateRuntimeMap.get(ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND);
+        expectedRunTimeMs = stateRuntimeMap.get(ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND)
+                + stateRuntimeMap.get(ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE);
         assertEquals(expectedRunTimeMs * 1000, actualRunTimeUs);
 
         actualRunTimeUs = uid.getProcessStateTime(BatteryStats.Uid.PROCESS_STATE_BACKGROUND,
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..42c9139 100644
--- a/core/tests/coretests/src/com/android/internal/os/BstatsCpuTimesValidationTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BstatsCpuTimesValidationTest.java
@@ -25,6 +25,7 @@
 import static android.os.BatteryStats.Uid.PROCESS_STATE_TOP_SLEEPING;
 import static android.os.BatteryStats.Uid.UID_PROCESS_TYPES;
 
+import static com.android.internal.os.BatteryStatsImpl.Constants.KEY_PROC_STATE_CPU_TIMES_READ_DELAY_MS;
 import static com.android.internal.os.BatteryStatsImpl.Constants.KEY_TRACK_CPU_TIMES_BY_PROC_STATE;
 
 import static junit.framework.Assert.assertNotNull;
@@ -59,6 +60,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;
@@ -100,6 +102,11 @@
 
     private static final int WORK_DURATION_MS = 2000;
 
+    private static final String DESIRED_PROC_STATE_CPU_TIMES_DELAY = "0";
+
+    private static boolean sBatteryStatsConstsUpdated;
+    private static String sOriginalBatteryStatsConsts;
+
     private static Context sContext;
     private static UiDevice sUiDevice;
     private static int sTestPkgUid;
@@ -116,6 +123,41 @@
                 PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 0);
         sTestPkgUid = sContext.getPackageManager().getPackageUid(TEST_PKG, 0);
         checkCpuTimesAvailability();
+        if (sPerProcStateTimesAvailable && sCpuFreqTimesAvailable) {
+            setDesiredReadyDelay();
+        }
+    }
+
+    @AfterClass
+    public static void tearDownOnce() throws Exception {
+        if (sBatteryStatsConstsUpdated) {
+            Settings.Global.putString(sContext.getContentResolver(),
+                    Settings.Global.BATTERY_STATS_CONSTANTS, sOriginalBatteryStatsConsts);
+        }
+        batteryReset();
+    }
+
+    private static void setDesiredReadyDelay() {
+        sOriginalBatteryStatsConsts = Settings.Global.getString(sContext.getContentResolver(),
+                Settings.Global.BATTERY_STATS_CONSTANTS);
+        String newBatteryStatsConstants;
+        final String newConstant = KEY_PROC_STATE_CPU_TIMES_READ_DELAY_MS
+                + "=" + DESIRED_PROC_STATE_CPU_TIMES_DELAY;
+        if (sOriginalBatteryStatsConsts == null || "null".equals(sOriginalBatteryStatsConsts)) {
+            // battery_stats_constants is initially empty, so just assign the desired value.
+            newBatteryStatsConstants = newConstant;
+        } else if (sOriginalBatteryStatsConsts.contains(KEY_PROC_STATE_CPU_TIMES_READ_DELAY_MS)) {
+            // battery_stats_constants contains delay duration, so replace it
+            // with the desired value.
+            newBatteryStatsConstants = sOriginalBatteryStatsConsts.replaceAll(
+                    KEY_PROC_STATE_CPU_TIMES_READ_DELAY_MS + "=\\d+", newConstant);
+        } else {
+            // battery_stats_constants didn't contain any delay, so append the desired value.
+            newBatteryStatsConstants = sOriginalBatteryStatsConsts + "," + newConstant;
+        }
+        Settings.Global.putString(sContext.getContentResolver(),
+                Settings.Global.BATTERY_STATS_CONSTANTS, newBatteryStatsConstants);
+        sBatteryStatsConstsUpdated = true;
     }
 
     // Checks cpu freq times of system uid as an indication of whether /proc/uid_time_in_state
@@ -126,9 +168,9 @@
         batteryOff();
         final long[] totalCpuTimes = getAllCpuFreqTimes(Process.SYSTEM_UID);
         sCpuFreqTimesAvailable = totalCpuTimes != null;
-        final long[] fgSvcCpuTimes = getAllCpuFreqTimes(Process.SYSTEM_UID,
-                PROCESS_STATE_FOREGROUND_SERVICE);
-        sPerProcStateTimesAvailable = fgSvcCpuTimes != null;
+        final long[] fgCpuTimes = getAllCpuFreqTimes(Process.SYSTEM_UID,
+                PROCESS_STATE_FOREGROUND);
+        sPerProcStateTimesAvailable = fgCpuTimes != null;
     }
 
     @Test
@@ -868,12 +910,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/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java b/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java
index 660c744..6d5c7e774 100644
--- a/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java
+++ b/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java
@@ -20,6 +20,7 @@
 import android.os.Looper;
 import android.util.SparseIntArray;
 
+import com.android.internal.location.gnssmetrics.GnssMetrics;
 import java.util.ArrayList;
 import java.util.concurrent.Future;
 
@@ -40,6 +41,11 @@
         mBluetoothScanTimer = new StopwatchTimer(mClocks, null, -14, null, mOnBatteryTimeBase);
         setExternalStatsSyncLocked(new DummyExternalStatsSync());
 
+        for (int i=0; i< GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
+            mGpsSignalQualityTimer[i] = new StopwatchTimer(clocks, null, -1000-i, null,
+                mOnBatteryTimeBase);
+        }
+
         // A no-op handler.
         mHandler = new Handler(Looper.getMainLooper()) {};
     }
@@ -154,8 +160,8 @@
         }
 
         @Override
-        public Future<?> scheduleReadProcStateCpuTimes(
-                boolean onBattery, boolean onBatteryScreenOff) {
+        public Future<?> scheduleReadProcStateCpuTimes(boolean onBattery,
+                boolean onBatteryScreenOff, long delayMillis) {
             return null;
         }
 
@@ -165,6 +171,20 @@
             return null;
         }
 
+        @Override
+        public Future<?> scheduleCpuSyncDueToScreenStateChange(
+                boolean onBattery, boolean onBatteryScreenOff) {
+            return null;
+        }
+
+        @Override
+        public Future<?> scheduleCpuSyncDueToWakelockChange(long delayMillis) {
+            return null;
+        }
+
+        @Override
+        public void cancelCpuSyncDueToWakelockChange() {
+        }
     }
 }
 
diff --git a/core/tests/coretests/src/com/android/internal/widget/MessagingLinearLayoutTest.java b/core/tests/coretests/src/com/android/internal/widget/MessagingLinearLayoutTest.java
index 3919fdd..41082b7 100644
--- a/core/tests/coretests/src/com/android/internal/widget/MessagingLinearLayoutTest.java
+++ b/core/tests/coretests/src/com/android/internal/widget/MessagingLinearLayoutTest.java
@@ -127,7 +127,7 @@
         assertEquals(355, mView.getMeasuredHeight());;
     }
 
-    private class FakeImageFloatingTextView extends MessagingMessage {
+    private class FakeImageFloatingTextView extends MessagingTextMessage {
 
         public static final int LINE_HEIGHT = 50;
         private final int mNumLines;
diff --git a/core/tests/featureflagtests/OWNERS b/core/tests/featureflagtests/OWNERS
new file mode 100644
index 0000000..1a8fd2b
--- /dev/null
+++ b/core/tests/featureflagtests/OWNERS
@@ -0,0 +1,2 @@
+sbasi@google.com
+zhfan@google.com
\ No newline at end of file
diff --git a/core/tests/hosttests/test-apps/SharedUid/32/jni/Android.mk b/core/tests/hosttests/test-apps/SharedUid/32/jni/Android.mk
index 994131a..9b9e811 100644
--- a/core/tests/hosttests/test-apps/SharedUid/32/jni/Android.mk
+++ b/core/tests/hosttests/test-apps/SharedUid/32/jni/Android.mk
@@ -29,13 +29,10 @@
 LOCAL_SRC_FILES:= \
   native.cpp
 
-# All of the shard libraries we link against.
-LOCAL_SHARED_LIBRARIES := liblog
+LOCAL_LDLIBS := -llog
 
 LOCAL_CFLAGS += -Wall -Wextra -Werror
 
-# Also need the JNI headers.
-LOCAL_C_INCLUDES += \
-	$(JNI_H_INCLUDE)
+LOCAL_SDK_VERSION := current
 
 include $(BUILD_SHARED_LIBRARY)
diff --git a/core/tests/hosttests/test-apps/SharedUid/32/jni/native.cpp b/core/tests/hosttests/test-apps/SharedUid/32/jni/native.cpp
index 99cf587..fe32454 100644
--- a/core/tests/hosttests/test-apps/SharedUid/32/jni/native.cpp
+++ b/core/tests/hosttests/test-apps/SharedUid/32/jni/native.cpp
@@ -15,12 +15,15 @@
  */
 
 #define LOG_TAG "pmtest32 native.cpp"
-#include <utils/Log.h>
+#include <android/log.h>
 
 #include <stdio.h>
 
 #include "jni.h"
 
+#define ALOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
+#define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
+
 static jint
 add(JNIEnv */* env */, jobject /* thiz */, jint a, jint b) {
 int result = a + b;
diff --git a/core/tests/hosttests/test-apps/SharedUid/64/jni/Android.mk b/core/tests/hosttests/test-apps/SharedUid/64/jni/Android.mk
index 6c2679b..600a5d1 100644
--- a/core/tests/hosttests/test-apps/SharedUid/64/jni/Android.mk
+++ b/core/tests/hosttests/test-apps/SharedUid/64/jni/Android.mk
@@ -30,14 +30,10 @@
 LOCAL_SRC_FILES:= \
   native.cpp
 
-# All of the shared libraries we link against.
-LOCAL_SHARED_LIBRARIES := \
-	libutils liblog
+LOCAL_LDLIBS := -llog
 
 LOCAL_CFLAGS += -Wall -Wextra -Werror
 
-# Also need the JNI headers.
-LOCAL_C_INCLUDES += \
-	$(JNI_H_INCLUDE)
+LOCAL_SDK_VERSION := current
 
 include $(BUILD_SHARED_LIBRARY)
diff --git a/core/tests/hosttests/test-apps/SharedUid/64/jni/native.cpp b/core/tests/hosttests/test-apps/SharedUid/64/jni/native.cpp
index 0b6d750..ad9e746 100644
--- a/core/tests/hosttests/test-apps/SharedUid/64/jni/native.cpp
+++ b/core/tests/hosttests/test-apps/SharedUid/64/jni/native.cpp
@@ -15,12 +15,15 @@
  */
 
 #define LOG_TAG "pmtest64 native.cpp"
-#include <utils/Log.h>
+#include <android/log.h>
 
 #include <stdio.h>
 
 #include "jni.h"
 
+#define ALOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
+#define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
+
 static jint
 add(JNIEnv */* env */, jobject /* thiz */, jint a, jint b) {
 int result = a + b;
diff --git a/core/tests/hosttests/test-apps/SharedUid/dual/jni/Android.mk b/core/tests/hosttests/test-apps/SharedUid/dual/jni/Android.mk
index d668f29..8e9ac6b 100644
--- a/core/tests/hosttests/test-apps/SharedUid/dual/jni/Android.mk
+++ b/core/tests/hosttests/test-apps/SharedUid/dual/jni/Android.mk
@@ -29,14 +29,10 @@
 LOCAL_SRC_FILES:= \
   native.cpp
 
-# All of the shard libraries we link against.
 LOCAL_LDLIBS = -llog
-LOCAL_SHARED_LIBRARIES := liblog
 
 LOCAL_CFLAGS += -Wall -Wextra -Werror
 
-# Also need the JNI headers.
-LOCAL_C_INCLUDES += \
-	$(JNI_H_INCLUDE)
+LOCAL_SDK_VERSION := current
 
 include $(BUILD_SHARED_LIBRARY)
diff --git a/core/tests/hosttests/test-apps/SharedUid/dual/jni/native.cpp b/core/tests/hosttests/test-apps/SharedUid/dual/jni/native.cpp
index 3947e21..5c5088f 100644
--- a/core/tests/hosttests/test-apps/SharedUid/dual/jni/native.cpp
+++ b/core/tests/hosttests/test-apps/SharedUid/dual/jni/native.cpp
@@ -15,12 +15,15 @@
  */
 
 #define LOG_TAG "pmtestdual native.cpp"
-#include <utils/Log.h>
+#include <android/log.h>
 
 #include <stdio.h>
 
 #include "jni.h"
 
+#define ALOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
+#define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
+
 static jint
 add(JNIEnv */* env */, jobject /* thiz */, jint a, jint b) {
 int result = a + b;
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/data/keyboards/Generic.kcm b/data/keyboards/Generic.kcm
index 1ef74ba..d0565ca 100644
--- a/data/keyboards/Generic.kcm
+++ b/data/keyboards/Generic.kcm
@@ -472,11 +472,15 @@
 ### Non-printing keys ###
 
 key ESCAPE {
-    base:                               fallback BACK
+    base:                               none
     alt, meta:                          fallback HOME
     ctrl:                               fallback MENU
 }
 
+key DEL {
+    ctrl+alt:                           fallback BACK
+}
+
 ### Gamepad buttons ###
 
 key BUTTON_A {
diff --git a/data/keyboards/Virtual.kcm b/data/keyboards/Virtual.kcm
index c4647e0..c763cc09 100644
--- a/data/keyboards/Virtual.kcm
+++ b/data/keyboards/Virtual.kcm
@@ -469,11 +469,15 @@
 ### Non-printing keys ###
 
 key ESCAPE {
-    base:                               fallback BACK
+    base:                               none
     alt, meta:                          fallback HOME
     ctrl:                               fallback MENU
 }
 
+key DEL {
+    ctrl+alt:                           fallback BACK
+}
+
 ### Gamepad buttons ###
 
 key BUTTON_A {
diff --git a/docs/html/reference/images/text/style/typefacespan.png b/docs/html/reference/images/text/style/typefacespan.png
index 67e2cf9..1651c39 100644
--- a/docs/html/reference/images/text/style/typefacespan.png
+++ b/docs/html/reference/images/text/style/typefacespan.png
Binary files differ
diff --git a/graphics/java/android/graphics/BaseCanvas.java b/graphics/java/android/graphics/BaseCanvas.java
index 69a5874..eacb727 100644
--- a/graphics/java/android/graphics/BaseCanvas.java
+++ b/graphics/java/android/graphics/BaseCanvas.java
@@ -22,7 +22,6 @@
 import android.annotation.Size;
 import android.graphics.Canvas.VertexMode;
 import android.text.GraphicsOperations;
-import android.text.MeasuredParagraph;
 import android.text.MeasuredText;
 import android.text.SpannableString;
 import android.text.SpannedString;
diff --git a/graphics/java/android/graphics/BitmapFactory.java b/graphics/java/android/graphics/BitmapFactory.java
index f5bf754..7ea35e7 100644
--- a/graphics/java/android/graphics/BitmapFactory.java
+++ b/graphics/java/android/graphics/BitmapFactory.java
@@ -18,6 +18,8 @@
 
 import static android.graphics.BitmapFactory.Options.validate;
 
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.content.res.AssetManager;
 import android.content.res.Resources;
 import android.os.Trace;
@@ -518,8 +520,9 @@
      *         is not {@link ColorSpace.Model#RGB RGB}, or if the specified color space's transfer
      *         function is not an {@link ColorSpace.Rgb.TransferParameters ICC parametric curve}
      */
-    public static Bitmap decodeResourceStream(Resources res, TypedValue value,
-            InputStream is, Rect pad, Options opts) {
+    @Nullable
+    public static Bitmap decodeResourceStream(@Nullable Resources res, @Nullable TypedValue value,
+            @Nullable InputStream is, @Nullable Rect pad, @Nullable Options opts) {
         validate(opts);
         if (opts == null) {
             opts = new Options();
@@ -707,7 +710,9 @@
      * <code>is.mark(1024)</code> would be called. As of
      * {@link android.os.Build.VERSION_CODES#KITKAT}, this is no longer the case.</p>
      */
-    public static Bitmap decodeStream(InputStream is, Rect outPadding, Options opts) {
+    @Nullable
+    public static Bitmap decodeStream(@Nullable InputStream is, @Nullable Rect outPadding,
+            @Nullable Options opts) {
         // we don't throw in this case, thus allowing the caller to only check
         // the cache, and not force the image to be decoded.
         if (is == null) {
@@ -742,7 +747,8 @@
      * Private helper function for decoding an InputStream natively. Buffers the input enough to
      * do a rewind as needed, and supplies temporary storage if necessary. is MUST NOT be null.
      */
-    private static Bitmap decodeStreamInternal(InputStream is, Rect outPadding, Options opts) {
+    private static Bitmap decodeStreamInternal(@NonNull InputStream is,
+            @Nullable Rect outPadding, @Nullable Options opts) {
         // ASSERT(is != null);
         byte [] tempStorage = null;
         if (opts != null) tempStorage = opts.inTempStorage;
diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java
index f5e8633..d925441 100644
--- a/graphics/java/android/graphics/Canvas.java
+++ b/graphics/java/android/graphics/Canvas.java
@@ -1219,10 +1219,14 @@
         nFreeTextLayoutCaches();
     }
 
+    /** @hide */
+    public static void setCompatibilityVersion(int apiLevel) { nSetCompatibilityVersion(apiLevel); }
+
     private static native void nFreeCaches();
     private static native void nFreeTextLayoutCaches();
     private static native long nInitRaster(Bitmap bitmap);
     private static native long nGetNativeFinalizer();
+    private static native void nSetCompatibilityVersion(int apiLevel);
 
     // ---------------- @FastNative -------------------
 
diff --git a/graphics/java/android/graphics/FontFamily.java b/graphics/java/android/graphics/FontFamily.java
index fe2b523..e7cfcfd 100644
--- a/graphics/java/android/graphics/FontFamily.java
+++ b/graphics/java/android/graphics/FontFamily.java
@@ -19,9 +19,9 @@
 import android.annotation.Nullable;
 import android.content.res.AssetManager;
 import android.graphics.fonts.FontVariationAxis;
-import android.text.FontConfig;
 import android.text.TextUtils;
 import android.util.Log;
+
 import dalvik.annotation.optimization.CriticalNative;
 
 import java.io.FileInputStream;
diff --git a/graphics/java/android/graphics/FontListParser.java b/graphics/java/android/graphics/FontListParser.java
index 9f672e3..431d0e0 100644
--- a/graphics/java/android/graphics/FontListParser.java
+++ b/graphics/java/android/graphics/FontListParser.java
@@ -16,16 +16,13 @@
 
 package android.graphics;
 
-import android.text.FontConfig;
 import android.graphics.fonts.FontVariationAxis;
+import android.text.FontConfig;
 import android.util.Xml;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
-import android.annotation.Nullable;
-import com.android.internal.annotations.VisibleForTesting;
-
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.ArrayList;
diff --git a/graphics/java/android/graphics/ImageDecoder.java b/graphics/java/android/graphics/ImageDecoder.java
index acefead..3cca47b 100644
--- a/graphics/java/android/graphics/ImageDecoder.java
+++ b/graphics/java/android/graphics/ImageDecoder.java
@@ -25,7 +25,7 @@
 import android.annotation.RawRes;
 import android.content.ContentResolver;
 import android.content.res.AssetFileDescriptor;
-import android.content.res.AssetManager;
+import android.content.res.AssetManager.AssetInputStream;
 import android.content.res.Resources;
 import android.graphics.drawable.AnimatedImageDrawable;
 import android.graphics.drawable.Drawable;
@@ -263,6 +263,63 @@
         }
     }
 
+    /**
+     * Takes ownership of the AssetInputStream.
+     *
+     * @hide
+     */
+    public static class AssetInputStreamSource extends Source {
+        public AssetInputStreamSource(@NonNull AssetInputStream ais,
+                @NonNull Resources res, @NonNull TypedValue value) {
+            mAssetInputStream = ais;
+            mResources = res;
+
+            if (value.density == TypedValue.DENSITY_DEFAULT) {
+                mDensity = DisplayMetrics.DENSITY_DEFAULT;
+            } else if (value.density != TypedValue.DENSITY_NONE) {
+                mDensity = value.density;
+            } else {
+                mDensity = Bitmap.DENSITY_NONE;
+            }
+        }
+
+        private AssetInputStream mAssetInputStream;
+        private final Resources  mResources;
+        private final int        mDensity;
+
+        @Override
+        public Resources getResources() { return mResources; }
+
+        @Override
+        public int getDensity() {
+            return mDensity;
+        }
+
+        @Override
+        public ImageDecoder createImageDecoder() throws IOException {
+            ImageDecoder decoder = null;
+            synchronized (this) {
+                if (mAssetInputStream == null) {
+                    throw new IOException("Cannot reuse AssetInputStreamSource");
+                }
+                AssetInputStream ais = mAssetInputStream;
+                mAssetInputStream = null;
+                try {
+                    long asset = ais.getNativeAsset();
+                    decoder = nCreate(asset);
+                } finally {
+                    if (decoder == null) {
+                        IoUtils.closeQuietly(ais);
+                    } else {
+                        decoder.mInputStream = ais;
+                        decoder.mOwnsInputStream = true;
+                    }
+                }
+                return decoder;
+            }
+        }
+    }
+
     private static class ResourceSource extends Source {
         ResourceSource(@NonNull Resources res, int resId) {
             mResources = res;
@@ -296,11 +353,7 @@
                     mResDensity = value.density;
                 }
 
-                if (!(is instanceof AssetManager.AssetInputStream)) {
-                    // This should never happen.
-                    throw new RuntimeException("Resource is not an asset?");
-                }
-                long asset = ((AssetManager.AssetInputStream) is).getNativeAsset();
+                long asset = ((AssetInputStream) is).getNativeAsset();
                 decoder = nCreate(asset);
             } finally {
                 if (decoder == null) {
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index 5a80ee2..ed147e9 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -19,10 +19,8 @@
 import android.annotation.ColorInt;
 import android.annotation.NonNull;
 import android.annotation.Size;
-import android.graphics.FontListParser;
 import android.graphics.fonts.FontVariationAxis;
 import android.os.LocaleList;
-import android.text.FontConfig;
 import android.text.GraphicsOperations;
 import android.text.SpannableString;
 import android.text.SpannedString;
@@ -33,14 +31,13 @@
 import dalvik.annotation.optimization.CriticalNative;
 import dalvik.annotation.optimization.FastNative;
 
+import libcore.util.NativeAllocationRegistry;
+
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Locale;
 
-import libcore.util.NativeAllocationRegistry;
-
 /**
  * The Paint class holds the style and color information about how to draw
  * geometries, text and bitmaps.
diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java
index f41267e..8595165 100644
--- a/graphics/java/android/graphics/Typeface.java
+++ b/graphics/java/android/graphics/Typeface.java
@@ -16,25 +16,17 @@
 
 package android.graphics;
 
-import static android.content.res.FontResourcesParser.ProviderResourceEntry;
-import static android.content.res.FontResourcesParser.FontFileResourceEntry;
-import static android.content.res.FontResourcesParser.FontFamilyFilesResourceEntry;
 import static android.content.res.FontResourcesParser.FamilyResourceEntry;
+import static android.content.res.FontResourcesParser.FontFamilyFilesResourceEntry;
+import static android.content.res.FontResourcesParser.FontFileResourceEntry;
+import static android.content.res.FontResourcesParser.ProviderResourceEntry;
 
-import static java.lang.annotation.RetentionPolicy.SOURCE;
-
-import android.annotation.IntDef;
 import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.res.AssetManager;
-import android.graphics.FontListParser;
 import android.graphics.fonts.FontVariationAxis;
 import android.net.Uri;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.ParcelFileDescriptor;
-import android.os.ResultReceiver;
 import android.provider.FontRequest;
 import android.provider.FontsContract;
 import android.text.FontConfig;
@@ -49,8 +41,6 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.Preconditions;
 
-import libcore.io.IoUtils;
-
 import org.xmlpull.v1.XmlPullParserException;
 
 import java.io.File;
@@ -58,19 +48,15 @@
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.IOException;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
 import java.io.InputStream;
 import java.nio.ByteBuffer;
 import java.nio.channels.FileChannel;
-import java.util.Arrays;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.concurrent.atomic.AtomicReference;
 
 /**
  * The Typeface class specifies the typeface and intrinsic style of a font.
@@ -395,7 +381,7 @@
          * weight and italic information, so {@link #setWeight} and {@link #setItalic} are used
          * for style matching during font selection.
          *
-         * @param results The array of {@link FontsContract.FontInfo}
+         * @param fonts The array of {@link FontsContract.FontInfo}
          * @param buffers The mapping from URI to buffers to be used during building.
          * @hide
          */
@@ -879,14 +865,12 @@
      * also the font families in the fallback list.
      * @param fallbackName the family name. If given families don't support characters, the
      *               characters will be rendered with this family.
-     * @param weight the weight for this family. {@link RESOLVE_BY_FONT_TABLE} can be used. In that
-     *               case, the table information in the first family's font is used. If the first
-     *               family has multiple fonts, the closest to the regular weight and upright font
-     *               is used.
-     * @param italic the italic information for this family. {@link RESOLVE_BY_FONT_TABLE} can be
-     *               used. In that case, the table information in the first family's font is used.
-     *               If the first family has multiple fonts, the closest to the regular weight and
-     *               upright font is used.
+     * @param weight the weight for this family. In that case, the table information in the first
+     *               family's font is used. If the first family has multiple fonts, the closest to
+     *               the regular weight and upright font is used.
+     * @param italic the italic information for this family. In that case, the table information in
+     *               the first family's font is used. If the first family has multiple fonts, the
+     *               closest to the regular weight and upright font is used.
      * @param families array of font families
      */
     private static Typeface createFromFamiliesWithDefault(FontFamily[] families,
diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java
index 36a4d26..8af2fd8 100644
--- a/graphics/java/android/graphics/drawable/Drawable.java
+++ b/graphics/java/android/graphics/drawable/Drawable.java
@@ -1171,9 +1171,13 @@
     /**
      * Create a drawable from an inputstream, using the given resources and
      * value to determine density information.
+     *
+     * @deprecated Prefer the version without an Options object.
      */
-    public static Drawable createFromResourceStream(Resources res, TypedValue value,
-            InputStream is, String srcName, BitmapFactory.Options opts) {
+    @Nullable
+    public static Drawable createFromResourceStream(@Nullable Resources res,
+            @Nullable TypedValue value, @Nullable InputStream is, @Nullable String srcName,
+            @Nullable BitmapFactory.Options opts) {
         if (is == null) {
             return null;
         }
@@ -1197,7 +1201,6 @@
         // 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) {
diff --git a/graphics/java/android/graphics/drawable/GradientDrawable.java b/graphics/java/android/graphics/drawable/GradientDrawable.java
index f5a6f49..8b5114c 100644
--- a/graphics/java/android/graphics/drawable/GradientDrawable.java
+++ b/graphics/java/android/graphics/drawable/GradientDrawable.java
@@ -825,6 +825,14 @@
         mFillPaint.setXfermode(mode);
     }
 
+    /**
+     * @param aa to draw this drawable with
+     * @hide
+     */
+    public void setAntiAlias(boolean aa) {
+        mFillPaint.setAntiAlias(aa);
+    }
+
     private void buildPathIfDirty() {
         final GradientState st = mGradientState;
         if (mPathIsDirty) {
diff --git a/graphics/java/android/graphics/drawable/NinePatchDrawable.java b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
index a56e8d1..66f2a31 100644
--- a/graphics/java/android/graphics/drawable/NinePatchDrawable.java
+++ b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
@@ -667,8 +667,9 @@
             return;
         }
 
-        final int sourceDensity = ninePatch.getDensity();
         final int targetDensity = mTargetDensity;
+        final int sourceDensity = ninePatch.getDensity() == Bitmap.DENSITY_NONE ?
+            targetDensity : ninePatch.getDensity();
 
         final Insets sourceOpticalInsets = mNinePatchState.mOpticalInsets;
         if (sourceOpticalInsets != Insets.NONE) {
diff --git a/graphics/java/android/graphics/drawable/RippleBackground.java b/graphics/java/android/graphics/drawable/RippleBackground.java
index 41d3698..2812abe 100644
--- a/graphics/java/android/graphics/drawable/RippleBackground.java
+++ b/graphics/java/android/graphics/drawable/RippleBackground.java
@@ -78,9 +78,10 @@
     }
 
     private void onStateChanged() {
-        float newOpacity = 0.0f;
-        if (mHovered) newOpacity += .25f;
-        if (mFocused) newOpacity += .75f;
+        // Hover             = .2 * alpha
+        // Focus             = .6 * alpha
+        // Focused + Hovered = .6 * alpha
+        float newOpacity = mFocused ? .6f : mHovered ? .2f : 0f;
         if (mAnimator != null) {
             mAnimator.cancel();
             mAnimator = null;
diff --git a/graphics/java/android/graphics/drawable/RippleForeground.java b/graphics/java/android/graphics/drawable/RippleForeground.java
index 4129868..a8dc34a 100644
--- a/graphics/java/android/graphics/drawable/RippleForeground.java
+++ b/graphics/java/android/graphics/drawable/RippleForeground.java
@@ -110,6 +110,7 @@
 
         // Take 60% of the maximum of the width and height, then divided half to get the radius.
         mStartRadius = Math.max(bounds.width(), bounds.height()) * 0.3f;
+        clampStartingPosition();
     }
 
     @Override
@@ -350,7 +351,7 @@
         final float cY = mBounds.exactCenterY();
         final float dX = mStartingX - cX;
         final float dY = mStartingY - cY;
-        final float r = mTargetRadius;
+        final float r = mTargetRadius - mStartRadius;
         if (dX * dX + dY * dY > r * r) {
             // Point is outside the circle, clamp to the perimeter.
             final double angle = Math.atan2(dY, dX);
diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java
index ded427e..e2aba04 100644
--- a/keystore/java/android/security/KeyStore.java
+++ b/keystore/java/android/security/KeyStore.java
@@ -545,7 +545,9 @@
         try {
             args = args != null ? args : new KeymasterArguments();
             entropy = entropy != null ? entropy : new byte[0];
-            return mBinder.begin(getToken(), alias, purpose, pruneable, args, entropy, uid);
+            OperationResult res = mBinder.begin(getToken(), alias, purpose, pruneable, args, entropy, uid);
+            // This result is -26 (KEY_USER_NOT_AUTHENTICATED) but why??
+            return res;
         } catch (RemoteException e) {
             Log.w(TAG, "Cannot connect to keystore", e);
             return null;
@@ -563,7 +565,8 @@
         try {
             arguments = arguments != null ? arguments : new KeymasterArguments();
             input = input != null ? input : new byte[0];
-            return mBinder.update(token, arguments, input);
+            OperationResult res = mBinder.update(token, arguments, input);
+            return res;
         } catch (RemoteException e) {
             Log.w(TAG, "Cannot connect to keystore", e);
             return null;
@@ -618,9 +621,9 @@
      * @return {@code KeyStore.NO_ERROR} on success, otherwise an error value corresponding to
      * a {@code KeymasterDefs.KM_ERROR_} value or {@code KeyStore} ResponseCode.
      */
-    public int addAuthToken(byte[] authToken) {
+    public int addAuthToken(byte[] authToken, int userId) {
         try {
-            return mBinder.addAuthToken(authToken);
+            return mBinder.addAuthToken(authToken, userId);
         } catch (RemoteException e) {
             Log.w(TAG, "Cannot connect to keystore", e);
             return SYSTEM_ERROR;
@@ -832,14 +835,14 @@
     public InvalidKeyException getInvalidKeyException(
             String keystoreKeyAlias, int uid, KeyStoreException e) {
         switch (e.getErrorCode()) {
-            case LOCKED:
+            case LOCKED: // 2
                 return new UserNotAuthenticatedException();
-            case KeymasterDefs.KM_ERROR_KEY_EXPIRED:
+            case KeymasterDefs.KM_ERROR_KEY_EXPIRED: // -25
                 return new KeyExpiredException();
-            case KeymasterDefs.KM_ERROR_KEY_NOT_YET_VALID:
+            case KeymasterDefs.KM_ERROR_KEY_NOT_YET_VALID: // -2
                 return new KeyNotYetValidException();
-            case KeymasterDefs.KM_ERROR_KEY_USER_NOT_AUTHENTICATED:
-            case OP_AUTH_NEEDED:
+            case KeymasterDefs.KM_ERROR_KEY_USER_NOT_AUTHENTICATED: // -26
+            case OP_AUTH_NEEDED: // 15
             {
                 // We now need to determine whether the key/operation can become usable if user
                 // authentication is performed, or whether it can never become usable again.
@@ -879,7 +882,7 @@
                 // None of the key's SIDs can ever be authenticated
                 return new KeyPermanentlyInvalidatedException();
             }
-            case UNINITIALIZED:
+            case UNINITIALIZED: // 3
                 return new KeyPermanentlyInvalidatedException();
             default:
                 return new InvalidKeyException("Keystore operation failed", e);
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java
index 09b3b9b..419eb24 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java
@@ -243,13 +243,7 @@
                 // Check that user authentication related parameters are acceptable. This method
                 // will throw an IllegalStateException if there are issues (e.g., secure lock screen
                 // not set up).
-                KeymasterUtils.addUserAuthArgs(new KeymasterArguments(),
-                        spec.isUserAuthenticationRequired(),
-                        spec.getUserAuthenticationValidityDurationSeconds(),
-                        spec.isUserAuthenticationValidWhileOnBody(),
-                        spec.isInvalidatedByBiometricEnrollment(),
-                        GateKeeper.INVALID_SECURE_USER_ID /* boundToSpecificSecureUserId */,
-                        spec.isUserConfirmationRequired());
+                KeymasterUtils.addUserAuthArgs(new KeymasterArguments(), spec);
             } catch (IllegalStateException | IllegalArgumentException e) {
                 throw new InvalidAlgorithmParameterException(e);
             }
@@ -285,16 +279,7 @@
         args.addEnums(KeymasterDefs.KM_TAG_BLOCK_MODE, mKeymasterBlockModes);
         args.addEnums(KeymasterDefs.KM_TAG_PADDING, mKeymasterPaddings);
         args.addEnums(KeymasterDefs.KM_TAG_DIGEST, mKeymasterDigests);
-        KeymasterUtils.addUserAuthArgs(args,
-                spec.isUserAuthenticationRequired(),
-                spec.getUserAuthenticationValidityDurationSeconds(),
-                spec.isUserAuthenticationValidWhileOnBody(),
-                spec.isInvalidatedByBiometricEnrollment(),
-                GateKeeper.INVALID_SECURE_USER_ID /* boundToSpecificSecureUserId */,
-                spec.isUserConfirmationRequired());
-        if (spec.isTrustedUserPresenceRequired()) {
-            args.addBoolean(KeymasterDefs.KM_TAG_TRUSTED_USER_PRESENCE_REQUIRED);
-        }
+        KeymasterUtils.addUserAuthArgs(args, spec);
         KeymasterUtils.addMinMacLengthAuthorizationIfNecessary(
                 args,
                 mKeymasterAlgorithm,
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java
index e33e3cd..d68a33d 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java
@@ -344,13 +344,7 @@
                 // Check that user authentication related parameters are acceptable. This method
                 // will throw an IllegalStateException if there are issues (e.g., secure lock screen
                 // not set up).
-                KeymasterUtils.addUserAuthArgs(new KeymasterArguments(),
-                        mSpec.isUserAuthenticationRequired(),
-                        mSpec.getUserAuthenticationValidityDurationSeconds(),
-                        mSpec.isUserAuthenticationValidWhileOnBody(),
-                        mSpec.isInvalidatedByBiometricEnrollment(),
-                        GateKeeper.INVALID_SECURE_USER_ID /* boundToSpecificSecureUserId */,
-                        mSpec.isUserConfirmationRequired());
+                KeymasterUtils.addUserAuthArgs(new KeymasterArguments(), mSpec);
             } catch (IllegalArgumentException | IllegalStateException e) {
                 throw new InvalidAlgorithmParameterException(e);
             }
@@ -541,13 +535,7 @@
         args.addEnums(KeymasterDefs.KM_TAG_PADDING, mKeymasterSignaturePaddings);
         args.addEnums(KeymasterDefs.KM_TAG_DIGEST, mKeymasterDigests);
 
-        KeymasterUtils.addUserAuthArgs(args,
-                mSpec.isUserAuthenticationRequired(),
-                mSpec.getUserAuthenticationValidityDurationSeconds(),
-                mSpec.isUserAuthenticationValidWhileOnBody(),
-                mSpec.isInvalidatedByBiometricEnrollment(),
-                GateKeeper.INVALID_SECURE_USER_ID /* boundToSpecificSecureUserId */,
-                mSpec.isUserConfirmationRequired());
+        KeymasterUtils.addUserAuthArgs(args, mSpec);
         args.addDateIfNotNull(KeymasterDefs.KM_TAG_ACTIVE_DATETIME, mSpec.getKeyValidityStart());
         args.addDateIfNotNull(KeymasterDefs.KM_TAG_ORIGINATION_EXPIRE_DATETIME,
                 mSpec.getKeyValidityForOriginationEnd());
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java
index 05cc74a..fc86ca0 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java
@@ -497,13 +497,7 @@
                 importArgs.addEnums(KeymasterDefs.KM_TAG_PADDING, keymasterEncryptionPaddings);
                 importArgs.addEnums(KeymasterDefs.KM_TAG_PADDING,
                         KeyProperties.SignaturePadding.allToKeymaster(spec.getSignaturePaddings()));
-                KeymasterUtils.addUserAuthArgs(importArgs,
-                        spec.isUserAuthenticationRequired(),
-                        spec.getUserAuthenticationValidityDurationSeconds(),
-                        spec.isUserAuthenticationValidWhileOnBody(),
-                        spec.isInvalidatedByBiometricEnrollment(),
-                        spec.getBoundToSpecificSecureUserId(),
-                        spec.isUserConfirmationRequired());
+                KeymasterUtils.addUserAuthArgs(importArgs, spec);
                 importArgs.addDateIfNotNull(KeymasterDefs.KM_TAG_ACTIVE_DATETIME,
                         spec.getKeyValidityStart());
                 importArgs.addDateIfNotNull(KeymasterDefs.KM_TAG_ORIGINATION_EXPIRE_DATETIME,
@@ -700,13 +694,7 @@
             int[] keymasterPaddings = KeyProperties.EncryptionPadding.allToKeymaster(
                     params.getEncryptionPaddings());
             args.addEnums(KeymasterDefs.KM_TAG_PADDING, keymasterPaddings);
-            KeymasterUtils.addUserAuthArgs(args,
-                    params.isUserAuthenticationRequired(),
-                    params.getUserAuthenticationValidityDurationSeconds(),
-                    params.isUserAuthenticationValidWhileOnBody(),
-                    params.isInvalidatedByBiometricEnrollment(),
-                    params.getBoundToSpecificSecureUserId(),
-                    params.isUserConfirmationRequired());
+            KeymasterUtils.addUserAuthArgs(args, params);
             KeymasterUtils.addMinMacLengthAuthorizationIfNecessary(
                     args,
                     keymasterAlgorithm,
diff --git a/keystore/java/android/security/keystore/KeyGenParameterSpec.java b/keystore/java/android/security/keystore/KeyGenParameterSpec.java
index da23c70..d0814c6 100644
--- a/keystore/java/android/security/keystore/KeyGenParameterSpec.java
+++ b/keystore/java/android/security/keystore/KeyGenParameterSpec.java
@@ -21,6 +21,7 @@
 import android.annotation.Nullable;
 import android.app.KeyguardManager;
 import android.hardware.fingerprint.FingerprintManager;
+import android.security.GateKeeper;
 import android.security.KeyStore;
 import android.text.TextUtils;
 
@@ -232,7 +233,7 @@
  * key = (SecretKey) keyStore.getKey("key2", null);
  * }</pre>
  */
-public final class KeyGenParameterSpec implements AlgorithmParameterSpec {
+public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAuthArgs {
 
     private static final X500Principal DEFAULT_CERT_SUBJECT = new X500Principal("CN=fake");
     private static final BigInteger DEFAULT_CERT_SERIAL_NUMBER = new BigInteger("1");
@@ -265,6 +266,7 @@
     private final boolean mInvalidatedByBiometricEnrollment;
     private final boolean mIsStrongBoxBacked;
     private final boolean mUserConfirmationRequired;
+    private final boolean mUnlockedDeviceRequired;
 
     /**
      * @hide should be built with Builder
@@ -295,7 +297,8 @@
             boolean userAuthenticationValidWhileOnBody,
             boolean invalidatedByBiometricEnrollment,
             boolean isStrongBoxBacked,
-            boolean userConfirmationRequired) {
+            boolean userConfirmationRequired,
+            boolean unlockedDeviceRequired) {
         if (TextUtils.isEmpty(keyStoreAlias)) {
             throw new IllegalArgumentException("keyStoreAlias must not be empty");
         }
@@ -344,6 +347,7 @@
         mInvalidatedByBiometricEnrollment = invalidatedByBiometricEnrollment;
         mIsStrongBoxBacked = isStrongBoxBacked;
         mUserConfirmationRequired = userConfirmationRequired;
+        mUnlockedDeviceRequired = unlockedDeviceRequired;
     }
 
     /**
@@ -669,6 +673,22 @@
     }
 
     /**
+     * Returns {@code true} if the key cannot be used unless the device screen is unlocked.
+     *
+     * @see Builder#SetUnlockedDeviceRequired(boolean)
+     */
+    public boolean isUnlockedDeviceRequired() {
+        return mUnlockedDeviceRequired;
+    }
+
+    /**
+     * @hide
+     */
+    public long getBoundToSpecificSecureUserId() {
+        return GateKeeper.INVALID_SECURE_USER_ID;
+    }
+
+    /**
      * Builder of {@link KeyGenParameterSpec} instances.
      */
     public final static class Builder {
@@ -699,6 +719,7 @@
         private boolean mInvalidatedByBiometricEnrollment = true;
         private boolean mIsStrongBoxBacked = false;
         private boolean mUserConfirmationRequired;
+        private boolean mUnlockedDeviceRequired = false;
 
         /**
          * Creates a new instance of the {@code Builder}.
@@ -1267,6 +1288,18 @@
         }
 
         /**
+         * Sets whether the keystore requires the screen to be unlocked before allowing decryption
+         * using this key. If this is set to {@code true}, any attempt to decrypt using this key
+         * while the screen is locked will fail. A locked device requires a PIN, password,
+         * fingerprint, or other trusted factor to access.
+         */
+        @NonNull
+        public Builder setUnlockedDeviceRequired(boolean unlockedDeviceRequired) {
+            mUnlockedDeviceRequired = unlockedDeviceRequired;
+            return this;
+        }
+
+        /**
          * Builds an instance of {@code KeyGenParameterSpec}.
          */
         @NonNull
@@ -1297,7 +1330,8 @@
                     mUserAuthenticationValidWhileOnBody,
                     mInvalidatedByBiometricEnrollment,
                     mIsStrongBoxBacked,
-                    mUserConfirmationRequired);
+                    mUserConfirmationRequired,
+                    mUnlockedDeviceRequired);
         }
     }
 }
diff --git a/keystore/java/android/security/keystore/KeyProtection.java b/keystore/java/android/security/keystore/KeyProtection.java
index b5b3281..7f8259b 100644
--- a/keystore/java/android/security/keystore/KeyProtection.java
+++ b/keystore/java/android/security/keystore/KeyProtection.java
@@ -212,7 +212,7 @@
  * ...
  * }</pre>
  */
-public final class KeyProtection implements ProtectionParameter {
+public final class KeyProtection implements ProtectionParameter, UserAuthArgs {
     private final Date mKeyValidityStart;
     private final Date mKeyValidityForOriginationEnd;
     private final Date mKeyValidityForConsumptionEnd;
@@ -229,6 +229,8 @@
     private final long mBoundToSecureUserId;
     private final boolean mCriticalToDeviceEncryption;
     private final boolean mUserConfirmationRequired;
+    private final boolean mTrustedUserPresenceRequired;
+    private final boolean mUnlockedDeviceRequired;
 
     private KeyProtection(
             Date keyValidityStart,
@@ -242,11 +244,13 @@
             boolean randomizedEncryptionRequired,
             boolean userAuthenticationRequired,
             int userAuthenticationValidityDurationSeconds,
+            boolean trustedUserPresenceRequired,
             boolean userAuthenticationValidWhileOnBody,
             boolean invalidatedByBiometricEnrollment,
             long boundToSecureUserId,
             boolean criticalToDeviceEncryption,
-            boolean userConfirmationRequired) {
+            boolean userConfirmationRequired,
+            boolean unlockedDeviceRequired) {
         mKeyValidityStart = Utils.cloneIfNotNull(keyValidityStart);
         mKeyValidityForOriginationEnd = Utils.cloneIfNotNull(keyValidityForOriginationEnd);
         mKeyValidityForConsumptionEnd = Utils.cloneIfNotNull(keyValidityForConsumptionEnd);
@@ -265,6 +269,8 @@
         mBoundToSecureUserId = boundToSecureUserId;
         mCriticalToDeviceEncryption = criticalToDeviceEncryption;
         mUserConfirmationRequired = userConfirmationRequired;
+        mTrustedUserPresenceRequired = trustedUserPresenceRequired;
+        mUnlockedDeviceRequired = unlockedDeviceRequired;
     }
 
     /**
@@ -437,6 +443,14 @@
     }
 
     /**
+     * Returns {@code true} if the key is authorized to be used only if a test of user presence has
+     * been performed between the {@code Signature.initSign()} and {@code Signature.sign()} calls.
+     */
+    public boolean isTrustedUserPresenceRequired() {
+        return mTrustedUserPresenceRequired;
+    }
+
+    /**
      * Returns {@code true} if the key will be de-authorized when the device is removed from the
      * user's body.  This option has no effect on keys that don't have an authentication validity
      * duration, and has no effect if the device lacks an on-body sensor.
@@ -494,6 +508,15 @@
     }
 
     /**
+     * Returns {@code true} if the key cannot be used unless the device screen is unlocked.
+     *
+     * @see Builder#SetRequireDeviceUnlocked(boolean)
+     */
+    public boolean isUnlockedDeviceRequired() {
+        return mUnlockedDeviceRequired;
+    }
+
+    /**
      * Builder of {@link KeyProtection} instances.
      */
     public final static class Builder {
@@ -512,6 +535,9 @@
         private boolean mUserAuthenticationValidWhileOnBody;
         private boolean mInvalidatedByBiometricEnrollment = true;
         private boolean mUserConfirmationRequired;
+        private boolean mTrustedUserPresenceRequired = false;
+        private boolean mUnlockedDeviceRequired = false;
+
         private long mBoundToSecureUserId = GateKeeper.INVALID_SECURE_USER_ID;
         private boolean mCriticalToDeviceEncryption = false;
 
@@ -811,6 +837,16 @@
         }
 
         /**
+         * Sets whether a test of user presence is required to be performed between the
+         * {@code Signature.initSign()} and {@code Signature.sign()} method calls.
+         */
+        @NonNull
+        public Builder setTrustedUserPresenceRequired(boolean required) {
+            mTrustedUserPresenceRequired = required;
+            return this;
+        }
+
+        /**
          * Sets whether the key will remain authorized only until the device is removed from the
          * user's body up to the limit of the authentication validity period (see
          * {@link #setUserAuthenticationValidityDurationSeconds} and
@@ -892,6 +928,18 @@
         }
 
         /**
+         * Sets whether the keystore requires the screen to be unlocked before allowing decryption
+         * using this key. If this is set to {@code true}, any attempt to decrypt using this key
+         * while the screen is locked will fail. A locked device requires a PIN, password,
+         * fingerprint, or other trusted factor to access.
+         */
+        @NonNull
+        public Builder setUnlockedDeviceRequired(boolean unlockedDeviceRequired) {
+            mUnlockedDeviceRequired = unlockedDeviceRequired;
+            return this;
+        }
+
+        /**
          * Builds an instance of {@link KeyProtection}.
          *
          * @throws IllegalArgumentException if a required field is missing
@@ -910,11 +958,13 @@
                     mRandomizedEncryptionRequired,
                     mUserAuthenticationRequired,
                     mUserAuthenticationValidityDurationSeconds,
+                    mTrustedUserPresenceRequired,
                     mUserAuthenticationValidWhileOnBody,
                     mInvalidatedByBiometricEnrollment,
                     mBoundToSecureUserId,
                     mCriticalToDeviceEncryption,
-                    mUserConfirmationRequired);
+                    mUserConfirmationRequired,
+                    mUnlockedDeviceRequired);
         }
     }
 }
diff --git a/keystore/java/android/security/keystore/KeymasterUtils.java b/keystore/java/android/security/keystore/KeymasterUtils.java
index 4e28601..5bd0e74 100644
--- a/keystore/java/android/security/keystore/KeymasterUtils.java
+++ b/keystore/java/android/security/keystore/KeymasterUtils.java
@@ -18,6 +18,7 @@
 
 import android.util.Log;
 import android.hardware.fingerprint.FingerprintManager;
+import android.os.UserHandle;
 import android.security.GateKeeper;
 import android.security.KeyStore;
 import android.security.keymaster.KeymasterArguments;
@@ -101,22 +102,27 @@
      *         require user authentication.
      */
     public static void addUserAuthArgs(KeymasterArguments args,
-            boolean userAuthenticationRequired,
-            int userAuthenticationValidityDurationSeconds,
-            boolean userAuthenticationValidWhileOnBody,
-            boolean invalidatedByBiometricEnrollment,
-            long boundToSpecificSecureUserId,
-            boolean userConfirmationRequired) {
-        if (userConfirmationRequired) {
+            UserAuthArgs spec) {
+        if (spec.isTrustedUserPresenceRequired()) {
+            args.addBoolean(KeymasterDefs.KM_TAG_TRUSTED_USER_PRESENCE_REQUIRED);
+        }
+
+        if (spec.isUserConfirmationRequired()) {
             args.addBoolean(KeymasterDefs.KM_TAG_TRUSTED_CONFIRMATION_REQUIRED);
         }
 
-        if (!userAuthenticationRequired) {
+        if (spec.isUnlockedDeviceRequired()) {
+            args.addBoolean(KeymasterDefs.KM_TAG_UNLOCKED_DEVICE_REQUIRED);
+            // Once keymaster is properly ignoring this tag, it should be added to every auth list
+            args.addUnsignedInt(KeymasterDefs.KM_TAG_USER_ID, UserHandle.getCallingUserId());
+        }
+
+        if (!spec.isUserAuthenticationRequired()) {
             args.addBoolean(KeymasterDefs.KM_TAG_NO_AUTH_REQUIRED);
             return;
         }
 
-        if (userAuthenticationValidityDurationSeconds == -1) {
+        if (spec.getUserAuthenticationValidityDurationSeconds() == -1) {
             // Every use of this key needs to be authorized by the user. This currently means
             // fingerprint-only auth.
             FingerprintManager fingerprintManager =
@@ -132,9 +138,9 @@
             }
 
             long sid;
-            if (boundToSpecificSecureUserId != GateKeeper.INVALID_SECURE_USER_ID) {
-                sid = boundToSpecificSecureUserId;
-            } else if (invalidatedByBiometricEnrollment) {
+            if (spec.getBoundToSpecificSecureUserId() != GateKeeper.INVALID_SECURE_USER_ID) {
+                sid = spec.getBoundToSpecificSecureUserId();
+            } else if (spec.isInvalidatedByBiometricEnrollment()) {
                 // The fingerprint-only SID will change on fingerprint enrollment or removal of all,
                 // enrolled fingerprints, invalidating the key.
                 sid = fingerprintOnlySid;
@@ -147,14 +153,14 @@
             args.addUnsignedLong(
                     KeymasterDefs.KM_TAG_USER_SECURE_ID, KeymasterArguments.toUint64(sid));
             args.addEnum(KeymasterDefs.KM_TAG_USER_AUTH_TYPE, KeymasterDefs.HW_AUTH_FINGERPRINT);
-            if (userAuthenticationValidWhileOnBody) {
+            if (spec.isUserAuthenticationValidWhileOnBody()) {
                 throw new ProviderException("Key validity extension while device is on-body is not "
                         + "supported for keys requiring fingerprint authentication");
             }
         } else {
             long sid;
-            if (boundToSpecificSecureUserId != GateKeeper.INVALID_SECURE_USER_ID) {
-                sid = boundToSpecificSecureUserId;
+            if (spec.getBoundToSpecificSecureUserId() != GateKeeper.INVALID_SECURE_USER_ID) {
+                sid = spec.getBoundToSpecificSecureUserId();
             } else {
                 // The key is authorized for use for the specified amount of time after the user has
                 // authenticated. Whatever unlocks the secure lock screen should authorize this key.
@@ -165,8 +171,8 @@
             args.addEnum(KeymasterDefs.KM_TAG_USER_AUTH_TYPE,
                     KeymasterDefs.HW_AUTH_PASSWORD | KeymasterDefs.HW_AUTH_FINGERPRINT);
             args.addUnsignedInt(KeymasterDefs.KM_TAG_AUTH_TIMEOUT,
-                    userAuthenticationValidityDurationSeconds);
-            if (userAuthenticationValidWhileOnBody) {
+                    spec.getUserAuthenticationValidityDurationSeconds());
+            if (spec.isUserAuthenticationValidWhileOnBody()) {
                 args.addBoolean(KeymasterDefs.KM_TAG_ALLOW_WHILE_ON_BODY);
             }
         }
diff --git a/keystore/java/android/security/keystore/UserAuthArgs.java b/keystore/java/android/security/keystore/UserAuthArgs.java
new file mode 100644
index 0000000..3a7017e
--- /dev/null
+++ b/keystore/java/android/security/keystore/UserAuthArgs.java
@@ -0,0 +1,38 @@
+/*
+ * 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.security.keystore;
+
+/**
+ * @hide
+ *
+ * This is an interface to encapsulate the user authentication arguments that
+ * are passed to KeymasterUtils.addUserAuthArgs. Classes that represent
+ * authorization characteristics for new or imported keys can implement this
+ * interface to be passed to that method.
+ */
+public interface UserAuthArgs {
+
+    boolean isUserAuthenticationRequired();
+    int getUserAuthenticationValidityDurationSeconds();
+    boolean isUserAuthenticationValidWhileOnBody();
+    boolean isInvalidatedByBiometricEnrollment();
+    boolean isTrustedUserPresenceRequired();
+    boolean isUnlockedDeviceRequired();
+    boolean isUserConfirmationRequired();
+    long getBoundToSpecificSecureUserId();
+
+}
diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp
index b2edd33..2b0b22d 100644
--- a/libs/hwui/SkiaCanvas.cpp
+++ b/libs/hwui/SkiaCanvas.cpp
@@ -187,11 +187,6 @@
 static inline SkCanvas::SaveLayerFlags layerFlags(SaveFlags::Flags flags) {
     SkCanvas::SaveLayerFlags layerFlags = 0;
 
-    // We intentionally ignore the SaveFlags::HasAlphaLayer and
-    // SkCanvas::kIsOpaque_SaveLayerFlag flags because HWUI ignores it
-    // and our Android client may use it incorrectly.
-    // In Skia, this flag is purely for performance optimization.
-
     if (!(flags & SaveFlags::ClipToLayer)) {
         layerFlags |= SkCanvas::kDontClipToLayer_Legacy_SaveLayerFlag;
     }
@@ -747,6 +742,12 @@
     SkPaint paintCopy(paint);
     paintCopy.setTextAlign(SkPaint::kLeft_Align);
     SkASSERT(paintCopy.getTextEncoding() == SkPaint::kGlyphID_TextEncoding);
+    // Stroke with a hairline is drawn on HW with a fill style for compatibility with Android O and
+    // older.
+    if (!mCanvasOwned && sApiLevel <= 27 && paintCopy.getStrokeWidth() <= 0
+            && paintCopy.getStyle() == SkPaint::kStroke_Style) {
+        paintCopy.setStyle(SkPaint::kFill_Style);
+    }
 
     SkRect bounds =
             SkRect::MakeLTRB(boundsLeft + x, boundsTop + y, boundsRight + x, boundsBottom + y);
diff --git a/libs/hwui/SkiaCanvasProxy.cpp b/libs/hwui/SkiaCanvasProxy.cpp
index 06e2d6c..fc009d8 100644
--- a/libs/hwui/SkiaCanvasProxy.cpp
+++ b/libs/hwui/SkiaCanvasProxy.cpp
@@ -204,10 +204,6 @@
         saveFlags |= SaveFlags::ClipToLayer;
     }
 
-    if (!(layerFlags & SkCanvas::kIsOpaque_SaveLayerFlag)) {
-        saveFlags |= SaveFlags::HasAlphaLayer;
-    }
-
     return saveFlags;
 }
 
diff --git a/libs/hwui/VectorDrawable.cpp b/libs/hwui/VectorDrawable.cpp
index f118e8d..18358e2 100644
--- a/libs/hwui/VectorDrawable.cpp
+++ b/libs/hwui/VectorDrawable.cpp
@@ -518,10 +518,7 @@
             Bitmap& bitmap = getBitmapUpdateIfDirty();
             SkBitmap skiaBitmap;
             bitmap.getSkBitmap(&skiaBitmap);
-            if (!surface->getCanvas()->writePixels(skiaBitmap, dst.fLeft, dst.fTop)) {
-                ALOGD("VectorDrawable caching failed to efficiently upload");
-                surface->getCanvas()->drawBitmap(skiaBitmap, dst.fLeft, dst.fTop);
-            }
+            surface->writePixels(skiaBitmap, dst.fLeft, dst.fTop);
         }
         mCache.dirty = false;
     }
@@ -557,13 +554,12 @@
     mAtlasKey = INVALID_ATLAS_KEY;
 }
 
-void Tree::draw(SkCanvas* canvas) {
+void Tree::draw(SkCanvas* canvas, const SkRect& bounds) {
     SkRect src;
     sk_sp<SkSurface> vdSurface = mCache.getSurface(&src);
     if (vdSurface) {
         canvas->drawImageRect(vdSurface->makeImageSnapshot().get(), src,
-                              mutateProperties()->getBounds(), getPaint(),
-                              SkCanvas::kFast_SrcRectConstraint);
+                bounds, getPaint(), SkCanvas::kFast_SrcRectConstraint);
     } else {
         // Handle the case when VectorDrawableAtlas has been destroyed, because of memory pressure.
         // We render the VD into a temporary standalone buffer and mark the frame as dirty. Next
@@ -575,8 +571,7 @@
         int scaledWidth = SkScalarCeilToInt(mProperties.getScaledWidth());
         int scaledHeight = SkScalarCeilToInt(mProperties.getScaledHeight());
         canvas->drawBitmapRect(skiaBitmap, SkRect::MakeWH(scaledWidth, scaledHeight),
-                               mutateProperties()->getBounds(), getPaint(),
-                               SkCanvas::kFast_SrcRectConstraint);
+                bounds, getPaint(), SkCanvas::kFast_SrcRectConstraint);
         mCache.clear();
         markDirty();
     }
diff --git a/libs/hwui/VectorDrawable.h b/libs/hwui/VectorDrawable.h
index d9cf8ab..da52a95 100644
--- a/libs/hwui/VectorDrawable.h
+++ b/libs/hwui/VectorDrawable.h
@@ -644,7 +644,7 @@
      * Draws VD cache into a canvas. This should always be called from RT and it works with Skia
      * pipelines only.
      */
-    void draw(SkCanvas* canvas);
+    void draw(SkCanvas* canvas, const SkRect& bounds);
 
     /**
      * Draws VD into a GPU backed surface.
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/hwui/hwui/Bitmap.h b/libs/hwui/hwui/Bitmap.h
index a75276f..4f06656 100644
--- a/libs/hwui/hwui/Bitmap.h
+++ b/libs/hwui/hwui/Bitmap.h
@@ -66,7 +66,7 @@
     Bitmap(GraphicBuffer* buffer, const SkImageInfo& info);
 
     int rowBytesAsPixels() const {
-        return rowBytes() >> SkColorTypeShiftPerPixel(mInfo.colorType());
+        return rowBytes() >> mInfo.shiftPerPixel();
     }
 
     void reconfigure(const SkImageInfo& info, size_t rowBytes);
diff --git a/libs/hwui/hwui/Canvas.cpp b/libs/hwui/hwui/Canvas.cpp
index 284fd83..ad4c8be 100644
--- a/libs/hwui/hwui/Canvas.cpp
+++ b/libs/hwui/hwui/Canvas.cpp
@@ -225,4 +225,10 @@
     MinikinUtils::forFontRun(layout, &paintCopy, f);
 }
 
+int Canvas::sApiLevel = 1;
+
+void Canvas::setCompatibilityVersion(int apiLevel) {
+    sApiLevel = apiLevel;
+}
+
 }  // namespace android
diff --git a/libs/hwui/hwui/Canvas.h b/libs/hwui/hwui/Canvas.h
index 3ddf1c4..fabb8d2 100644
--- a/libs/hwui/hwui/Canvas.h
+++ b/libs/hwui/hwui/Canvas.h
@@ -116,6 +116,14 @@
     static Canvas* create_canvas(SkCanvas* skiaCanvas);
 
     /**
+     *  Sets the target SDK version used to build the app.
+     *
+     *  @param apiLevel API level
+     *
+     */
+    static void setCompatibilityVersion(int apiLevel);
+
+    /**
      *  Provides a Skia SkCanvas interface that acts as a proxy to this Canvas.
      *  It is useful for testing and clients (e.g. Picture/Movie) that expect to
      *  draw their contents into an SkCanvas.
@@ -282,6 +290,8 @@
     virtual void drawLayoutOnPath(const minikin::Layout& layout, float hOffset, float vOffset,
                                   const SkPaint& paint, const SkPath& path, size_t start,
                                   size_t end) = 0;
+    static int sApiLevel;
+
     friend class DrawTextFunctor;
     friend class DrawTextOnPathFunctor;
     friend class uirenderer::SkiaCanvasProxy;
diff --git a/libs/hwui/hwui/Typeface.cpp b/libs/hwui/hwui/Typeface.cpp
index 091b526..dca9ef5 100644
--- a/libs/hwui/hwui/Typeface.cpp
+++ b/libs/hwui/hwui/Typeface.cpp
@@ -132,8 +132,8 @@
         bool italicFromFont;
 
         const minikin::FontStyle defaultStyle;
-        const minikin::MinikinFont* mf =
-                families.empty() ? nullptr : families[0]->getClosestMatch(defaultStyle).font;
+        const minikin::MinikinFont* mf = families.empty() ? nullptr
+                : families[0]->getClosestMatch(defaultStyle).font->typeface().get();
         if (mf != nullptr) {
             SkTypeface* skTypeface = reinterpret_cast<const MinikinFontSkia*>(mf)->GetSkTypeface();
             const SkFontStyle& style = skTypeface->fontStyle();
@@ -183,7 +183,7 @@
     std::shared_ptr<minikin::MinikinFont> font = std::make_shared<MinikinFontSkia>(
             std::move(typeface), data, st.st_size, 0, std::vector<minikin::FontVariation>());
     std::vector<minikin::Font> fonts;
-    fonts.push_back(minikin::Font(std::move(font), minikin::FontStyle()));
+    fonts.push_back(minikin::Font::Builder(font).build());
 
     std::shared_ptr<minikin::FontCollection> collection = std::make_shared<minikin::FontCollection>(
             std::make_shared<minikin::FontFamily>(std::move(fonts)));
diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
index eabe2e8..25c76eb 100644
--- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
+++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
@@ -124,14 +124,19 @@
 
 class VectorDrawable : public SkDrawable {
 public:
-    VectorDrawable(VectorDrawableRoot* tree) : mRoot(tree) {}
+    VectorDrawable(VectorDrawableRoot* tree)
+            : mRoot(tree)
+            , mBounds(tree->stagingProperties()->getBounds()) {}
 
 protected:
-    virtual SkRect onGetBounds() override { return SkRect::MakeLargest(); }
-    virtual void onDraw(SkCanvas* canvas) override { mRoot->draw(canvas); }
+    virtual SkRect onGetBounds() override { return mBounds; }
+    virtual void onDraw(SkCanvas* canvas) override {
+        mRoot->draw(canvas, mBounds);
+    }
 
 private:
     sp<VectorDrawableRoot> mRoot;
+    SkRect mBounds;
 };
 
 void SkiaRecordingCanvas::drawVectorDrawable(VectorDrawableRoot* tree) {
diff --git a/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp b/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp
index 2953ea8..15c0ab1 100644
--- a/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp
+++ b/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp
@@ -471,6 +471,7 @@
         sk_sp<SkSurface> onNewSurface(const SkImageInfo&) override { return nullptr; }
         void onCopyOnWrite(ContentChangeMode) override {}
         int* mDrawCounter;
+        void onWritePixels(const SkPixmap&, int x, int y) {}
     };
 
     auto receiverBackground = TestUtils::createSkiaNode(
@@ -1143,4 +1144,47 @@
     RenderNodeDrawable drawable(parent.get(), &canvas, false);
     canvas.drawDrawable(&drawable);
     EXPECT_EQ(6, canvas.getIndex());
-}
\ No newline at end of file
+}
+
+// Draw a vector drawable twice but with different bounds and verify correct bounds are used.
+RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaRecordingCanvas, drawVectorDrawable) {
+    static const int CANVAS_WIDTH = 100;
+    static const int CANVAS_HEIGHT = 200;
+    class VectorDrawableTestCanvas : public TestCanvasBase {
+    public:
+        VectorDrawableTestCanvas() : TestCanvasBase(CANVAS_WIDTH, CANVAS_HEIGHT) {}
+        void onDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
+                const SkPaint* paint, SrcRectConstraint constraint) override {
+            const int index = mDrawCounter++;
+            switch (index) {
+                case 0:
+                    EXPECT_EQ(dst, SkRect::MakeWH(CANVAS_WIDTH, CANVAS_HEIGHT));
+                    break;
+                case 1:
+                    EXPECT_EQ(dst, SkRect::MakeWH(CANVAS_WIDTH/2, CANVAS_HEIGHT));
+                    break;
+                default:
+                    ADD_FAILURE();
+            }
+        }
+    };
+
+    VectorDrawable::Group* group = new VectorDrawable::Group();
+    sp<VectorDrawableRoot> vectorDrawable(new VectorDrawableRoot(group));
+    vectorDrawable->mutateStagingProperties()->setScaledSize(CANVAS_WIDTH/10, CANVAS_HEIGHT/10);
+
+    auto node = TestUtils::createSkiaNode(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT,
+            [&](RenderProperties& props, SkiaRecordingCanvas& canvas) {
+                vectorDrawable->mutateStagingProperties()->setBounds(SkRect::MakeWH(CANVAS_WIDTH,
+                        CANVAS_HEIGHT));
+                canvas.drawVectorDrawable(vectorDrawable.get());
+                vectorDrawable->mutateStagingProperties()->setBounds(SkRect::MakeWH(CANVAS_WIDTH/2,
+                        CANVAS_HEIGHT));
+                canvas.drawVectorDrawable(vectorDrawable.get());
+            });
+
+    VectorDrawableTestCanvas canvas;
+    RenderNodeDrawable drawable(node.get(), &canvas, true);
+    canvas.drawDrawable(&drawable);
+    EXPECT_EQ(2, canvas.mDrawCounter);
+}
diff --git a/libs/hwui/tests/unit/SkiaPipelineTests.cpp b/libs/hwui/tests/unit/SkiaPipelineTests.cpp
index 8fdb0e3..42a92fc 100644
--- a/libs/hwui/tests/unit/SkiaPipelineTests.cpp
+++ b/libs/hwui/tests/unit/SkiaPipelineTests.cpp
@@ -250,6 +250,7 @@
     sk_sp<SkImage> onNewImageSnapshot() override { return nullptr; }
     T* canvas() { return static_cast<T*>(getCanvas()); }
     void onCopyOnWrite(ContentChangeMode) override {}
+    void onWritePixels(const SkPixmap&, int x, int y) override {}
 };
 }
 
diff --git a/libs/hwui/tests/unit/TypefaceTests.cpp b/libs/hwui/tests/unit/TypefaceTests.cpp
index 2232c25..e424a26 100644
--- a/libs/hwui/tests/unit/TypefaceTests.cpp
+++ b/libs/hwui/tests/unit/TypefaceTests.cpp
@@ -57,7 +57,7 @@
     std::shared_ptr<minikin::MinikinFont> font = std::make_shared<MinikinFontSkia>(
             std::move(typeface), data, st.st_size, 0, std::vector<minikin::FontVariation>());
     std::vector<minikin::Font> fonts;
-    fonts.push_back(minikin::Font(std::move(font), minikin::FontStyle()));
+    fonts.push_back(minikin::Font::Builder(font).build());
     return std::make_shared<minikin::FontFamily>(std::move(fonts));
 }
 
diff --git a/libs/incident/Android.mk b/libs/incident/Android.mk
index b63400f..08c8346 100644
--- a/libs/incident/Android.mk
+++ b/libs/incident/Android.mk
@@ -33,6 +33,7 @@
         ../../core/java/android/os/IIncidentManager.aidl \
         ../../core/java/android/os/IIncidentReportStatusListener.aidl \
         proto/android/os/header.proto \
+        proto/android/os/metadata.proto \
         src/IncidentReportArgs.cpp
 
 LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
diff --git a/libs/incident/proto/android/os/metadata.proto b/libs/incident/proto/android/os/metadata.proto
new file mode 100644
index 0000000..a1e89b0
--- /dev/null
+++ b/libs/incident/proto/android/os/metadata.proto
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+syntax = "proto2";
+option java_multiple_files = true;
+
+package android.os;
+
+// This field contains internal metadata associated with an incident report,
+// such as the section ids and privacy policy specs from caller as well as how long
+// and how many bytes a section takes, etc.
+message IncidentMetadata {
+
+    // privacy level of the incident report.
+    enum Destination {
+        AUTOMATIC = 0;
+        EXPLICIT = 1;
+        LOCAL = 2;
+    }
+    optional Destination dest = 1;
+
+    optional int32 request_size = 2;
+
+    optional bool use_dropbox = 3;
+
+    // stats of each section taken in this incident report.
+    message SectionStats {
+        // section id.
+        optional int32 id = 1;
+        // if the section is successfully taken.
+        optional bool success = 2;
+        // number of bytes in the report after filtering.
+        optional int32 report_size_bytes = 3;
+        // the total duration to execute the section.
+        optional int64 exec_duration_ms = 4;
+
+        // number of bytes dumped from the section directly.
+        optional int32 dump_size_bytes = 5;
+        // duration of the dump takes.
+        optional int64 dump_duration_ms = 6;
+        // true if the section timed out.
+        optional bool timed_out = 7;
+        // true if the section is truncated.
+        optional bool is_truncated = 8;
+
+        // Next Tag: 9
+    }
+    repeated SectionStats sections = 4;
+}
+
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/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index d3c6edd..7d2ad91 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -23,6 +23,7 @@
 
 import android.Manifest;
 import android.annotation.NonNull;
+import android.annotation.RequiresFeature;
 import android.annotation.RequiresPermission;
 import android.annotation.SuppressLint;
 import android.annotation.SystemApi;
@@ -30,6 +31,7 @@
 import android.app.PendingIntent;
 import android.content.Context;
 import android.content.Intent;
+import android.content.pm.PackageManager;
 import android.os.Build;
 import android.os.Bundle;
 import android.os.Handler;
@@ -63,6 +65,7 @@
  * location will be obfuscated to a coarse level of accuracy.
  */
 @SystemService(Context.LOCATION_SERVICE)
+@RequiresFeature(PackageManager.FEATURE_LOCATION)
 public class LocationManager {
     private static final String TAG = "LocationManager";
 
@@ -1271,6 +1274,9 @@
         final String allowedProviders = Settings.Secure.getStringForUser(
                 mContext.getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
                 userHandle.getIdentifier());
+        if (allowedProviders == null) {
+            return false;
+        }
         final List<String> providerList = Arrays.asList(allowedProviders.split(","));
         for(String provider : getAllProviders()) {
             if (provider.equals(PASSIVE_PROVIDER)) {
diff --git a/media/OWNERS b/media/OWNERS
new file mode 100644
index 0000000..8f405e9
--- /dev/null
+++ b/media/OWNERS
@@ -0,0 +1,4 @@
+elaurent@google.com
+etalvala@google.com
+lajos@google.com
+marcone@google.com
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 0be54ec..9ff964b 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -16,6 +16,7 @@
 
 package android.media;
 
+import android.annotation.CallbackExecutor;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -65,6 +66,8 @@
 import java.util.Iterator;
 import java.util.List;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.Executor;
+
 
 /**
  * AudioManager provides access to volume and ringer mode control.
@@ -4864,6 +4867,114 @@
         }
     }
 
+
+    /**
+     * @hide
+     * Abstract class to receive event notification about audioserver process state.
+     */
+    @SystemApi
+    public abstract static class AudioServerStateCallback {
+        public void onAudioServerDown() { }
+        public void onAudioServerUp() { }
+    }
+
+    private Executor mAudioServerStateExec;
+    private AudioServerStateCallback mAudioServerStateCb;
+    private final Object mAudioServerStateCbLock = new Object();
+
+    private final IAudioServerStateDispatcher mAudioServerStateDispatcher =
+            new IAudioServerStateDispatcher.Stub() {
+        @Override
+        public void dispatchAudioServerStateChange(boolean state) {
+            Executor exec;
+            AudioServerStateCallback cb;
+
+            synchronized (mAudioServerStateCbLock) {
+                exec = mAudioServerStateExec;
+                cb = mAudioServerStateCb;
+            }
+
+            if ((exec == null) || (cb == null)) {
+                return;
+            }
+            if (state) {
+                exec.execute(() -> cb.onAudioServerUp());
+            } else {
+                exec.execute(() -> cb.onAudioServerDown());
+            }
+        }
+    };
+
+    /**
+     * @hide
+     * Registers a callback for notification of audio server state changes.
+     * @param executor {@link Executor} to handle the callbacks
+     * @param stateCallback the callback to receive the audio server state changes
+     *        To remove the callabck, pass a null reference for both executor and stateCallback.
+     */
+    @SystemApi
+    public void setAudioServerStateCallback(@NonNull Executor executor,
+            @NonNull AudioServerStateCallback stateCallback) {
+        if (stateCallback == null) {
+            throw new IllegalArgumentException("Illegal null AudioServerStateCallback");
+        }
+        if (executor == null) {
+            throw new IllegalArgumentException(
+                    "Illegal null Executor for the AudioServerStateCallback");
+        }
+
+        synchronized (mAudioServerStateCbLock) {
+            if (mAudioServerStateCb != null) {
+                throw new IllegalStateException(
+                    "setAudioServerStateCallback called with already registered callabck");
+            }
+            final IAudioService service = getService();
+            try {
+                service.registerAudioServerStateDispatcher(mAudioServerStateDispatcher);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+            mAudioServerStateExec = executor;
+            mAudioServerStateCb = stateCallback;
+        }
+    }
+
+    /**
+     * @hide
+     * Unregisters the callback for notification of audio server state changes.
+     */
+    @SystemApi
+    public void clearAudioServerStateCallback() {
+        synchronized (mAudioServerStateCbLock) {
+            if (mAudioServerStateCb != null) {
+                final IAudioService service = getService();
+                try {
+                    service.unregisterAudioServerStateDispatcher(
+                            mAudioServerStateDispatcher);
+                } catch (RemoteException e) {
+                    throw e.rethrowFromSystemServer();
+                }
+            }
+            mAudioServerStateExec = null;
+            mAudioServerStateCb = null;
+        }
+    }
+
+    /**
+     * @hide
+     * Checks if native audioservice is running or not.
+     * @return true if native audioservice runs, false otherwise.
+     */
+    @SystemApi
+    public boolean isAudioServerRunning() {
+        final IAudioService service = getService();
+        try {
+            return service.isAudioServerRunning();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
     //---------------------------------------------------------
     // Inner classes
     //--------------------
diff --git a/media/java/android/media/AudioRecord.java b/media/java/android/media/AudioRecord.java
index 8feeb5a..95ad93c 100644
--- a/media/java/android/media/AudioRecord.java
+++ b/media/java/android/media/AudioRecord.java
@@ -1425,6 +1425,7 @@
     /*
      * Call BEFORE adding a routing callback handler.
      */
+    @GuardedBy("mRoutingChangeListeners")
     private void testEnableNativeRoutingCallbacksLocked() {
         if (mRoutingChangeListeners.size() == 0) {
             native_enableDeviceCallback();
@@ -1434,6 +1435,7 @@
     /*
      * Call AFTER removing a routing callback handler.
      */
+    @GuardedBy("mRoutingChangeListeners")
     private void testDisableNativeRoutingCallbacksLocked() {
         if (mRoutingChangeListeners.size() == 0) {
             native_disableDeviceCallback();
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index 8e822a5..2d5fad5 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -2821,6 +2821,7 @@
     /*
      * Call BEFORE adding a routing callback handler.
      */
+    @GuardedBy("mRoutingChangeListeners")
     private void testEnableNativeRoutingCallbacksLocked() {
         if (mRoutingChangeListeners.size() == 0) {
             native_enableDeviceCallback();
@@ -2830,6 +2831,7 @@
     /*
      * Call AFTER removing a routing callback handler.
      */
+    @GuardedBy("mRoutingChangeListeners")
     private void testDisableNativeRoutingCallbacksLocked() {
         if (mRoutingChangeListeners.size() == 0) {
             native_disableDeviceCallback();
diff --git a/media/java/android/media/DataSourceDesc.java b/media/java/android/media/DataSourceDesc.java
index 73fad7a..6dff07f 100644
--- a/media/java/android/media/DataSourceDesc.java
+++ b/media/java/android/media/DataSourceDesc.java
@@ -30,6 +30,8 @@
 import java.io.FileDescriptor;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.net.CookieHandler;
+import java.net.CookieManager;
 import java.net.HttpCookie;
 
 import java.util.ArrayList;
@@ -433,10 +435,22 @@
          * @param cookies the cookies to be sent together with the request
          * @return the same Builder instance.
          * @throws NullPointerException if context or uri is null.
+         * @throws IllegalArgumentException if the cookie handler is not of CookieManager type
+         *                                  when cookies are provided.
          */
         public Builder setDataSource(@NonNull Context context, @NonNull Uri uri,
                 @Nullable Map<String, String> headers, @Nullable List<HttpCookie> cookies) {
+            Preconditions.checkNotNull(context, "context cannot be null");
             Preconditions.checkNotNull(uri);
+            if (cookies != null) {
+                CookieHandler cookieHandler = CookieHandler.getDefault();
+                if (cookieHandler != null && !(cookieHandler instanceof CookieManager)) {
+                    throw new IllegalArgumentException(
+                            "The cookie handler has to be of CookieManager type "
+                            + "when cookies are provided.");
+                }
+            }
+
             resetDataSource();
             mType = TYPE_URI;
             mUri = uri;
diff --git a/core/java/com/android/internal/car/ICarServiceHelper.aidl b/media/java/android/media/IAudioServerStateDispatcher.aidl
similarity index 68%
rename from core/java/com/android/internal/car/ICarServiceHelper.aidl
rename to media/java/android/media/IAudioServerStateDispatcher.aidl
index 9ee330b..2bc90ea 100644
--- a/core/java/com/android/internal/car/ICarServiceHelper.aidl
+++ b/media/java/android/media/IAudioServerStateDispatcher.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 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.
@@ -14,11 +14,15 @@
  * limitations under the License.
  */
 
-package com.android.internal.car;
+package android.media;
 
 /**
- * Helper API for car service. Only for itneraction between system server and car service.
- * @hide
+ * AIDL for the AudioService to signal audio server state changes
+ *
+ * {@hide}
  */
-interface ICarServiceHelper {
+oneway interface IAudioServerStateDispatcher {
+
+    void dispatchAudioServerStateChange(boolean state);
+
 }
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index cd4143c..05ba4c3 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -16,9 +16,7 @@
 
 package android.media;
 
-import android.app.PendingIntent;
 import android.bluetooth.BluetoothDevice;
-import android.content.ComponentName;
 import android.media.AudioAttributes;
 import android.media.AudioFocusInfo;
 import android.media.AudioPlaybackConfiguration;
@@ -26,30 +24,40 @@
 import android.media.AudioRoutesInfo;
 import android.media.IAudioFocusDispatcher;
 import android.media.IAudioRoutesObserver;
+import android.media.IAudioServerStateDispatcher;
 import android.media.IPlaybackConfigDispatcher;
 import android.media.IRecordingConfigDispatcher;
 import android.media.IRingtonePlayer;
 import android.media.IVolumeController;
+import android.media.IVolumeController;
 import android.media.PlayerBase;
-import android.media.Rating;
 import android.media.VolumePolicy;
 import android.media.audiopolicy.AudioPolicyConfig;
 import android.media.audiopolicy.IAudioPolicyCallback;
-import android.net.Uri;
-import android.view.KeyEvent;
 
 /**
  * {@hide}
  */
 interface IAudioService {
+    // C++ and Java methods below.
 
-    // WARNING: When methods are inserted or deleted, the transaction IDs in
+    // WARNING: When methods are inserted or deleted in this section, the transaction IDs in
     // frameworks/native/include/audiomanager/IAudioManager.h must be updated to match the order
     // in this file.
     //
     // When a method's argument list is changed, BpAudioManager's corresponding serialization code
     // (if any) in frameworks/native/services/audiomanager/IAudioManager.cpp must be updated.
 
+    int trackPlayer(in PlayerBase.PlayerIdCard pic);
+
+    oneway void playerAttributes(in int piid, in AudioAttributes attr);
+
+    oneway void playerEvent(in int piid, in int event);
+
+    oneway void releasePlayer(in int piid);
+
+    // Java-only methods below.
+
     oneway void adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags,
             String callingPackage, String caller);
 
@@ -187,14 +195,6 @@
 
     List<AudioPlaybackConfiguration> getActivePlaybackConfigurations();
 
-    int trackPlayer(in PlayerBase.PlayerIdCard pic);
-
-    oneway void playerAttributes(in int piid, in AudioAttributes attr);
-
-    oneway void playerEvent(in int piid, in int event);
-
-    oneway void releasePlayer(in int piid);
-
     void disableRingtoneSync(in int userId);
 
     int getFocusRampTimeMs(in int focusGain, in AudioAttributes attr);
@@ -210,5 +210,12 @@
     oneway void setFocusRequestResultFromExtPolicy(in AudioFocusInfo afi, int requestResult,
             in IAudioPolicyCallback pcb);
 
-    // WARNING: read warning at top of file, it is recommended to add new methods at the end
+    void registerAudioServerStateDispatcher(IAudioServerStateDispatcher asd);
+
+    oneway void unregisterAudioServerStateDispatcher(IAudioServerStateDispatcher asd);
+
+    boolean isAudioServerRunning();
+
+    // WARNING: read warning at top of file, new methods that need to be used by native
+    // code via IAudioManager.h need to be added to the top section.
 }
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/MediaController2.java b/media/java/android/media/MediaController2.java
index e9ffe60..bd6c7e6 100644
--- a/media/java/android/media/MediaController2.java
+++ b/media/java/android/media/MediaController2.java
@@ -30,7 +30,7 @@
 import android.media.session.MediaSessionManager;
 import android.media.update.ApiLoader;
 import android.media.update.MediaController2Provider;
-import android.media.update.PlaybackInfoProvider;
+import android.media.update.MediaController2Provider.PlaybackInfoProvider;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.ResultReceiver;
diff --git a/media/java/android/media/MediaDataSource.java b/media/java/android/media/MediaDataSource.java
index 948da0b..4ba2120 100644
--- a/media/java/android/media/MediaDataSource.java
+++ b/media/java/android/media/MediaDataSource.java
@@ -34,8 +34,8 @@
     /**
      * Called to request data from the given position.
      *
-     * Implementations should should write up to {@code size} bytes into
-     * {@code buffer}, and return the number of bytes written.
+     * Implementations should fill {@code buffer} with up to {@code size}
+     * bytes of data, and return the number of valid bytes in the buffer.
      *
      * Return {@code 0} if size is zero (thus no bytes are read).
      *
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/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index 1bc3dfa..fe5e822 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -1484,6 +1484,7 @@
     /*
      * Call BEFORE adding a routing callback handler or AFTER removing a routing callback handler.
      */
+    @GuardedBy("mRoutingChangeListeners")
     private void enableNativeRoutingCallbacksLocked(boolean enabled) {
         if (mRoutingChangeListeners.size() == 0) {
             native_enableDeviceCallback(enabled);
diff --git a/media/java/android/media/MediaPlayer2.java b/media/java/android/media/MediaPlayer2.java
index e331b2c..2f3d972 100644
--- a/media/java/android/media/MediaPlayer2.java
+++ b/media/java/android/media/MediaPlayer2.java
@@ -804,19 +804,6 @@
     public abstract DataSourceDesc editPlaylistItem(int index, DataSourceDesc dsd);
 
     /**
-     * Prepares the player for playback, synchronously.
-     *
-     * After setting the datasource and the display surface, you need to either
-     * call prepare() or prepareAsync(). For files, it is OK to call prepare(),
-     * which blocks until MediaPlayer2 is ready for playback.
-     *
-     * @throws IOException if source can not be accessed
-     * @throws IllegalStateException if it is called in an invalid state
-     * @hide
-     */
-    public void prepare() throws IOException { }
-
-    /**
      * Prepares the player for playback, asynchronously.
      *
      * After setting the datasource and the display surface, you need to
diff --git a/media/java/android/media/MediaPlayer2Impl.java b/media/java/android/media/MediaPlayer2Impl.java
index e3d5ac0..1b21b5b 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;
@@ -152,7 +137,7 @@
  *         {@link #getVideoWidth()}, {@link #setAudioAttributes(AudioAttributes)},
  *         {@link #setLooping(boolean)},
  *         {@link #setVolume(float, float)}, {@link #pause()}, {@link #play()},
- *         {@link #seekTo(long, int)}, {@link #prepare()} or
+ *         {@link #seekTo(long, int)} or
  *         {@link #prepareAsync()} in the <em>Idle</em> state for both cases. If any of these
  *         methods is called right after a MediaPlayer2 object is constructed,
  *         the user supplied callback method OnErrorListener.onError() won't be
@@ -199,7 +184,7 @@
  *         register a OnErrorListener to look out for error notifications from
  *         the internal player engine.</li>
  *         <li>IllegalStateException is
- *         thrown to prevent programming errors such as calling {@link #prepare()},
+ *         thrown to prevent programming errors such as calling
  *         {@link #prepareAsync()}, {@link #setDataSource(DataSourceDesc)}, or
  *         {@code setPlaylist} methods in an invalid state. </li>
  *         </ul>
@@ -221,15 +206,11 @@
  *     <li>A MediaPlayer2 object must first enter the <em>Prepared</em> state
  *         before playback can be started.
  *         <ul>
- *         <li>There are two ways (synchronous vs.
- *         asynchronous) that the <em>Prepared</em> state can be reached:
- *         either a call to {@link #prepare()} (synchronous) which
- *         transfers the object to the <em>Prepared</em> state once the method call
- *         returns, or a call to {@link #prepareAsync()} (asynchronous) which
- *         first transfers the object to the <em>Preparing</em> state after the
+ *         <li>{@link #prepareAsync()} first transfers the object to the
+ *         <em>Preparing</em> state after the
  *         call returns (which occurs almost right way) while the internal
  *         player engine continues working on the rest of preparation work
- *         until the preparation work completes. When the preparation completes or when {@link #prepare()} call returns,
+ *         until the preparation work completes. When the preparation completes,
  *         the internal player engine then calls a user supplied callback method,
  *         onPrepared() of the EventCallback interface, if an
  *         EventCallback is registered beforehand via {@link
@@ -239,7 +220,7 @@
  *         of calling any method with side effect while a MediaPlayer2 object is
  *         in the <em>Preparing</em> state is undefined.</li>
  *         <li>An IllegalStateException is
- *         thrown if {@link #prepare()} or {@link #prepareAsync()} is called in
+ *         thrown if {@link #prepareAsync()} is called in
  *         any other state.</li>
  *         <li>While in the <em>Prepared</em> state, properties
  *         such as audio/sound volume, screenOnWhilePlaying, looping can be
@@ -410,7 +391,7 @@
  *     <td>{Error}</p></td>
  *     <td>Successful invoke of this method does not change the state. In order for the
  *         target audio attributes type to become effective, this method must be called before
- *         prepare() or prepareAsync().</p></td></tr>
+ *         prepareAsync().</p></td></tr>
  * <tr><td>setAudioSessionId </p></td>
  *     <td>{Idle} </p></td>
  *     <td>{Initialized, Prepared, Started, Paused, Stopped, PlaybackCompleted,
@@ -424,7 +405,7 @@
  *     <td>{Error}</p></td>
  *     <td>Successful invoke of this method does not change the state. In order for the
  *         target audio stream type to become effective, this method must be called before
- *         prepare() or prepareAsync().</p></td></tr>
+ *         prepareAsync().</p></td></tr>
  * <tr><td>setAuxEffectSendLevel </p></td>
  *     <td>any</p></td>
  *     <td>{} </p></td>
@@ -576,9 +557,12 @@
     private boolean mBypassInterruptionPolicy;
     private final CloseGuard mGuard = CloseGuard.get();
 
+    private final Object mPlLock = new Object();
     private List<DataSourceDesc> mPlaylist;
-    private int mPLCurrentIndex = 0;
-    private int mPLNextIndex = -1;
+    private int mPlCurrentIndex = 0;
+    private int mPlNextIndex = -1;
+    private int mPlNextSourceState = NEXT_SOURCE_STATE_INIT;
+    private boolean mPlNextSourcePlayPending = false;
     private int mLoopingMode = LOOPING_MODE_NONE;
 
     // Modular DRM
@@ -620,6 +604,11 @@
         native_setup(new WeakReference<MediaPlayer2Impl>(this));
     }
 
+    private static final int NEXT_SOURCE_STATE_ERROR = -1;
+    private static final int NEXT_SOURCE_STATE_INIT = 0;
+    private static final int NEXT_SOURCE_STATE_PREPARING = 1;
+    private static final int NEXT_SOURCE_STATE_PREPARED = 2;
+
     /*
      * Update the MediaPlayer2Impl SurfaceTexture.
      * Call after setting a new display surface.
@@ -789,10 +778,13 @@
     @Override
     public void setDataSource(@NonNull DataSourceDesc dsd) throws IOException {
         Preconditions.checkNotNull(dsd, "the DataSourceDesc cannot be null");
-        mPlaylist = Collections.synchronizedList(new ArrayList<DataSourceDesc>(1));
-        mPlaylist.add(dsd);
-        mPLCurrentIndex = 0;
-        setDataSourcePriv(dsd);
+        synchronized (mPlLock) {
+            mPlaylist = Collections.synchronizedList(new ArrayList<DataSourceDesc>(1));
+            mPlaylist.add(dsd);
+            mPlCurrentIndex = 0;
+            mPlNextIndex = -1;
+            handleDataSource(true /* isCurrent */, dsd);
+        }
     }
 
     /**
@@ -802,10 +794,12 @@
      */
     @Override
     public DataSourceDesc getCurrentDataSource() {
-        if (mPlaylist == null) {
-            return null;
+        synchronized (mPlLock) {
+            if (mPlaylist == null) {
+                return null;
+            }
+            return mPlaylist.get(mPlCurrentIndex);
         }
-        return mPlaylist.get(mPLCurrentIndex);
     }
 
     /**
@@ -841,11 +835,14 @@
             startIndex = pl.size() - 1;
         }
 
-        mPlaylist = Collections.synchronizedList(new ArrayList(pl));
-        mPLCurrentIndex = startIndex;
-        setDataSourcePriv(mPlaylist.get(startIndex));
-        // TODO: handle the preparation of next source in the play list.
-        // It should be processed after current source is prepared.
+        synchronized (mPlLock) {
+            mPlaylist = Collections.synchronizedList(new ArrayList(pl));
+            mPlCurrentIndex = startIndex;
+            handleDataSource(true /* isCurrent */, mPlaylist.get(startIndex));
+            // TODO: handle the preparation of next source in the play list.
+            // It should be processed after current source is prepared.
+            mPlNextIndex = getNextIndex_l();
+        }
     }
 
     /**
@@ -855,10 +852,12 @@
      */
     @Override
     public List<DataSourceDesc> getPlaylist() {
-        if (mPlaylist == null) {
-            return null;
+        synchronized (mPlLock) {
+            if (mPlaylist == null) {
+                return null;
+            }
+            return new ArrayList(mPlaylist);
         }
-        return new ArrayList(mPlaylist);
     }
 
     /**
@@ -870,19 +869,21 @@
      */
     @Override
     public void setCurrentPlaylistItem(int index) {
-        if (mPlaylist == null) {
-            throw new IllegalArgumentException("play list has not been set yet.");
-        }
-        if (index < 0 || index >= mPlaylist.size()) {
-            throw new IndexOutOfBoundsException("index is out of play list range.");
-        }
+        synchronized (mPlLock) {
+            if (mPlaylist == null) {
+                throw new IllegalArgumentException("play list has not been set yet.");
+            }
+            if (index < 0 || index >= mPlaylist.size()) {
+                throw new IndexOutOfBoundsException("index is out of play list range.");
+            }
 
-        if (index == mPLCurrentIndex) {
-            return;
-        }
+            if (index == mPlCurrentIndex) {
+                return;
+            }
 
-        // TODO: in playing state, stop current source and start to play source of index.
-        mPLCurrentIndex = index;
+            // TODO: in playing state, stop current source and start to play source of index.
+            mPlCurrentIndex = index;
+        }
     }
 
     /**
@@ -894,19 +895,21 @@
      */
     @Override
     public void setNextPlaylistItem(int index) {
-        if (mPlaylist == null) {
-            throw new IllegalArgumentException("play list has not been set yet.");
-        }
-        if (index < 0 || index >= mPlaylist.size()) {
-            throw new IndexOutOfBoundsException("index is out of play list range.");
-        }
+        synchronized (mPlLock) {
+            if (mPlaylist == null) {
+                throw new IllegalArgumentException("play list has not been set yet.");
+            }
+            if (index < 0 || index >= mPlaylist.size()) {
+                throw new IndexOutOfBoundsException("index is out of play list range.");
+            }
 
-        if (index == mPLNextIndex) {
-            return;
-        }
+            if (index == mPlNextIndex) {
+                return;
+            }
 
-        // TODO: prepare the new next-to-be-played DataSourceDesc
-        mPLNextIndex = index;
+            // TODO: prepare the new next-to-be-played DataSourceDesc
+            mPlNextIndex = index;
+        }
     }
 
     /**
@@ -916,7 +919,9 @@
      */
     @Override
     public int getCurrentPlaylistItemIndex() {
-        return mPLCurrentIndex;
+        synchronized (mPlLock) {
+            return mPlCurrentIndex;
+        }
     }
 
     /**
@@ -935,12 +940,15 @@
             && mode != LOOPING_MODE_SHUFFLE) {
             throw new IllegalArgumentException("mode is not supported.");
         }
-        mLoopingMode = mode;
-        if (mPlaylist == null) {
-            return;
-        }
 
-        // TODO: handle the new mode if necessary.
+        synchronized (mPlLock) {
+            mLoopingMode = mode;
+            if (mPlaylist == null) {
+                return;
+            }
+
+            // TODO: handle the new mode if necessary.
+        }
     }
 
     /**
@@ -950,7 +958,9 @@
      */
     @Override
     public int getLoopingMode() {
-        return mPLCurrentIndex;
+        synchronized (mPlLock) {
+            return mPlCurrentIndex;
+        }
     }
 
     /**
@@ -961,10 +971,12 @@
      */
     @Override
     public void movePlaylistItem(int indexFrom, int indexTo) {
-        if (mPlaylist == null) {
-            throw new IllegalArgumentException("play list has not been set yet.");
+        synchronized (mPlLock) {
+            if (mPlaylist == null) {
+                throw new IllegalArgumentException("play list has not been set yet.");
+            }
+            // TODO: move the DataSourceDesc from indexFrom to indexTo.
         }
-        // TODO: move the DataSourceDesc from indexFrom to indexTo.
     }
 
     /**
@@ -979,14 +991,16 @@
      */
     @Override
     public DataSourceDesc removePlaylistItem(int index) {
-        if (mPlaylist == null) {
-            throw new IllegalArgumentException("play list has not been set yet.");
-        }
+        synchronized (mPlLock) {
+            if (mPlaylist == null) {
+                throw new IllegalArgumentException("play list has not been set yet.");
+            }
 
-        DataSourceDesc oldDsd = mPlaylist.remove(index);
-        // TODO: if index == mPLCurrentIndex, stop current source and move to next one.
-        // if index == mPLNextIndex, prepare the new next-to-be-played source.
-        return oldDsd;
+            DataSourceDesc oldDsd = mPlaylist.remove(index);
+            // TODO: if index == mPlCurrentIndex, stop current source and move to next one.
+            // if index == mPlNextIndex, prepare the new next-to-be-played source.
+            return oldDsd;
+        }
     }
 
     /**
@@ -1005,26 +1019,28 @@
     public void addPlaylistItem(int index, DataSourceDesc dsd) {
         Preconditions.checkNotNull(dsd, "the DataSourceDesc cannot be null");
 
-        if (mPlaylist == null) {
-            if (index == 0) {
-                mPlaylist = Collections.synchronizedList(new ArrayList<DataSourceDesc>());
-                mPlaylist.add(dsd);
-                mPLCurrentIndex = 0;
-                return;
+        synchronized (mPlLock) {
+            if (mPlaylist == null) {
+                if (index == 0) {
+                    mPlaylist = Collections.synchronizedList(new ArrayList<DataSourceDesc>());
+                    mPlaylist.add(dsd);
+                    mPlCurrentIndex = 0;
+                    return;
+                }
+                throw new IllegalArgumentException("index should be 0 for first DataSourceDesc.");
             }
-            throw new IllegalArgumentException("index should be 0 for first DataSourceDesc.");
-        }
 
-        long id = dsd.getId();
-        for (DataSourceDesc pldsd : mPlaylist) {
-            if (id == pldsd.getId()) {
-                throw new IllegalArgumentException("Id of dsd already exists in the play list.");
+            long id = dsd.getId();
+            for (DataSourceDesc pldsd : mPlaylist) {
+                if (id == pldsd.getId()) {
+                    throw new IllegalArgumentException("Id of dsd already exists in the play list.");
+                }
             }
-        }
 
-        mPlaylist.add(index, dsd);
-        if (index <= mPLCurrentIndex) {
-            ++mPLCurrentIndex;
+            mPlaylist.add(index, dsd);
+            if (index <= mPlCurrentIndex) {
+                ++mPlCurrentIndex;
+            }
         }
     }
 
@@ -1051,42 +1067,62 @@
         Preconditions.checkNotNull(mPlaylist, "the play list cannot be null");
 
         long id = dsd.getId();
-        for (int i = 0; i < mPlaylist.size(); ++i) {
-            if (i == index) {
-                continue;
+        synchronized (mPlLock) {
+            for (int i = 0; i < mPlaylist.size(); ++i) {
+                if (i == index) {
+                    continue;
+                }
+                if (id == mPlaylist.get(i).getId()) {
+                    throw new IllegalArgumentException(
+                            "Id of dsd already exists in the play list.");
+                }
             }
-            if (id == mPlaylist.get(i).getId()) {
-                throw new IllegalArgumentException("Id of dsd already exists in the play list.");
-            }
-        }
 
-        // TODO: if needed, stop playback of current source, and start new dsd.
-        DataSourceDesc oldDsd = mPlaylist.set(index, dsd);
-        return mPlaylist.set(index, dsd);
+            // TODO: if needed, stop playback of current source, and start new dsd.
+            DataSourceDesc oldDsd = mPlaylist.set(index, dsd);
+            return mPlaylist.set(index, dsd);
+        }
     }
 
-    private void setDataSourcePriv(@NonNull DataSourceDesc dsd) throws IOException {
+    // Called with mPlLock acquired.
+    // TODO: support all looping modes
+    private int getNextIndex_l() {
+        if (mPlaylist.size() <= 1) {
+            return -1;
+        }
+        int index = mPlCurrentIndex + 1;
+        if (index >= mPlaylist.size()) {
+            index = 0;
+        }
+        return index;
+    }
+
+    private void handleDataSource(boolean isCurrent, @NonNull DataSourceDesc dsd)
+            throws IOException {
         Preconditions.checkNotNull(dsd, "the DataSourceDesc cannot be null");
 
         switch (dsd.getType()) {
             case DataSourceDesc.TYPE_CALLBACK:
-                setDataSourcePriv(dsd.getId(),
-                                  dsd.getMedia2DataSource());
+                handleDataSource(isCurrent,
+                                 dsd.getId(),
+                                 dsd.getMedia2DataSource());
                 break;
 
             case DataSourceDesc.TYPE_FD:
-                setDataSourcePriv(dsd.getId(),
-                                  dsd.getFileDescriptor(),
-                                  dsd.getFileDescriptorOffset(),
-                                  dsd.getFileDescriptorLength());
+                handleDataSource(isCurrent,
+                                 dsd.getId(),
+                                 dsd.getFileDescriptor(),
+                                 dsd.getFileDescriptorOffset(),
+                                 dsd.getFileDescriptorLength());
                 break;
 
             case DataSourceDesc.TYPE_URI:
-                setDataSourcePriv(dsd.getId(),
-                                  dsd.getUriContext(),
-                                  dsd.getUri(),
-                                  dsd.getUriHeaders(),
-                                  dsd.getUriCookies());
+                handleDataSource(isCurrent,
+                                 dsd.getId(),
+                                 dsd.getUriContext(),
+                                 dsd.getUri(),
+                                 dsd.getUriHeaders(),
+                                 dsd.getUriCookies());
                 break;
 
             default:
@@ -1113,66 +1149,59 @@
      * @throws NullPointerException     if context or uri is null
      * @throws IOException              if uri has a file scheme and an I/O error occurs
      */
-    private void setDataSourcePriv(long srcId, @NonNull Context context, @NonNull Uri uri,
+    private void handleDataSource(
+            boolean isCurrent, long srcId,
+            @NonNull Context context, @NonNull Uri uri,
             @Nullable Map<String, String> headers, @Nullable List<HttpCookie> cookies)
             throws IOException {
-        if (context == null) {
-            throw new NullPointerException("context param can not be null.");
-        }
-
-        if (uri == null) {
-            throw new NullPointerException("uri param can not be null.");
-        }
-
-        if (cookies != null) {
-            CookieHandler cookieHandler = CookieHandler.getDefault();
-            if (cookieHandler != null && !(cookieHandler instanceof CookieManager)) {
-                throw new IllegalArgumentException("The cookie handler has to be of CookieManager "
-                        + "type when cookies are provided.");
-            }
-        }
-
         // The context and URI usually belong to the calling user. Get a resolver for that user
         // and strip out the userId from the URI if present.
         final ContentResolver resolver = context.getContentResolver();
         final String scheme = uri.getScheme();
         final String authority = ContentProvider.getAuthorityWithoutUserId(uri.getAuthority());
         if (ContentResolver.SCHEME_FILE.equals(scheme)) {
-            setDataSourcePriv(srcId, uri.getPath(), null, null);
+            handleDataSource(isCurrent, srcId, uri.getPath(), null, null);
             return;
-        } else if (ContentResolver.SCHEME_CONTENT.equals(scheme)
+        }
+
+        if (ContentResolver.SCHEME_CONTENT.equals(scheme)
                 && Settings.AUTHORITY.equals(authority)) {
             // Try cached ringtone first since the actual provider may not be
             // encryption aware, or it may be stored on CE media storage
             final int type = RingtoneManager.getDefaultType(uri);
             final Uri cacheUri = RingtoneManager.getCacheForType(type, context.getUserId());
             final Uri actualUri = RingtoneManager.getActualDefaultRingtoneUri(context, type);
-            if (attemptDataSource(srcId, resolver, cacheUri)) {
+            if (attemptDataSource(isCurrent, srcId, resolver, cacheUri)) {
                 return;
-            } else if (attemptDataSource(srcId, resolver, actualUri)) {
-                return;
-            } else {
-                setDataSourcePriv(srcId, uri.toString(), headers, cookies);
             }
+            if (attemptDataSource(isCurrent, srcId, resolver, actualUri)) {
+                return;
+            }
+            handleDataSource(isCurrent, srcId, uri.toString(), headers, cookies);
         } else {
             // Try requested Uri locally first, or fallback to media server
-            if (attemptDataSource(srcId, resolver, uri)) {
+            if (attemptDataSource(isCurrent, srcId, resolver, uri)) {
                 return;
-            } else {
-                setDataSourcePriv(srcId, uri.toString(), headers, cookies);
             }
+            handleDataSource(isCurrent, srcId, uri.toString(), headers, cookies);
         }
     }
 
-    private boolean attemptDataSource(long srcId, ContentResolver resolver, Uri uri) {
+    private boolean attemptDataSource(
+            boolean isCurrent, long srcId, ContentResolver resolver, Uri uri) {
         try (AssetFileDescriptor afd = resolver.openAssetFileDescriptor(uri, "r")) {
             if (afd.getDeclaredLength() < 0) {
-                setDataSourcePriv(srcId, afd.getFileDescriptor(), 0, DataSourceDesc.LONG_MAX);
+                handleDataSource(isCurrent,
+                                 srcId,
+                                 afd.getFileDescriptor(),
+                                 0,
+                                 DataSourceDesc.LONG_MAX);
             } else {
-                setDataSourcePriv(srcId,
-                                  afd.getFileDescriptor(),
-                                  afd.getStartOffset(),
-                                  afd.getDeclaredLength());
+                handleDataSource(isCurrent,
+                                 srcId,
+                                 afd.getFileDescriptor(),
+                                 afd.getStartOffset(),
+                                 afd.getDeclaredLength());
             }
             return true;
         } catch (NullPointerException | SecurityException | IOException ex) {
@@ -1181,10 +1210,10 @@
         }
     }
 
-    private void setDataSourcePriv(
-            long srcId, String path, Map<String, String> headers, List<HttpCookie> cookies)
-            throws IOException, IllegalArgumentException, SecurityException, IllegalStateException
-    {
+    private void handleDataSource(
+            boolean isCurrent, long srcId,
+            String path, Map<String, String> headers, List<HttpCookie> cookies)
+            throws IOException {
         String[] keys = null;
         String[] values = null;
 
@@ -1199,19 +1228,21 @@
                 ++i;
             }
         }
-        setDataSourcePriv(srcId, path, keys, values, cookies);
+        handleDataSource(isCurrent, srcId, path, keys, values, cookies);
     }
 
-    private void setDataSourcePriv(long srcId, String path, String[] keys, String[] values,
-            List<HttpCookie> cookies)
-            throws IOException, IllegalArgumentException, SecurityException, IllegalStateException {
+    private void handleDataSource(boolean isCurrent, long srcId,
+            String path, String[] keys, String[] values, List<HttpCookie> cookies)
+            throws IOException {
         final Uri uri = Uri.parse(path);
         final String scheme = uri.getScheme();
         if ("file".equals(scheme)) {
             path = uri.getPath();
         } else if (scheme != null) {
             // handle non-file sources
-            nativeSetDataSource(
+            nativeHandleDataSourceUrl(
+                isCurrent,
+                srcId,
                 Media2HTTPService.createHTTPService(path, cookies),
                 path,
                 keys,
@@ -1223,16 +1254,17 @@
         if (file.exists()) {
             FileInputStream is = new FileInputStream(file);
             FileDescriptor fd = is.getFD();
-            setDataSourcePriv(srcId, fd, 0, DataSourceDesc.LONG_MAX);
+            handleDataSource(isCurrent, srcId, fd, 0, DataSourceDesc.LONG_MAX);
             is.close();
         } else {
-            throw new IOException("setDataSourcePriv failed.");
+            throw new IOException("handleDataSource failed.");
         }
     }
 
-    private native void nativeSetDataSource(
-        Media2HTTPService httpService, String path, String[] keys, String[] values)
-        throws IOException, IllegalArgumentException, SecurityException, IllegalStateException;
+    private native void nativeHandleDataSourceUrl(
+            boolean isCurrent, long srcId,
+            Media2HTTPService httpService, String path, String[] keys, String[] values)
+            throws IOException;
 
     /**
      * Sets the data source (FileDescriptor) to use. The FileDescriptor must be
@@ -1243,53 +1275,92 @@
      * @throws IllegalArgumentException if fd is not a valid FileDescriptor
      * @throws IOException if fd can not be read
      */
-    private void setDataSourcePriv(long srcId, FileDescriptor fd, long offset, long length)
-            throws IOException {
-        _setDataSource(fd, offset, length);
+    private void handleDataSource(
+            boolean isCurrent, long srcId,
+            FileDescriptor fd, long offset, long length) throws IOException {
+        nativeHandleDataSourceFD(isCurrent, srcId, fd, offset, length);
     }
 
-    private native void _setDataSource(FileDescriptor fd, long offset, long length)
-            throws IOException;
+    private native void nativeHandleDataSourceFD(boolean isCurrent, long srcId,
+            FileDescriptor fd, long offset, long length) throws IOException;
 
     /**
      * @throws IllegalStateException if it is called in an invalid state
      * @throws IllegalArgumentException if dataSource is not a valid Media2DataSource
      */
-    private void setDataSourcePriv(long srcId, Media2DataSource dataSource) {
-        _setDataSource(dataSource);
+    private void handleDataSource(boolean isCurrent, long srcId, Media2DataSource dataSource) {
+        nativeHandleDataSourceCallback(isCurrent, srcId, dataSource);
     }
 
-    private native void _setDataSource(Media2DataSource dataSource);
+    private native void nativeHandleDataSourceCallback(
+            boolean isCurrent, long srcId, Media2DataSource dataSource);
 
-    /**
-     * Prepares the player for playback, synchronously.
-     *
-     * After setting the datasource and the display surface, you need to either
-     * call prepare() or prepareAsync(). For files, it is OK to call prepare(),
-     * which blocks until MediaPlayer2 is ready for playback.
-     *
-     * @throws IOException if source can not be accessed
-     * @throws IllegalStateException if it is called in an invalid state
-     * @hide
-     */
-    @Override
-    public void prepare() throws IOException {
-        _prepare();
-        scanInternalSubtitleTracks();
+    // This function shall be called with |mPlLock| acquired.
+    private void prepareNextDataSource_l() {
+        if (mPlNextIndex < 0 || mPlNextSourceState != NEXT_SOURCE_STATE_INIT) {
+            // There is no next source or it's in preparing or prepared state.
+            return;
+        }
 
-        // DrmInfo, if any, has been resolved by now.
-        synchronized (mDrmLock) {
-            mDrmInfoResolved = true;
+        try {
+            mPlNextSourceState = NEXT_SOURCE_STATE_PREPARING;
+            handleDataSource(false /* isCurrent */, mPlaylist.get(mPlNextIndex));
+        } catch (Exception e) {
+            Message msg2 = mEventHandler.obtainMessage(
+                    MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, MEDIA_ERROR_UNSUPPORTED, null);
+            final long nextSrcId = mPlaylist.get(mPlNextIndex).getId();
+            mEventHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    mEventHandler.handleMessage(msg2, nextSrcId);
+                }
+            });
         }
     }
 
-    private native void _prepare() throws IOException, IllegalStateException;
+    // This function shall be called with |mPlLock| acquired.
+    private void playNextDataSource_l() {
+        if (mPlNextIndex < 0) {
+            return;
+        }
+
+        if (mPlNextSourceState == NEXT_SOURCE_STATE_PREPARED) {
+            // Switch to next source only when it's in prepared state.
+            mPlCurrentIndex = mPlNextIndex;
+            mPlNextIndex = getNextIndex_l();
+            mPlNextSourceState = NEXT_SOURCE_STATE_INIT;
+            mPlNextSourcePlayPending = false;
+
+            long srcId = mPlaylist.get(mPlCurrentIndex).getId();
+            try {
+                nativePlayNextDataSource(srcId);
+            } catch (Exception e) {
+                Message msg2 = mEventHandler.obtainMessage(
+                        MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, MEDIA_ERROR_UNSUPPORTED, null);
+                mEventHandler.post(new Runnable() {
+                    @Override
+                    public void run() {
+                        mEventHandler.handleMessage(msg2, srcId);
+                    }
+                });
+            }
+
+            // Wait for MEDIA2_INFO_STARTED_AS_NEXT to prepare next source.
+        } else {
+            if (mPlNextSourceState == NEXT_SOURCE_STATE_INIT) {
+                prepareNextDataSource_l();
+            }
+            mPlNextSourcePlayPending = true;
+        }
+    }
+
+    private native void nativePlayNextDataSource(long srcId);
 
     /**
      * Prepares the player for playback, asynchronously.
      *
      * After setting the datasource and the display surface, you need to either
-     * call prepare() or prepareAsync(). For streams, you should call prepareAsync(),
+     * call prepareAsync(). For streams, you should call prepareAsync(),
      * which returns immediately, rather than blocking until enough data has been
      * buffered.
      *
@@ -1417,6 +1488,7 @@
     /*
      * Call BEFORE adding a routing callback handler or AFTER removing a routing callback handler.
      */
+    @GuardedBy("mRoutingChangeListeners")
     private void enableNativeRoutingCallbacksLocked(boolean enabled) {
         if (mRoutingChangeListeners.size() == 0) {
             native_enableDeviceCallback(enabled);
@@ -1938,7 +2010,7 @@
     /**
      * Resets the MediaPlayer2 to its uninitialized state. After calling
      * this method, you will have to initialize it again by setting the
-     * data source and calling prepare().
+     * data source and calling prepareAsync().
      */
     @Override
     public void reset() {
@@ -2013,7 +2085,7 @@
     /**
      * Sets the audio attributes for this MediaPlayer2.
      * See {@link AudioAttributes} for how to build and configure an instance of this class.
-     * You must call this method before {@link #prepare()} or {@link #prepareAsync()} in order
+     * You must call this method before {@link #prepareAsync()} in order
      * for the audio attributes to become effective thereafter.
      * @param attributes a non-null set of audio attributes
      * @throws IllegalArgumentException if the attributes are null or invalid.
@@ -2188,6 +2260,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.
      *
@@ -3072,6 +3151,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;
@@ -3091,10 +3174,23 @@
                     sendMessage(msg2);
                 }
 
+                synchronized (mPlLock) {
+                    Log.i(TAG, "MEDIA_PREPARED: srcId=" + srcId
+                            + ", currentIndex=" + mPlCurrentIndex + ", nextIndex=" + mPlNextIndex);
+                    if (mPlCurrentIndex >= 0 && srcId == mPlaylist.get(mPlCurrentIndex).getId()) {
+                        prepareNextDataSource_l();
+                    } else if (mPlNextIndex >= 0 && srcId == mPlaylist.get(mPlNextIndex).getId()) {
+                        mPlNextSourceState = NEXT_SOURCE_STATE_PREPARED;
+                        if (mPlNextSourcePlayPending) {
+                            playNextDataSource_l();
+                        }
+                    }
+                }
+
                 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;
@@ -3129,10 +3225,18 @@
                 return;
 
             case MEDIA_PLAYBACK_COMPLETE:
+                synchronized (mPlLock) {
+                    if (mPlCurrentIndex >= 0 && srcId == mPlaylist.get(mPlCurrentIndex).getId()) {
+                        Log.i(TAG, "MEDIA_PLAYBACK_COMPLETE: srcId=" + srcId
+                                + ", currentIndex=" + mPlCurrentIndex + ", nextIndex=" + mPlNextIndex);
+                        playNextDataSource_l();
+                    }
+                }
+
                 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);
@@ -3162,7 +3266,7 @@
                 synchronized (mEventCbLock) {
                     for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) {
                         cb.first.execute(() -> cb.second.onBufferingUpdate(
-                                mMediaPlayer, 0, percent));
+                                mMediaPlayer, srcId, percent));
                     }
                 }
                 return;
@@ -3171,7 +3275,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
@@ -3191,7 +3295,7 @@
                 synchronized (mEventCbLock) {
                     for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) {
                         cb.first.execute(() -> cb.second.onVideoSizeChanged(
-                                mMediaPlayer, 0, width, height));
+                                mMediaPlayer, srcId, width, height));
                     }
                 }
                 return;
@@ -3201,9 +3305,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);
@@ -3211,6 +3315,12 @@
 
             case MEDIA_INFO:
                 switch (msg.arg1) {
+                    case MEDIA_INFO_STARTED_AS_NEXT:
+                        if (mPlCurrentIndex >= 0 && srcId == mPlaylist.get(mPlCurrentIndex).getId()) {
+                            prepareNextDataSource_l();
+                        }
+                        break;
+
                     case MEDIA_INFO_VIDEO_TRACK_LAGGING:
                         Log.i(TAG, "Info (" + msg.arg1 + "," + msg.arg2 + ")");
                         break;
@@ -3246,7 +3356,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.
@@ -3271,7 +3381,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;
@@ -3302,7 +3412,7 @@
                 synchronized (mEventCbLock) {
                     for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) {
                         cb.first.execute(() -> cb.second.onTimedMetaDataAvailable(
-                                mMediaPlayer, 0, data));
+                                mMediaPlayer, srcId, data));
                     }
                 }
                 return;
@@ -3334,7 +3444,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();
@@ -3387,7 +3497,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);
+                }
+            });
         }
     }
 
@@ -3513,7 +3629,7 @@
     /**
      * Retrieves the DRM Info associated with the current source
      *
-     * @throws IllegalStateException if called before prepare()
+     * @throws IllegalStateException if called before prepareAsync()
      */
     @Override
     public DrmInfo getDrmInfo() {
@@ -3564,7 +3680,7 @@
      * @param uuid The UUID of the crypto scheme. If not known beforehand, it can be retrieved
      * from the source through {@code getDrmInfo} or registering a {@code onDrmInfoListener}.
      *
-     * @throws IllegalStateException              if called before prepare(), or the DRM was
+     * @throws IllegalStateException              if called before prepareAsync(), or the DRM was
      *                                            prepared already
      * @throws UnsupportedSchemeException         if the crypto scheme is not supported
      * @throws ResourceBusyException              if required DRM resources are in use
@@ -4216,6 +4332,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;
 
@@ -4489,7 +4664,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/MediaRecorder.java b/media/java/android/media/MediaRecorder.java
index 7d38083..394e6a5 100644
--- a/media/java/android/media/MediaRecorder.java
+++ b/media/java/android/media/MediaRecorder.java
@@ -17,6 +17,7 @@
 package android.media;
 
 import android.annotation.NonNull;
+import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.app.ActivityThread;
 import android.hardware.Camera;
@@ -278,6 +279,7 @@
          * third-party applications.
          * </p>
          */
+        @RequiresPermission(android.Manifest.permission.CAPTURE_AUDIO_OUTPUT)
         public static final int REMOTE_SUBMIX = 8;
 
         /** Microphone audio source tuned for unprocessed (raw) sound if available, behaves like
@@ -303,6 +305,7 @@
          * @hide
          */
         @SystemApi
+        @RequiresPermission(android.Manifest.permission.CAPTURE_AUDIO_HOTWORD)
         public static final int HOTWORD = 1999;
     }
 
@@ -1366,6 +1369,7 @@
     /*
      * Call BEFORE adding a routing callback handler or AFTER removing a routing callback handler.
      */
+    @GuardedBy("mRoutingChangeListeners")
     private void enableNativeRoutingCallbacksLocked(boolean enabled) {
         if (mRoutingChangeListeners.size() == 0) {
             native_enableDeviceCallback(enabled);
diff --git a/media/java/android/media/VolumePolicy.java b/media/java/android/media/VolumePolicy.java
index bbcce82..bd6667f 100644
--- a/media/java/android/media/VolumePolicy.java
+++ b/media/java/android/media/VolumePolicy.java
@@ -23,7 +23,7 @@
 
 /** @hide */
 public final class VolumePolicy implements Parcelable {
-    public static final VolumePolicy DEFAULT = new VolumePolicy(false, false, true, 400);
+    public static final VolumePolicy DEFAULT = new VolumePolicy(false, false, false, 400);
 
     /**
      * Accessibility volume policy where the STREAM_MUSIC volume (i.e. media volume) affects
diff --git a/media/java/android/media/audiopolicy/AudioPolicy.java b/media/java/android/media/audiopolicy/AudioPolicy.java
index 2190635..343bbda 100644
--- a/media/java/android/media/audiopolicy/AudioPolicy.java
+++ b/media/java/android/media/audiopolicy/AudioPolicy.java
@@ -400,6 +400,7 @@
                 new AudioAttributes.Builder()
                         .setInternalCapturePreset(MediaRecorder.AudioSource.REMOTE_SUBMIX)
                         .addTag(addressForTag(mix))
+                        .addTag(AudioRecord.SUBMIX_FIXED_VOLUME)
                         .build(),
                 mixFormat,
                 AudioRecord.getMinBufferSize(mix.getFormat().getSampleRate(),
diff --git a/media/java/android/media/midi/MidiManager.java b/media/java/android/media/midi/MidiManager.java
index a015732..dee94c68 100644
--- a/media/java/android/media/midi/MidiManager.java
+++ b/media/java/android/media/midi/MidiManager.java
@@ -16,9 +16,11 @@
 
 package android.media.midi;
 
+import android.annotation.RequiresFeature;
 import android.annotation.SystemService;
 import android.bluetooth.BluetoothDevice;
 import android.content.Context;
+import android.content.pm.PackageManager;
 import android.os.Binder;
 import android.os.IBinder;
 import android.os.Bundle;
@@ -32,6 +34,7 @@
  * This class is the public application interface to the MIDI service.
  */
 @SystemService(Context.MIDI_SERVICE)
+@RequiresFeature(PackageManager.FEATURE_MIDI)
 public final class MidiManager {
     private static final String TAG = "MidiManager";
 
diff --git a/media/java/android/media/session/MediaSession.java b/media/java/android/media/session/MediaSession.java
index b8184a0..b8d01c4 100644
--- a/media/java/android/media/session/MediaSession.java
+++ b/media/java/android/media/session/MediaSession.java
@@ -119,7 +119,8 @@
     private final ISession mBinder;
     private final CallbackStub mCbStub;
 
-    private CallbackMessageHandler mCallbackHandler;
+    // Do not change the name of mCallback. Support lib accesses this by using reflection.
+    private CallbackMessageHandler mCallback;
     private VolumeProvider mVolumeProvider;
     private PlaybackState mPlaybackState;
 
@@ -194,13 +195,13 @@
      */
     public void setCallback(@Nullable Callback callback, @Nullable Handler handler) {
         synchronized (mLock) {
-            if (mCallbackHandler != null) {
+            if (mCallback != null) {
                 // We're updating the callback, clear the session from the old one.
-                mCallbackHandler.mCallback.mSession = null;
-                mCallbackHandler.removeCallbacksAndMessages(null);
+                mCallback.mCallback.mSession = null;
+                mCallback.removeCallbacksAndMessages(null);
             }
             if (callback == null) {
-                mCallbackHandler = null;
+                mCallback = null;
                 return;
             }
             if (handler == null) {
@@ -209,7 +210,7 @@
             callback.mSession = this;
             CallbackMessageHandler msgHandler = new CallbackMessageHandler(handler.getLooper(),
                     callback);
-            mCallbackHandler = msgHandler;
+            mCallback = msgHandler;
         }
     }
 
@@ -634,8 +635,8 @@
 
     private void postToCallback(int what, Object obj, Bundle extras) {
         synchronized (mLock) {
-            if (mCallbackHandler != null) {
-                mCallbackHandler.post(what, obj, extras);
+            if (mCallback != null) {
+                mCallback.post(what, obj, extras);
             }
         }
     }
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/java/android/media/update/MediaController2Provider.java b/media/java/android/media/update/MediaController2Provider.java
index 71bc64a..c492d307 100644
--- a/media/java/android/media/update/MediaController2Provider.java
+++ b/media/java/android/media/update/MediaController2Provider.java
@@ -18,6 +18,7 @@
 
 import android.annotation.SystemApi;
 import android.app.PendingIntent;
+import android.media.AudioAttributes;
 import android.media.MediaController2.PlaybackInfo;
 import android.media.MediaItem2;
 import android.media.MediaSession2.Command;
@@ -65,4 +66,12 @@
     PlaylistParams getPlaylistParams_impl();
     void setPlaylistParams_impl(PlaylistParams params);
     PlaybackState2 getPlaybackState_impl();
+
+    interface PlaybackInfoProvider {
+        int getPlaybackType_impl();
+        AudioAttributes getAudioAttributes_impl();
+        int getControlType_impl();
+        int getMaxVolume_impl();
+        int getCurrentVolume_impl();
+    }
 }
diff --git a/media/java/android/media/update/PlaybackInfoProvider.java b/media/java/android/media/update/PlaybackInfoProvider.java
deleted file mode 100644
index 36eb58a..0000000
--- a/media/java/android/media/update/PlaybackInfoProvider.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media.update;
-
-import android.media.AudioAttributes;
-
-/**
- * @hide
- */
-// TODO(jaewan): @SystemApi
-public interface PlaybackInfoProvider {
-    int getPlaybackType_impl();
-    AudioAttributes getAudioAttributes_impl();
-    int getControlType_impl();
-    int getMaxVolume_impl();
-    int getCurrentVolume_impl();
-}
diff --git a/media/jni/Android.bp b/media/jni/Android.bp
index 1dde16c..787aa62 100644
--- a/media/jni/Android.bp
+++ b/media/jni/Android.bp
@@ -130,11 +130,11 @@
         "libdexfile",
         "liblzma",
         "libmedia_helper",
-        "libmedia_player2",
         "libmedia_player2_util",
         "libmediadrm",
         "libmediaextractor",
         "libmediametrics",
+        "libmediaplayer2",
         "libmediautils",
         "libnativehelper",
         "libnetd_client",
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 27eaed0..5a0081a 100644
--- a/media/jni/android_media_MediaPlayer2.cpp
+++ b/media/jni/android_media_MediaPlayer2.cpp
@@ -21,15 +21,15 @@
 
 #include <sys/stat.h>
 
-#include <media/mediaplayer2.h>
 #include <media/AudioResamplerPublic.h>
 #include <media/DataSourceDesc.h>
 #include <media/MediaHTTPService.h>
-#include <media/MediaPlayer2Interface.h>
 #include <media/MediaAnalyticsItem.h>
 #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>
 #include <limits.h>
@@ -155,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
@@ -188,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) {
@@ -197,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.");
@@ -244,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,9 +273,9 @@
 }
 
 static void
-android_media_MediaPlayer2_setDataSourceAndHeaders(
-        JNIEnv *env, jobject thiz, jobject httpServiceObj, jstring path,
-        jobjectArray keys, jobjectArray values) {
+android_media_MediaPlayer2_handleDataSourceUrl(
+        JNIEnv *env, jobject thiz, jboolean isCurrent, jlong srcId,
+        jobject httpServiceObj, jstring path, jobjectArray keys, jobjectArray values) {
 
     sp<MediaPlayer2> mp = getMediaPlayer(env, thiz);
     if (mp == NULL) {
@@ -287,16 +292,17 @@
     if (tmp == NULL) {  // Out of memory
         return;
     }
-    ALOGV("setDataSourceAndHeaders: path %s", tmp);
+    ALOGV("handleDataSourceUrl: path %s, srcId %lld", tmp, (long long)srcId);
 
     if (strncmp(tmp, "content://", 10) == 0) {
-        ALOGE("setDataSourceAndHeaders: content scheme is not supported in native code");
+        ALOGE("handleDataSourceUrl: content scheme is not supported in native code");
         jniThrowException(env, "java/io/IOException",
                           "content scheme is not supported in native code");
         return;
     }
 
     sp<DataSourceDesc> dsd = new DataSourceDesc();
+    dsd->mId = srcId;
     dsd->mType = DataSourceDesc::TYPE_URL;
     dsd->mUrl = tmp;
 
@@ -315,14 +321,20 @@
     }
     dsd->mHttpService = httpService;
 
-    process_media_player_call(
-            env, thiz, mp->setDataSource(dsd), "java/io/IOException",
-            "setDataSourceAndHeaders failed." );
+    status_t err;
+    if (isCurrent) {
+        err = mp->setDataSource(dsd);
+    } else {
+        err = mp->prepareNextDataSource(dsd);
+    }
+    process_media_player_call(env, thiz, err,
+            "java/io/IOException", "handleDataSourceUrl failed." );
 }
 
 static void
-android_media_MediaPlayer2_setDataSourceFD(
-    JNIEnv *env, jobject thiz, jobject fileDescriptor, jlong offset, jlong length)
+android_media_MediaPlayer2_handleDataSourceFD(
+    JNIEnv *env, jobject thiz, jboolean isCurrent, jlong srcId,
+    jobject fileDescriptor, jlong offset, jlong length)
 {
     sp<MediaPlayer2> mp = getMediaPlayer(env, thiz);
     if (mp == NULL ) {
@@ -335,14 +347,14 @@
         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("handleDataSourceFD: 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);
     if (ret != 0) {
-        ALOGE("setDataSourceFD: fstat(%d) failed: %d, %s", fd, ret, strerror(errno));
-        jniThrowException(env, "java/io/IOException", "setDataSourceFD failed fstat");
+        ALOGE("handleDataSourceFD: fstat(%d) failed: %d, %s", fd, ret, strerror(errno));
+        jniThrowException(env, "java/io/IOException", "handleDataSourceFD failed fstat");
         return;
     }
 
@@ -353,28 +365,36 @@
     ALOGV("st_size = %llu", static_cast<unsigned long long>(sb.st_size));
 
     if (offset >= sb.st_size) {
-        ALOGE("setDataSourceFD: offset is out of range");
+        ALOGE("handleDataSourceFD: offset is out of range");
         jniThrowException(env, "java/lang/IllegalArgumentException",
-                          "setDataSourceFD failed, offset is out of range.");
+                          "handleDataSourceFD failed, offset is out of range.");
         return;
     }
     if (offset + length > sb.st_size) {
         length = sb.st_size - offset;
-        ALOGV("setDataSourceFD: adjusted length = %lld", (long long)length);
+        ALOGV("handleDataSourceFD: adjusted length = %lld", (long long)length);
     }
 
     sp<DataSourceDesc> dsd = new DataSourceDesc();
+    dsd->mId = srcId;
     dsd->mType = DataSourceDesc::TYPE_FD;
     dsd->mFD = fd;
     dsd->mFDOffset = offset;
     dsd->mFDLength = length;
-    process_media_player_call(env, thiz, mp->setDataSource(dsd),
-                              "java/io/IOException", "setDataSourceFD failed." );
+
+    status_t err;
+    if (isCurrent) {
+        err = mp->setDataSource(dsd);
+    } else {
+        err = mp->prepareNextDataSource(dsd);
+    }
+    process_media_player_call(env, thiz, err,
+            "java/io/IOException", "handleDataSourceFD failed." );
 }
 
 static void
-android_media_MediaPlayer2_setDataSourceCallback(
-    JNIEnv *env, jobject thiz, jobject dataSource)
+android_media_MediaPlayer2_handleDataSourceCallback(
+    JNIEnv *env, jobject thiz, jboolean isCurrent, jlong srcId, jobject dataSource)
 {
     sp<MediaPlayer2> mp = getMediaPlayer(env, thiz);
     if (mp == NULL ) {
@@ -388,10 +408,18 @@
     }
     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),
-                              "java/lang/RuntimeException", "setDataSourceCallback failed." );
+
+    status_t err;
+    if (isCurrent) {
+        err = mp->setDataSource(dsd);
+    } else {
+        err = mp->prepareNextDataSource(dsd);
+    }
+    process_media_player_call(env, thiz, err,
+            "java/lang/RuntimeException", "handleDataSourceCallback failed." );
 }
 
 static sp<ANativeWindowWrapper>
@@ -495,20 +523,16 @@
 }
 
 static void
-android_media_MediaPlayer2_prepare(JNIEnv *env, jobject thiz)
+android_media_MediaPlayer2_playNextDataSource(JNIEnv *env, jobject thiz, jlong srcId)
 {
     sp<MediaPlayer2> mp = getMediaPlayer(env, thiz);
-    if (mp == NULL ) {
+    if (mp == NULL) {
         jniThrowException(env, "java/lang/IllegalStateException", NULL);
         return;
     }
 
-    // Handle the case where the display surface was set before the mp was
-    // initialized. We try again to make it stick.
-    sp<ANativeWindowWrapper> st = getVideoSurfaceTexture(env, thiz);
-    mp->setVideoSurfaceTexture(st);
-
-    process_media_player_call( env, thiz, mp->prepare(), "java/io/IOException", "Prepare failed." );
+    process_media_player_call(env, thiz, mp->playNextDataSource((int64_t)srcId),
+            "java/io/IOException", "playNextDataSource failed." );
 }
 
 static void
@@ -1013,7 +1037,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;
     }
@@ -1380,20 +1404,86 @@
 // 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;"
+        "nativeHandleDataSourceUrl",
+        "(ZJLandroid/media/Media2HTTPService;Ljava/lang/String;[Ljava/lang/String;"
         "[Ljava/lang/String;)V",
-        (void *)android_media_MediaPlayer2_setDataSourceAndHeaders
+        (void *)android_media_MediaPlayer2_handleDataSourceUrl
     },
-
-    {"_setDataSource",      "(Ljava/io/FileDescriptor;JJ)V",    (void *)android_media_MediaPlayer2_setDataSourceFD},
-    {"_setDataSource",      "(Landroid/media/Media2DataSource;)V",(void *)android_media_MediaPlayer2_setDataSourceCallback },
+    {
+        "nativeHandleDataSourceFD",
+        "(ZJLjava/io/FileDescriptor;JJ)V",
+        (void *)android_media_MediaPlayer2_handleDataSourceFD
+    },
+    {
+        "nativeHandleDataSourceCallback",
+        "(ZJLandroid/media/Media2DataSource;)V",
+        (void *)android_media_MediaPlayer2_handleDataSourceCallback
+    },
+    {"nativePlayNextDataSource", "(J)V",                        (void *)android_media_MediaPlayer2_playNextDataSource},
     {"_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},
-    {"_prepare",            "()V",                              (void *)android_media_MediaPlayer2_prepare},
     {"prepareAsync",        "()V",                              (void *)android_media_MediaPlayer2_prepareAsync},
     {"_start",              "()V",                              (void *)android_media_MediaPlayer2_start},
     {"_stop",               "()V",                              (void *)android_media_MediaPlayer2_stop},
@@ -1436,6 +1526,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/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/Camera2RecordingTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/Camera2RecordingTest.java
index 5566b4e..ddb05f0 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/Camera2RecordingTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/Camera2RecordingTest.java
@@ -659,6 +659,10 @@
                 updatePreviewSurfaceWithVideo(videoSz, profile.videoFrameRate);
 
                 prepareVideoSnapshot(videoSnapshotRequestBuilder, imageListener);
+                Range<Integer> fpsRange = Range.create(profile.videoFrameRate,
+                        profile.videoFrameRate);
+                videoSnapshotRequestBuilder.set(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE,
+                        fpsRange);
                 CaptureRequest request = videoSnapshotRequestBuilder.build();
 
                 // Start recording
diff --git a/native/android/OWNERS b/native/android/OWNERS
new file mode 100644
index 0000000..11d4be4
--- /dev/null
+++ b/native/android/OWNERS
@@ -0,0 +1,11 @@
+set noparent
+
+per-file libandroid_net.map.txt=ek@google.com
+per-file libandroid_net.map.txt=jchalard@google.com
+per-file libandroid_net.map.txt=lorenzo@google.com
+per-file libandroid_net.map.txt=satk@google.com
+
+per-file net.c=ek@google.com
+per-file net.c=jchalard@google.com
+per-file net.c=lorenzo@google.com
+per-file net.c=satk@google.com
diff --git a/packages/CarrierDefaultApp/OWNERS b/packages/CarrierDefaultApp/OWNERS
new file mode 100644
index 0000000..7057ce6
--- /dev/null
+++ b/packages/CarrierDefaultApp/OWNERS
@@ -0,0 +1,12 @@
+tgunn@google.com
+breadley@google.com
+hallliu@google.com
+rgreenwalt@google.com
+mpq@google.com
+amitmahajan@google.com
+fionaxu@google.com
+jackyu@google.com
+jminjie@google.com
+satk@google.com
+shuoq@google.com
+refuhoo@google.com
\ No newline at end of file
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/DefaultContainerService/AndroidManifest.xml b/packages/DefaultContainerService/AndroidManifest.xml
index e399fb1..9f54652 100644
--- a/packages/DefaultContainerService/AndroidManifest.xml
+++ b/packages/DefaultContainerService/AndroidManifest.xml
@@ -6,9 +6,6 @@
     <uses-permission android:name="android.permission.ASEC_DESTROY"/>
     <uses-permission android:name="android.permission.ASEC_MOUNT_UNMOUNT"/>
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
-    <!-- Used to improve MeasureUtils performance on emulated storage, and to
-         view storage for all users -->
-    <uses-permission android:name="android.permission.WRITE_MEDIA_STORAGE" />
     <uses-permission android:name="android.permission.ACCESS_CACHE_FILESYSTEM" />
     <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
 
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
index 44f68ec..d73a5d7 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
@@ -3117,6 +3117,8 @@
 
         private final Consumer<String> mCallback;
 
+        private boolean mIsTransformationStarted;
+
         public DocumentTransformer(Context context, PrintJobInfo printJob,
                 MutexFileProvider fileProvider, PrintAttributes attributes,
                 Consumer<String> callback) {
@@ -3144,29 +3146,35 @@
 
         @Override
         public void onServiceConnected(ComponentName name, IBinder service) {
-            final IPdfEditor editor = IPdfEditor.Stub.asInterface(service);
-            new AsyncTask<Void, Void, String>() {
-                @Override
-                protected String doInBackground(Void... params) {
-                    // It's OK to access the data members as they are
-                    // final and this code is the last one to touch
-                    // them as shredding is the very last step, so the
-                    // UI is not interactive at this point.
-                    try {
-                        doTransform(editor);
-                        updatePrintJob();
-                        return null;
-                    } catch (IOException | RemoteException | IllegalStateException e) {
-                        return e.toString();
+            // We might get several onServiceConnected if the service crashes and restarts.
+            // mIsTransformationStarted makes sure that we only try once.
+            if (!mIsTransformationStarted) {
+                final IPdfEditor editor = IPdfEditor.Stub.asInterface(service);
+                new AsyncTask<Void, Void, String>() {
+                    @Override
+                    protected String doInBackground(Void... params) {
+                        // It's OK to access the data members as they are
+                        // final and this code is the last one to touch
+                        // them as shredding is the very last step, so the
+                        // UI is not interactive at this point.
+                        try {
+                            doTransform(editor);
+                            updatePrintJob();
+                            return null;
+                        } catch (IOException | RemoteException | IllegalStateException e) {
+                            return e.toString();
+                        }
                     }
-                }
 
-                @Override
-                protected void onPostExecute(String error) {
-                    mContext.unbindService(DocumentTransformer.this);
-                    mCallback.accept(error);
-                }
-            }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+                    @Override
+                    protected void onPostExecute(String error) {
+                        mContext.unbindService(DocumentTransformer.this);
+                        mCallback.accept(error);
+                    }
+                }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+
+                mIsTransformationStarted = true;
+            }
         }
 
         @Override
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/SelectPrinterActivity.java b/packages/PrintSpooler/src/com/android/printspooler/ui/SelectPrinterActivity.java
index 7c2e55f..cf73aac 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/SelectPrinterActivity.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/SelectPrinterActivity.java
@@ -285,6 +285,11 @@
             final int position = ((AdapterContextMenuInfo) menuInfo).position;
             PrinterInfo printer = (PrinterInfo) mListView.getAdapter().getItem(position);
 
+            // Printer is null if this is a context menu for the "add printer" entry
+            if (printer == null) {
+                return;
+            }
+
             menu.setHeaderTitle(printer.getName());
 
             // Add the select menu item if applicable.
diff --git a/packages/PrintSpooler/tests/outofprocess/AndroidTest.xml b/packages/PrintSpooler/tests/outofprocess/AndroidTest.xml
index 72be35b..15dd64b 100644
--- a/packages/PrintSpooler/tests/outofprocess/AndroidTest.xml
+++ b/packages/PrintSpooler/tests/outofprocess/AndroidTest.xml
@@ -20,6 +20,8 @@
 
     <option name="test-suite-tag" value="apct" />
     <option name="test-tag" value="PrintSpoolerOutOfProcessTests" />
+    <option name="config-descriptor:metadata" key="component" value="print" />
+
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
         <option name="package" value="com.android.printspooler.outofprocess.tests" />
         <option name="runner" value="android.support.test.runner.AndroidJUnitRunner" />
diff --git a/packages/SettingsLib/res/drawable/ic_bt_hearing_aid.xml b/packages/SettingsLib/res/drawable/ic_bt_hearing_aid.xml
new file mode 100644
index 0000000..e14c99b
--- /dev/null
+++ b/packages/SettingsLib/res/drawable/ic_bt_hearing_aid.xml
@@ -0,0 +1,24 @@
+<!--
+     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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M17,20c-0.29,0 -0.56,-0.06 -0.76,-0.15 -0.71,-0.37 -1.21,-0.88 -1.71,-2.38 -0.51,-1.56 -1.47,-2.29 -2.39,-3 -0.79,-0.61 -1.61,-1.24 -2.32,-2.53C9.29,10.98 9,9.93 9,9c0,-2.8 2.2,-5 5,-5s5,2.2 5,5h2c0,-3.93 -3.07,-7 -7,-7S7,5.07 7,9c0,1.26 0.38,2.65 1.07,3.9 0.91,1.65 1.98,2.48 2.85,3.15 0.81,0.62 1.39,1.07 1.71,2.05 0.6,1.82 1.37,2.84 2.73,3.55 0.51,0.23 1.07,0.35 1.64,0.35 2.21,0 4,-1.79 4,-4h-2c0,1.1 -0.9,2 -2,2zM7.64,2.64L6.22,1.22C4.23,3.21 3,5.96 3,9s1.23,5.79 3.22,7.78l1.41,-1.41C6.01,13.74 5,11.49 5,9s1.01,-4.74 2.64,-6.36zM11.5,9c0,1.38 1.12,2.5 2.5,2.5s2.5,-1.12 2.5,-2.5 -1.12,-2.5 -2.5,-2.5 -2.5,1.12 -2.5,2.5z"/>
+</vector>
diff --git a/packages/SettingsLib/res/layout/zen_mode_turn_on_dialog_container.xml b/packages/SettingsLib/res/layout/zen_mode_turn_on_dialog_container.xml
index ac56a2d..bc330c7 100644
--- a/packages/SettingsLib/res/layout/zen_mode_turn_on_dialog_container.xml
+++ b/packages/SettingsLib/res/layout/zen_mode_turn_on_dialog_container.xml
@@ -22,25 +22,40 @@
             android:fillViewport ="true"
             android:orientation="vertical">
 
-    <com.android.settingslib.notification.ZenRadioLayout
-        xmlns:android="http://schemas.android.com/apk/res/android"
-        android:id="@+id/zen_conditions"
+    <LinearLayout
+        android:id="@+id/dialog_container"
         android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_marginTop="8dp"
-        android:layout_marginEnd="4dp"
-        android:layout_marginStart="4dp"
-        android:paddingBottom="4dp"
-        android:orientation="horizontal">
-        <RadioGroup
-            android:id="@+id/zen_radio_buttons"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content" />
-        <LinearLayout
-            android:id="@+id/zen_radio_buttons_content"
-            android:layout_width="fill_parent"
-            android:layout_height="fill_parent"
-            android:orientation="vertical"/>
-    </com.android.settingslib.notification.ZenRadioLayout>
+        android:layout_height="match_parent"
+        android:orientation="vertical">
+
+        <com.android.settingslib.notification.ZenRadioLayout
+            android:id="@+id/zen_conditions"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="8dp"
+            android:layout_marginEnd="4dp"
+            android:layout_marginStart="4dp"
+            android:paddingBottom="4dp"
+            android:orientation="horizontal">
+            <RadioGroup
+                android:id="@+id/zen_radio_buttons"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content" />
+            <LinearLayout
+                android:id="@+id/zen_radio_buttons_content"
+                android:layout_width="fill_parent"
+                android:layout_height="fill_parent"
+                android:orientation="vertical"/>
+        </com.android.settingslib.notification.ZenRadioLayout>
+
+        <TextView
+            android:id="@+id/zen_alarm_warning"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginStart="18dp"
+            android:layout_marginEnd="16dp"
+            android:textDirection="locale"
+            android:textColor="?android:attr/colorError"/>
+    </LinearLayout>
 
 </ScrollView>
\ No newline at end of file
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index 278b07d..a2329db 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -53,16 +53,16 @@
     <string name="bluetooth_disconnected" msgid="6557104142667339895">"Ontkoppel"</string>
     <string name="bluetooth_disconnecting" msgid="8913264760027764974">"Ontkoppel tans…"</string>
     <string name="bluetooth_connecting" msgid="8555009514614320497">"Verbind tans…"</string>
-    <string name="bluetooth_connected" msgid="6038755206916626419">"Gekoppel"</string>
+    <string name="bluetooth_connected" msgid="5427152882755735944">"Gekoppel<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
     <string name="bluetooth_pairing" msgid="1426882272690346242">"Verbind tans…"</string>
-    <string name="bluetooth_connected_no_headset" msgid="2866994875046035609">"Gekoppel (geen foon nie)"</string>
-    <string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Gekoppel (geen media nie)"</string>
-    <string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Gekoppel (geen boodskaptoegang nie)"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Gekoppel (geen foon of media nie)"</string>
-    <string name="bluetooth_connected_battery_level" msgid="7049181126136692368">"Gekoppel, battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_headset_battery_level" msgid="5504193961248406027">"Gekoppel (geen foon nie), battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="4751724026365870779">"Gekoppel (geen media nie), battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1549265779323455261">"Gekoppel (geen foon en media nie), battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset" msgid="616068069034994802">"Gekoppel (geen foon nie)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp" msgid="3736431800395923868">"Gekoppel (geen media nie)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_map" msgid="3200033913678466453">"Gekoppel (geen boodskaptoegang nie)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2047403011284187056">"Gekoppel (geen foon of media nie)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_battery_level" msgid="5162924691231307748">"Gekoppel, battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"Gekoppel (geen foon nie), battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"Gekoppel (geen media nie), battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"Gekoppel (geen foon of media nie), battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Media-oudio"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"Foonoproepe"</string>
     <string name="bluetooth_profile_opp" msgid="9168139293654233697">"Lêeroordrag"</string>
@@ -75,6 +75,10 @@
     <string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM-toegang"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD-oudio: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD oudio"</string>
+    <!-- no translation found for bluetooth_profile_hearing_aid (7999237886427812595) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (7188282786730266159) -->
+    <skip />
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Gekoppel aan media-oudio"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Gekoppel aan foonoudio"</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Gekoppel aan lêeroordragbediener"</string>
@@ -91,6 +95,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Gebruik vir foonoudio"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Gebruik vir lêeroordrag"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Gebruik vir invoer"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (908775281788309484) -->
+    <skip />
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Bind saam"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"BIND SAAM"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Kanselleer"</string>
@@ -327,9 +333,10 @@
     <item msgid="8280754435979370728">"Natuurlike kleure soos dit vir die oë lyk"</item>
     <item msgid="5363960654009010371">"Kleure vir digitale inhoud geoptimeer"</item>
   </string-array>
-    <string name="inactive_apps_title" msgid="1317817863508274533">"Onaktiewe programme"</string>
+    <string name="inactive_apps_title" msgid="9042996804461901648">"Bystandprogramme"</string>
     <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"Onaktief. Tik om te wissel."</string>
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"Aktief. Tik om te wissel."</string>
+    <string name="standby_bucket_summary" msgid="6567835350910684727">"Programbystandstatus:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="runningservices_settings_title" msgid="8097287939865165213">"Lopende dienste"</string>
     <string name="runningservices_settings_summary" msgid="854608995821032748">"Sien en beheer dienste wat tans loop"</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView-implementering"</string>
@@ -351,16 +358,24 @@
     <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Kleurregstelling"</string>
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Hierdie kenmerk is eksperimenteel en kan werkverrigting beïnvloed."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Geneutraliseer deur <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only" msgid="845431008899029842">"Omtrent <xliff:g id="TIME">^1</xliff:g> oor"</string>
-    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Ongeveer <xliff:g id="TIME">^1</xliff:g> oor gegrond op jou gebruik"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">^1</xliff:g> oor tot vol gelaai"</string>
-    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">^1</xliff:g> oor"</string>
-    <string name="power_remaining_duration_only_short_enhanced" msgid="7450425624026394823">"<xliff:g id="TIME">^1</xliff:g> oor gegrond op jou gebruik"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">^1</xliff:g> – omtrent <xliff:g id="TIME">^2</xliff:g> oor"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">^1</xliff:g> – ongeveer <xliff:g id="TIME">^2</xliff:g> oor gegrond op jou gebruik"</string>
-    <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> – <xliff:g id="TIME">^2</xliff:g> oor"</string>
+    <string name="power_remaining_duration_only" msgid="845431008899029842">"Omtrent <xliff:g id="TIME">%1$s</xliff:g> oor"</string>
+    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Ongeveer <xliff:g id="TIME">%1$s</xliff:g> oor gegrond op jou gebruik"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> oor tot vol gelaai"</string>
+    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">%1$s</xliff:g> oor"</string>
+    <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Minder as <xliff:g id="THRESHOLD">%1$s</xliff:g> oor"</string>
+    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> – minder as <xliff:g id="THRESHOLD">%2$s</xliff:g> oor"</string>
+    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g>meer as <xliff:g id="TIME_REMAINING">%2$s</xliff:g> oor"</string>
+    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"meer as <xliff:g id="TIME_REMAINING">%1$s</xliff:g> oor"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"foon kan binnekort afgaan"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"tablet kan binnekort afgaan"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"toestel kan binnekort afgaan"</string>
+    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> – omtrent <xliff:g id="TIME">%2$s</xliff:g> oor"</string>
+    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> – ongeveer <xliff:g id="TIME">%2$s</xliff:g> oor gegrond op jou gebruik"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> – foon kan binnekort afgaan"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> – tablet kan binnekort afgaan"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> – toestel kan binnekort afgaan"</string>
     <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> tot vol gelaai"</string>
+    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> tot vol gelaai"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Onbekend"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Laai"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"laai tans"</string>
@@ -414,4 +429,8 @@
     <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"Nooit"</string>
     <string name="zen_interruption_level_priority" msgid="2078370238113347720">"Net prioriteit"</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>
+    <string name="zen_alarm_warning_indef" msgid="3007988140196673193">"Jy sal nie jou volgende wekker om <xliff:g id="WHEN">%1$s</xliff:g> hoor nie tensy jy dit voor die tyd afskakel"</string>
+    <string name="zen_alarm_warning" msgid="6236690803924413088">"Jy sal nie jou volgende wekker om <xliff:g id="WHEN">%1$s</xliff:g> hoor nie"</string>
+    <string name="alarm_template" msgid="4996153414057676512">"om <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template_far" msgid="3779172822607461675">"op <xliff:g id="WHEN">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml
index 466c01b..f2c05bf 100644
--- a/packages/SettingsLib/res/values-am/strings.xml
+++ b/packages/SettingsLib/res/values-am/strings.xml
@@ -53,16 +53,16 @@
     <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>
+    <string name="bluetooth_connected" msgid="5427152882755735944">"ተገናኝቷል<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
     <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>
+    <string name="bluetooth_connected_no_headset" msgid="616068069034994802">"ተገናኝቷል (ምንም ስልክ የለም)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp" msgid="3736431800395923868">"ተገናኝቷል (ምንም ማህደረ መረጃ የለም)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_map" msgid="3200033913678466453">"ተገናኝቷል (ምንም የመልዕክት መዳረሻ)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2047403011284187056">"ተገናኝቷል (ምንም ስልክ ወይም ማህደረ መረጃ የለም)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_battery_level" msgid="5162924691231307748">"ተገናኝቷል፣ ባትሪ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"ተገናኝቷል (ምንም ስልክ የለም)፣ ባትሪ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"ተገናኝቷል (ምንም ማህደረ መረጃ የለም)፣ ባትሪ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"ተገናኝቷል (ምንም ስልክ ወይም ማህደረ መረጃ የለም)፣ ባትሪ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"የማህደረ መረጃ ኦዲዮ"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"የስልክ ጥሪዎች"</string>
     <string name="bluetooth_profile_opp" msgid="9168139293654233697">"ፋይል ማስተላለፍ"</string>
@@ -75,6 +75,10 @@
     <string name="bluetooth_profile_sap" msgid="5764222021851283125">"የሲም መዳረሻ"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"ኤችዲ ኦዲዮ፦ <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"ኤችዲ ኦዲዮ"</string>
+    <!-- no translation found for bluetooth_profile_hearing_aid (7999237886427812595) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (7188282786730266159) -->
+    <skip />
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"ወደ ማህደረ  መረጃ  አውዲዮ ተያይዟል"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"ወደ ስልክ አውዲዮ ተያይዟል"</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"ወደ ፋይል ዝውውር አገልጋይ ተያይዟል"</string>
@@ -91,6 +95,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"ለስልክ ድምፅ ተጠቀም"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"ለፋይል ዝውውር ተጠቀም"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"ለውፅአት ተጠቀም"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (908775281788309484) -->
+    <skip />
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"አጣምር"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"አጣምር"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"ይቅር"</string>
@@ -327,9 +333,10 @@
     <item msgid="8280754435979370728">"ልክ በዓይን እንደሚታዩት የተፈጥሮ ቀለማት"</item>
     <item msgid="5363960654009010371">"ለዲጂታል ይዘት የላቁ ቀለማት"</item>
   </string-array>
-    <string name="inactive_apps_title" msgid="1317817863508274533">"ንቁ ያልሆኑ መተግበሪያዎች"</string>
+    <string name="inactive_apps_title" msgid="9042996804461901648">"ዝግጁ መተግበሪያዎች"</string>
     <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"ቦዝኗል። ለመቀያየር ነካ ያድርጉ።"</string>
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"ገቢር። ለመቀያየር ነካ ያድርጉ።"</string>
+    <string name="standby_bucket_summary" msgid="6567835350910684727">"የመተግበሪያ ዝግጁ የመሆን ሁኔታ፦<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <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 +358,24 @@
     <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>
+    <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"ከ<xliff:g id="THRESHOLD">%1$s</xliff:g> ያነሰ ይቀራል"</string>
+    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> - ከ<xliff:g id="THRESHOLD">%2$s</xliff:g> በታች ይቀራል"</string>
+    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g>ከ<xliff:g id="TIME_REMAINING">%2$s</xliff:g> የበለጠ ይቀራል"</string>
+    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"ከ<xliff:g id="TIME_REMAINING">%1$s</xliff:g> በላይ ይቀራል"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"ስልኩ በቅርቡ ሊዘጋ ይችላል"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"ጡባዊ በቅርቡ ሊዘጋ ይችል ይሆናል"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"መሣሪያ በቅርቡ ሊዘጋ ይችል ይሆናል"</string>
+    <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>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> - ስልክ በቅርቡ ሊዘጋ ይችል ይሆናል"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> - ጡባዊ በቅርቡ ሊዘጋ ይችል ይሆናል"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> - መሣሪያ በቅርቡ ሊዘጋ ይችል ይሆናል"</string>
     <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 +429,8 @@
     <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>
+    <string name="zen_alarm_warning_indef" msgid="3007988140196673193">"ከዚያ በፊት ይህንን ካላጠፉት በቀር የእርስዎን ቀጣይ ማንቂያ <xliff:g id="WHEN">%1$s</xliff:g> አይሰሙም"</string>
+    <string name="zen_alarm_warning" msgid="6236690803924413088">"የእርስዎን ቀጣይ ማንቂያ <xliff:g id="WHEN">%1$s</xliff:g> አይሰሙም"</string>
+    <string name="alarm_template" msgid="4996153414057676512">"በ<xliff:g id="WHEN">%1$s</xliff:g> ላይ"</string>
+    <string name="alarm_template_far" msgid="3779172822607461675">"በ<xliff:g id="WHEN">%1$s</xliff:g> ላይ"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ar/arrays.xml b/packages/SettingsLib/res/values-ar/arrays.xml
index 603dcc8..741560a 100644
--- a/packages/SettingsLib/res/values-ar/arrays.xml
+++ b/packages/SettingsLib/res/values-ar/arrays.xml
@@ -234,10 +234,6 @@
     <item msgid="7688197031296835369">"عرض مناطق تجاوز الحد"</item>
     <item msgid="2290859360633824369">"عرض مناطق العجز في رؤية اللونين الأخضر والأحمر"</item>
   </string-array>
-  <string-array name="debug_hw_renderer_entries">
-    <item msgid="2578620445459945681">"‏OpenGL (الافتراضي)"</item>
-    <item msgid="2839130076198120436">"‏OpenGL ‏(Skia)"</item>
-  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"الحد القياسي"</item>
     <item msgid="4071574792028999443">"ليست هناك عمليات بالخلفية"</item>
diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml
index 3149af0..6acc8e9 100644
--- a/packages/SettingsLib/res/values-ar/strings.xml
+++ b/packages/SettingsLib/res/values-ar/strings.xml
@@ -53,16 +53,16 @@
     <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>
+    <string name="bluetooth_connected" msgid="5427152882755735944">"الجهاز متصل<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
     <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>
+    <string name="bluetooth_connected_no_headset" msgid="616068069034994802">"الجهاز متصل (من دون هاتف)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp" msgid="3736431800395923868">"الجهاز متصل (من دون وسائط)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_map" msgid="3200033913678466453">"الجهاز متصل (من دون وصول إلى الرسائل)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2047403011284187056">"الجهاز متصل (من دون هاتف أو وسائط)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_battery_level" msgid="5162924691231307748">"الجهاز متصل، ومستوى طاقة البطارية <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"الجهاز متصل (من دون هاتف)، ومستوى طاقة البطارية <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"الجهاز متصل (من دون وسائط)، ومستوى طاقة البطارية <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"الجهاز متّصل (من دون هاتف أو وسائط)، ومستوى طاقة البطارية <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"الإعدادات الصوتية للوسائط"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"المكالمات الهاتفية"</string>
     <string name="bluetooth_profile_opp" msgid="9168139293654233697">"نقل الملف"</string>
@@ -75,6 +75,10 @@
     <string name="bluetooth_profile_sap" msgid="5764222021851283125">"‏الوصول إلى شريحة SIM"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"صوت عالي الدقة: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"صوت عالي الدقة"</string>
+    <!-- no translation found for bluetooth_profile_hearing_aid (7999237886427812595) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (7188282786730266159) -->
+    <skip />
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"متصل بالإعدادات الصوتية للوسائط"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"متصل بالإعدادات الصوتية للهاتف"</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"متصل بخادم نقل الملف"</string>
@@ -91,6 +95,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"الاستخدام لإعدادات الهاتف الصوتية"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"استخدامه لنقل الملفات"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"استخدام للإدخال"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (908775281788309484) -->
+    <skip />
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"اقتران"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"إقران"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"إلغاء"</string>
@@ -275,7 +281,6 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"عرض تحديثات طبقات الأجهزة"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"تشغيل وميض بالأخضر لطبقات الأجهزة عند تحديثها"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"تصحيح تجاوز حد وحدة معالجة الرسومات"</string>
-    <string name="debug_hw_renderer" msgid="7568529019431785816">"تعيين عارض معالجة الرسومات"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"تعطيل تراكبات الأجهزة"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"استخدام وحدة معالجة الرسومات دائمًا لتركيب الشاشة"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"محاكاة مسافة اللون"</string>
@@ -328,9 +333,10 @@
     <item msgid="8280754435979370728">"الألوان الطبيعية تراها العين"</item>
     <item msgid="5363960654009010371">"الألوان المحسَّنة للمحتوى الرقمي"</item>
   </string-array>
-    <string name="inactive_apps_title" msgid="1317817863508274533">"التطبيقات غير النشطة"</string>
+    <string name="inactive_apps_title" msgid="9042996804461901648">"تطبيقات وضع الاستعداد"</string>
     <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"غير نشط، انقر للتبديل."</string>
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"نشط، انقر للتبديل."</string>
+    <string name="standby_bucket_summary" msgid="6567835350910684727">"حالة تطبيق وضع الاستعداد:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <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>
@@ -352,16 +358,24 @@
     <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>
+    <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"يتبقى أقل من <xliff:g id="THRESHOLD">%1$s</xliff:g>."</string>
+    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> - يتبقى أقل من <xliff:g id="THRESHOLD">%2$s</xliff:g>."</string>
+    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g>يتبقى أكثر من <xliff:g id="TIME_REMAINING">%2$s</xliff:g>."</string>
+    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"يتبقى أكثر من <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"قد يتم إغلاق الهاتف بعد قليل."</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"قد يتم إغلاق الجهاز اللوحي بعد قليل."</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"قد يتم إغلاق الجهاز بعد قليل."</string>
+    <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>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> - قد يتم إغلاق الهاتف بعد قليل."</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> - قد يتم إغلاق الجهاز اللوحي بعد قليل."</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> - قد يتم إغلاق الجهاز بعد قليل."</string>
     <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>
@@ -413,4 +427,14 @@
     </plurals>
     <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"وقت أكثر."</string>
     <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"وقت أقل."</string>
+    <string name="zen_mode_enable_dialog_turn_on" msgid="8287824809739581837">"تشغيل"</string>
+    <string name="cancel" msgid="6859253417269739139">"إلغاء"</string>
+    <string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"تشغيل وضع \"الرجاء عدم الإزعاج\""</string>
+    <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>
+    <string name="zen_alarm_warning_indef" msgid="3007988140196673193">"لن تسمع المنبه القادم في <xliff:g id="WHEN">%1$s</xliff:g> إلا إذا أوقفت هذا قبل الموعد."</string>
+    <string name="zen_alarm_warning" msgid="6236690803924413088">"لن تسمع المنبه القادم في <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template" msgid="4996153414057676512">"الساعة <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template_far" msgid="3779172822607461675">"يوم <xliff:g id="WHEN">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-az/strings.xml b/packages/SettingsLib/res/values-az/strings.xml
index 80536e1..750f225 100644
--- a/packages/SettingsLib/res/values-az/strings.xml
+++ b/packages/SettingsLib/res/values-az/strings.xml
@@ -53,16 +53,16 @@
     <string name="bluetooth_disconnected" msgid="6557104142667339895">"Ayrıldı"</string>
     <string name="bluetooth_disconnecting" msgid="8913264760027764974">"Ayrılır..."</string>
     <string name="bluetooth_connecting" msgid="8555009514614320497">"Qoşulur..."</string>
-    <string name="bluetooth_connected" msgid="6038755206916626419">"Qoşulu"</string>
+    <string name="bluetooth_connected" msgid="5427152882755735944">"Qoşuludur<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
     <string name="bluetooth_pairing" msgid="1426882272690346242">"Cütləşdirmə"</string>
-    <string name="bluetooth_connected_no_headset" msgid="2866994875046035609">"Qoşulub (telefonsuz)"</string>
-    <string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Qoşuludur (media yoxdur)"</string>
-    <string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Qoşulu (mesaj girişi yoxdur)"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Bağlantı yaradılıb (telefon və ya media deyil)"</string>
-    <string name="bluetooth_connected_battery_level" msgid="7049181126136692368">"Qoşuldu, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batareya"</string>
-    <string name="bluetooth_connected_no_headset_battery_level" msgid="5504193961248406027">"Qoşuldu (telefondan başqa), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batareya"</string>
-    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="4751724026365870779">"Qoşuldu (mediadan başqa), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batareya"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1549265779323455261">"Qoşuldu (telefon və ya mediadan başqa), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batareya"</string>
+    <string name="bluetooth_connected_no_headset" msgid="616068069034994802">"Qoşuludur (telefon yoxdur)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp" msgid="3736431800395923868">"Qoşuludur (media yoxdur)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_map" msgid="3200033913678466453">"Qoşuludur (mesaj girişi yoxdur)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2047403011284187056">"Qoşuludur (telefon və ya media yoxdur)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_battery_level" msgid="5162924691231307748">"Qoşuludur, batareya <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"Qoşuludur (telefon yoxdur), batareya <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"Qoşuludur (media yoxdur), batareya <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"Qoşuludur (telefon və ya media yoxdur), batareya <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Media audio"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"Telefon zəngləri"</string>
     <string name="bluetooth_profile_opp" msgid="9168139293654233697">"Fayl transferi"</string>
@@ -75,6 +75,10 @@
     <string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM Girişi"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD audio: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD audio"</string>
+    <!-- no translation found for bluetooth_profile_hearing_aid (7999237886427812595) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (7188282786730266159) -->
+    <skip />
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Media audioya birləşdirilib"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Telefon audiosuna qoşulu"</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Fayl transfer serverinə qoşulu"</string>
@@ -91,6 +95,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Telefon audiosu istifadə edin"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Fayl transferi üçün istifadə edin"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Daxiletmə üçün istifadə edin"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (908775281788309484) -->
+    <skip />
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Birləşdir"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"CÜTLƏNDİR"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Ləğv et"</string>
@@ -327,9 +333,10 @@
     <item msgid="8280754435979370728">"Gözlə göründüyü kimi təbii rənglər"</item>
     <item msgid="5363960654009010371">"Rəqəmsal məzmun üçün optimallaşdırılan rənglər"</item>
   </string-array>
-    <string name="inactive_apps_title" msgid="1317817863508274533">"İnaktiv tətbiqlər"</string>
+    <string name="inactive_apps_title" msgid="9042996804461901648">"Arxa fonda məhdudlaşdırılan tətbiq"</string>
     <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"Deaktivdir. Keçid etmək üçün basın."</string>
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"Aktivdir. Keçid etmək üçün basın."</string>
+    <string name="standby_bucket_summary" msgid="6567835350910684727">"Tətbiqin gözləmə rejimi:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="runningservices_settings_title" msgid="8097287939865165213">"İşləyən xidmətlər"</string>
     <string name="runningservices_settings_summary" msgid="854608995821032748">"Hazırda prosesdə olan xidmətləri görüntüləyin və onlara nəzarət edin"</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView icrası"</string>
@@ -351,16 +358,24 @@
     <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Rəng düzəlişi"</string>
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Bu funksiya eksperimentaldır və performansa təsir edə bilər."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> tərəfindən qəbul edilmir"</string>
-    <string name="power_remaining_duration_only" msgid="845431008899029842">"Təxminən <xliff:g id="TIME">^1</xliff:g> qalıb"</string>
-    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"İstifadəyə əsasən təxminən <xliff:g id="TIME">^1</xliff:g> qalıb"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Tam enerji yığmağına <xliff:g id="TIME">^1</xliff:g> qalıb"</string>
-    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">^1</xliff:g> qalıb"</string>
-    <string name="power_remaining_duration_only_short_enhanced" msgid="7450425624026394823">"İstifadəyə əsasən <xliff:g id="TIME">^1</xliff:g> qalıb"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">^1</xliff:g> - təxminən <xliff:g id="TIME">^2</xliff:g> qalıb"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">^1</xliff:g> - istifadəyə əsasən təxminən <xliff:g id="TIME">^2</xliff:g> qalıb"</string>
-    <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g> qalıb"</string>
+    <string name="power_remaining_duration_only" msgid="845431008899029842">"Təxminən <xliff:g id="TIME">%1$s</xliff:g> qalıb"</string>
+    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"İstifadəyə əsasən təxminən <xliff:g id="TIME">%1$s</xliff:g> qalıb"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Tam enerji yığmağına <xliff:g id="TIME">%1$s</xliff:g> qalıb"</string>
+    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">%1$s</xliff:g> qalıb"</string>
+    <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Qalan vaxt <xliff:g id="THRESHOLD">%1$s</xliff:g> və daha azdır"</string>
+    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="THRESHOLD">%2$s</xliff:g> və daha az vaxt qalır"</string>
+    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g> - Qalan vaxt <xliff:g id="TIME_REMAINING">%2$s</xliff:g> və daha azdır"</string>
+    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"Qalan vaxt <xliff:g id="TIME_REMAINING">%1$s</xliff:g> və daha çoxdur"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"telefon tezliklə sönə bilər"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"planşet tezliklə sönə bilər"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"cihaz tezliklə sönə bilər"</string>
+    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> - təxminən <xliff:g id="TIME">%2$s</xliff:g> qalıb"</string>
+    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> - istifadəyə əsasən təxminən <xliff:g id="TIME">%2$s</xliff:g> qalıb"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> - telefon tezliklə sönə bilər"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> - planşet tezliklə sönə bilər"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> - cihaz tezliklə sönə bilər"</string>
     <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> tam enerji yığana kimi"</string>
+    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> tam enerji yığana kimi"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Naməlum"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Enerji doldurma"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"enerji yığır"</string>
@@ -414,4 +429,8 @@
     <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"Heç vaxt"</string>
     <string name="zen_interruption_level_priority" msgid="2078370238113347720">"Yalnız prioritet"</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>
+    <string name="zen_alarm_warning_indef" msgid="3007988140196673193">"Tez bir zamanda söndürməyincə, <xliff:g id="WHEN">%1$s</xliff:g> olduqda növbəti xəbərdarlığınızı eşitməyəcəksiniz"</string>
+    <string name="zen_alarm_warning" msgid="6236690803924413088">"<xliff:g id="WHEN">%1$s</xliff:g> olduqda növbəti xəbərdarlığınızı eşitməyəcəksiniz"</string>
+    <string name="alarm_template" msgid="4996153414057676512">"<xliff:g id="WHEN">%1$s</xliff:g> olduqda"</string>
+    <string name="alarm_template_far" msgid="3779172822607461675">"<xliff:g id="WHEN">%1$s</xliff:g> olduqda"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/arrays.xml b/packages/SettingsLib/res/values-b+sr+Latn/arrays.xml
index aaf67e7d..f2f34c1 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/arrays.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/arrays.xml
@@ -234,10 +234,6 @@
     <item msgid="7688197031296835369">"Prikaži oblasti preklapanja"</item>
     <item msgid="2290859360633824369">"Prikaži oblasti za deuteranomaliju"</item>
   </string-array>
-  <string-array name="debug_hw_renderer_entries">
-    <item msgid="2578620445459945681">"OpenGL (podrazumevano)"</item>
-    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
-  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"Standardno ograničenje"</item>
     <item msgid="4071574792028999443">"Bez pozadinskih procesa"</item>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
index 9ebb651..fc7300e 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
@@ -53,16 +53,16 @@
     <string name="bluetooth_disconnected" msgid="6557104142667339895">"Veza je prekinuta"</string>
     <string name="bluetooth_disconnecting" msgid="8913264760027764974">"Prekidanje veze..."</string>
     <string name="bluetooth_connecting" msgid="8555009514614320497">"Povezivanje…"</string>
-    <string name="bluetooth_connected" msgid="6038755206916626419">"Povezano"</string>
+    <string name="bluetooth_connected" msgid="5427152882755735944">"Povezano: <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
     <string name="bluetooth_pairing" msgid="1426882272690346242">"Uparivanje..."</string>
-    <string name="bluetooth_connected_no_headset" msgid="2866994875046035609">"Povezano (bez telefona)"</string>
-    <string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Povezano (bez medija)"</string>
-    <string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Povezano je (nema pristupa porukama)"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Povezano (bez telefona ili medija)"</string>
-    <string name="bluetooth_connected_battery_level" msgid="7049181126136692368">"Povezano, nivo baterije je <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_headset_battery_level" msgid="5504193961248406027">"Povezano (bez telefona), nivo baterije je <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="4751724026365870779">"Povezano (bez medija), nivo baterije je <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1549265779323455261">"Povezano (bez telefona ili medija), nivo baterije je <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset" msgid="616068069034994802">"Povezano (bez telefona): <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp" msgid="3736431800395923868">"Povezano (bez medija): <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_map" msgid="3200033913678466453">"Povezano je (bez pristupa porukama): <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2047403011284187056">"Povezano (bez telefona ili medija): <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_battery_level" msgid="5162924691231307748">"Povezano, nivo baterije je <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"Povezano (bez telefona), nivo baterije je <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"Povezano (bez medija), nivo baterije je <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"Povezano (bez telefona ili medija), nivo baterije je <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Zvuk medija"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"Telefonski pozivi"</string>
     <string name="bluetooth_profile_opp" msgid="9168139293654233697">"Prenos datoteke"</string>
@@ -75,6 +75,10 @@
     <string name="bluetooth_profile_sap" msgid="5764222021851283125">"Pristup SIM kartici"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD zvuk: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD zvuk"</string>
+    <!-- no translation found for bluetooth_profile_hearing_aid (7999237886427812595) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (7188282786730266159) -->
+    <skip />
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Povezano sa zvukom medija"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Povezano sa zvukom telefona"</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Povezano sa serverom za prenos datoteka"</string>
@@ -91,6 +95,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Korišćenje za audio telefona"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Korišćenje za prenos datoteka"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Koristi za ulaz"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (908775281788309484) -->
+    <skip />
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Upari"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"UPARI"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Otkaži"</string>
@@ -275,7 +281,6 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"Prikaži ažuriranja hardverskih slojeva"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Hardverski slojevi trepere zeleno kada se ažuriraju"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"Otkloni greške GPU preklapanja"</string>
-    <string name="debug_hw_renderer" msgid="7568529019431785816">"Podesi GPU prikazivač"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"Onemog. HW post. elemente"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"Uvek koristi GPU za komponovanje ekrana"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"Simuliraj prostor boje"</string>
@@ -328,9 +333,10 @@
     <item msgid="8280754435979370728">"Prirodne boje nalik onima koje registruje oko"</item>
     <item msgid="5363960654009010371">"Boje optimizovane za digitalni sadržaj"</item>
   </string-array>
-    <string name="inactive_apps_title" msgid="1317817863508274533">"Neaktivne aplikacije"</string>
+    <string name="inactive_apps_title" msgid="9042996804461901648">"Aplikacije u stanju pripravnosti"</string>
     <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"Neaktivna. Dodirnite da biste je aktivirali."</string>
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"Aktivna. Dodirnite da biste je deaktivirali."</string>
+    <string name="standby_bucket_summary" msgid="6567835350910684727">"Stanje pripravnosti aplikacije: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="runningservices_settings_title" msgid="8097287939865165213">"Pokrenute usluge"</string>
     <string name="runningservices_settings_summary" msgid="854608995821032748">"Prikaz i kontrola trenutno pokrenutih usluga"</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"Primena WebView-a"</string>
@@ -352,16 +358,24 @@
     <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Korekcija boja"</string>
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Ova funkcija je eksperimentalna i može da utiče na kvalitet rada."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Zamenjuje ga <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only" msgid="845431008899029842">"Još oko <xliff:g id="TIME">^1</xliff:g>"</string>
-    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Na osnovu potrošnje imate još otprilike <xliff:g id="TIME">^1</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">^1</xliff:g> do potpunog punjenja"</string>
-    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Preostalo vreme: <xliff:g id="TIME">^1</xliff:g>"</string>
-    <string name="power_remaining_duration_only_short_enhanced" msgid="7450425624026394823">"Na osnovu potrošnje imate još <xliff:g id="TIME">^1</xliff:g>"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">^1</xliff:g> – ostalo je oko <xliff:g id="TIME">^2</xliff:g>"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">^1</xliff:g> – na osnovu potrošnje imate još otprilike <xliff:g id="TIME">^2</xliff:g>"</string>
-    <string name="power_discharging_duration_short" msgid="4192244429001842403">"Preostalo je <xliff:g id="LEVEL">^1</xliff:g> – <xliff:g id="TIME">^2</xliff:g>"</string>
+    <string name="power_remaining_duration_only" msgid="845431008899029842">"Još oko <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Na osnovu potrošnje imate još otprilike <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> do potpunog punjenja"</string>
+    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Preostalo vreme: <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Preostalo je manje od <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
+    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> – preostalo je manje od <xliff:g id="THRESHOLD">%2$s</xliff:g>"</string>
+    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g> – preostalo je više od <xliff:g id="TIME_REMAINING">%2$s</xliff:g>"</string>
+    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"preostalo je više od <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"telefon će se uskoro isključiti"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"tablet će se uskoro isključiti"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"uređaj će se uskoro isključiti"</string>
+    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> – ostalo je oko <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> – na osnovu potrošnje imate još otprilike <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> – telefon će se uskoro isključiti"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> – tablet će se uskoro isključiti"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> – uređaj će se uskoro isključiti"</string>
     <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> do potpunog punjenja"</string>
+    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do potpunog punjenja"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Nepoznato"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Punjenje"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"puni se"</string>
@@ -410,4 +424,14 @@
     </plurals>
     <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"Više vremena."</string>
     <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"Manje vremena."</string>
+    <string name="zen_mode_enable_dialog_turn_on" msgid="8287824809739581837">"Uključi"</string>
+    <string name="cancel" msgid="6859253417269739139">"Otkaži"</string>
+    <string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"Uključite režim Ne uznemiravaj"</string>
+    <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"Nikad"</string>
+    <string name="zen_interruption_level_priority" msgid="2078370238113347720">"Samo prioritetni prekidi"</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>
+    <string name="zen_alarm_warning_indef" msgid="3007988140196673193">"Nećete čuti sledeći alarm u <xliff:g id="WHEN">%1$s</xliff:g> ako ne isključite ovo pre toga"</string>
+    <string name="zen_alarm_warning" msgid="6236690803924413088">"Nećete čuti sledeći alarm u <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template" msgid="4996153414057676512">"u <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template_far" msgid="3779172822607461675">"<xliff:g id="WHEN">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml
index 9ea825d..97ccf91 100644
--- a/packages/SettingsLib/res/values-be/strings.xml
+++ b/packages/SettingsLib/res/values-be/strings.xml
@@ -53,16 +53,16 @@
     <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>
+    <string name="bluetooth_connected" msgid="5427152882755735944">"Падключана прылада <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
     <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>
+    <string name="bluetooth_connected_no_headset" msgid="616068069034994802">"Падключана прылада <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> (без званкоў)"</string>
+    <string name="bluetooth_connected_no_a2dp" msgid="3736431800395923868">"Падключана прылада <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> (без аўдыя)"</string>
+    <string name="bluetooth_connected_no_map" msgid="3200033913678466453">"Падключана прылада <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> (без паведамленняў)"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2047403011284187056">"Падкл. прылада <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> (без званкоў і аўдыя)"</string>
+    <string name="bluetooth_connected_battery_level" msgid="5162924691231307748">"Падключана прылада <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>. Узровень зараду яе акумулятара: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"Падключана прылада <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (без званкоў). Узровень зараду яе акумулятара: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"Падключана прылада <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (без аўдыя). Узровень зараду яе акумулятара: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"Падключана прылада <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (без званкоў і аўдыя). Узровень зараду яе акумулятара: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Аўдыё медыяпрылады"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"Тэлефонныя выклікі"</string>
     <string name="bluetooth_profile_opp" msgid="9168139293654233697">"Перадача файлаў"</string>
@@ -75,6 +75,10 @@
     <string name="bluetooth_profile_sap" msgid="5764222021851283125">"Доступ да SIM-карты"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"Аўдыя ў HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"Аўдыя ў HD"</string>
+    <!-- no translation found for bluetooth_profile_hearing_aid (7999237886427812595) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (7188282786730266159) -->
+    <skip />
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Падключана да аўдыё медыа"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Падключана да аўдыё тэлефона"</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Падключаны да серверу перадачы файлаў"</string>
@@ -91,6 +95,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Выкарыстоўваць для аўдыё тэлефона"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Выкарыстоўваць для перадачы файлаў"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Выкарыстоўваць для ўводу"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (908775281788309484) -->
+    <skip />
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Падлучыць"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"СПАЛУЧЫЦЬ"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Скасаваць"</string>
@@ -327,9 +333,10 @@
     <item msgid="8280754435979370728">"Натуральныя колеры (такія, як яны ўспрымаюцца вокам)"</item>
     <item msgid="5363960654009010371">"Колеры, аптымізаваныя для лічбавага змесціва"</item>
   </string-array>
-    <string name="inactive_apps_title" msgid="1317817863508274533">"Неактыўныя дадаткі"</string>
+    <string name="inactive_apps_title" msgid="9042996804461901648">"Праграмы ў рэжыме чакання"</string>
     <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"Неактыўная. Краніце, каб пераключыць."</string>
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"Актыўная. Краніце, каб пераключыць."</string>
+    <string name="standby_bucket_summary" msgid="6567835350910684727">"Стан праграмы ў рэжыме чакання: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="runningservices_settings_title" msgid="8097287939865165213">"Запушчаныя службы"</string>
     <string name="runningservices_settings_summary" msgid="854608995821032748">"Прагляд запушчаных службаў i кіраванне iмi"</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"Рэалізацыя WebView"</string>
@@ -351,16 +358,24 @@
     <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>
+    <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Засталося менш за <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
+    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> – засталося менш за <xliff:g id="THRESHOLD">%2$s</xliff:g>"</string>
+    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g> – засталося больш за <xliff:g id="TIME_REMAINING">%2$s</xliff:g>"</string>
+    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"засталося больш за <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"тэлефон у хуткім часе выключыцца"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"планшэт у хуткім часе выключыцца"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"прылада ў хуткім часе выключыцца"</string>
+    <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>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> – тэлефон у хуткім часе выключыцца"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> – планшэт у хуткім часе выключыцца"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> – прылада ў хуткім часе выключыцца"</string>
     <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>
@@ -416,4 +431,8 @@
     <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>
+    <string name="zen_alarm_warning_indef" msgid="3007988140196673193">"Наступны будзільнік (<xliff:g id="WHEN">%1$s</xliff:g>) не зазвініць, пакуль вы не выключыце гэту функцыю"</string>
+    <string name="zen_alarm_warning" msgid="6236690803924413088">"Наступны будзільнік не зазвініць: <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template" msgid="4996153414057676512">"у <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template_far" msgid="3779172822607461675">"у <xliff:g id="WHEN">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-bg/arrays.xml b/packages/SettingsLib/res/values-bg/arrays.xml
index 7eec6ed..a5aa98e 100644
--- a/packages/SettingsLib/res/values-bg/arrays.xml
+++ b/packages/SettingsLib/res/values-bg/arrays.xml
@@ -234,10 +234,6 @@
     <item msgid="7688197031296835369">"Области за преизчертаване: Показв."</item>
     <item msgid="2290859360633824369">"Показване на областите за деутеранопия"</item>
   </string-array>
-  <string-array name="debug_hw_renderer_entries">
-    <item msgid="2578620445459945681">"OpenGL (по подразбиране)"</item>
-    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
-  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"Стандартно ограничение"</item>
     <item msgid="4071574792028999443">"Няма процеси на заден план"</item>
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index 8186a03..9bde546 100644
--- a/packages/SettingsLib/res/values-bg/strings.xml
+++ b/packages/SettingsLib/res/values-bg/strings.xml
@@ -53,16 +53,16 @@
     <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>
+    <string name="bluetooth_connected" msgid="5427152882755735944">"Свързано<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
     <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>
+    <string name="bluetooth_connected_no_headset" msgid="616068069034994802">"Свързано (без телефон)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp" msgid="3736431800395923868">"Свързано (без мултимедия)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_map" msgid="3200033913678466453">"Свързано (без достъп до съобщенията)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2047403011284187056">"Свързано (без телефон или мултимедия)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_battery_level" msgid="5162924691231307748">"Свързано, батерия: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"Свързано (без телефон), батерия: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"Свързано (без мултимедия), батерия: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"Свързано (без телефон или мултимедия), батерия: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Мултимедийно аудио"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"Телефонни обаждания"</string>
     <string name="bluetooth_profile_opp" msgid="9168139293654233697">"Прехвърляне на файл"</string>
@@ -75,6 +75,10 @@
     <string name="bluetooth_profile_sap" msgid="5764222021851283125">"Достъп до SIM картата"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"Висококачествено аудио: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"Висококачествено аудио"</string>
+    <!-- no translation found for bluetooth_profile_hearing_aid (7999237886427812595) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (7188282786730266159) -->
+    <skip />
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Установена е връзка с медийно аудио"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Връзка със звука на телефона"</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Установена е връзка със сървър за трансфер на файлове"</string>
@@ -91,6 +95,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Използване на телефон за аудио"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Използване на за пренос на файлове"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Да се използва за въвеждане"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (908775281788309484) -->
+    <skip />
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Сдвояване"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"СДВОЯВАНЕ"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Отказ"</string>
@@ -275,7 +281,6 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"Актуал. на слоевете на хардуера"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Примигв. на слоевете на хардуера в зелено при актуал."</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"Отстран. на проблеми с преизчертаване от GPU"</string>
-    <string name="debug_hw_renderer" msgid="7568529019431785816">"Визуализатор на ГП: Избор"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"Хардуерни наслагв.: Деактив."</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"Винаги да се използва GPU за изграждане на екрана"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"Цвет. простр.: Симулиране"</string>
@@ -328,9 +333,10 @@
     <item msgid="8280754435979370728">"Естествени цветове, без подобрения"</item>
     <item msgid="5363960654009010371">"Цветове, оптимизирани за дигитално съдържание"</item>
   </string-array>
-    <string name="inactive_apps_title" msgid="1317817863508274533">"Неактивни приложения"</string>
+    <string name="inactive_apps_title" msgid="9042996804461901648">"Приложения в готовност"</string>
     <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"Неактивно. Докоснете, за да превключите."</string>
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"Активно. Докоснете, за да превключите."</string>
+    <string name="standby_bucket_summary" msgid="6567835350910684727">"Състояние на готовност на приложението: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <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>
@@ -352,16 +358,24 @@
     <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>
+    <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Остава/т по-малко от <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
+    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> – остава/т по-малко от <xliff:g id="THRESHOLD">%2$s</xliff:g>"</string>
+    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g> – остава/т повече от <xliff:g id="TIME_REMAINING">%2$s</xliff:g>"</string>
+    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"остава/т повече от <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"възможно е телефонът да се изключи скоро"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"възможно е таблетът да се изключи скоро"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"възможно е устройството да се изключи скоро"</string>
+    <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>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> – възможно е телефонът да се изключи скоро"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> – възможно е таблетът да се изключи скоро"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> – възможно е устройството да се изключи скоро"</string>
     <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>
@@ -409,4 +423,14 @@
     </plurals>
     <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"Повече време."</string>
     <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"По-малко време."</string>
+    <string name="zen_mode_enable_dialog_turn_on" msgid="8287824809739581837">"Включване"</string>
+    <string name="cancel" msgid="6859253417269739139">"Отказ"</string>
+    <string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"Включване на режима „Не безпокойте“"</string>
+    <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>
+    <string name="zen_alarm_warning_indef" msgid="3007988140196673193">"Няма да чуете следващия си будилник в <xliff:g id="WHEN">%1$s</xliff:g>, освен ако не изключите настройката преди това"</string>
+    <string name="zen_alarm_warning" msgid="6236690803924413088">"Няма да чуете следващия си будилник в <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template" msgid="4996153414057676512">"в <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template_far" msgid="3779172822607461675">"в/ъв <xliff:g id="WHEN">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml
index 2f6748f..28b879bd 100644
--- a/packages/SettingsLib/res/values-bn/strings.xml
+++ b/packages/SettingsLib/res/values-bn/strings.xml
@@ -53,16 +53,16 @@
     <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>
+    <string name="bluetooth_connected" msgid="5427152882755735944">"কানেক্ট করা আছে<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
     <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>
+    <string name="bluetooth_connected_no_headset" msgid="616068069034994802">"কানেক্ট করা আছে (ফোনের অডিও ছাড়া)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp" msgid="3736431800395923868">"কানেক্ট করা আছে (মিডিয়ার অডিও ছাড়া)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_map" msgid="3200033913678466453">"কানেক্ট করা আছে (মেসেজে অ্যাকসেস নেই)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2047403011284187056">"কানেক্ট করা আছে (ফোনের বা মিডিয়ার অডিও ছাড়া)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_battery_level" msgid="5162924691231307748">"কানেক্ট করা আছে, ব্যাটারি <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"কানেক্ট করা আছে (ফোনের অডিও ছাড়া), ব্যাটারি <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"কানেক্ট করা আছে (মিডিয়ার অডিও ছাড়া), ব্যাটারি <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"কানেক্ট করা আছে (ফোনের বা মিডিয়ার অডিও ছাড়া), ব্যাটারি <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"মিডিয়া অডিও"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"ফোন কল"</string>
     <string name="bluetooth_profile_opp" msgid="9168139293654233697">"ফাইল স্থানান্তর"</string>
@@ -75,6 +75,10 @@
     <string name="bluetooth_profile_sap" msgid="5764222021851283125">"সিম -এর অ্যাক্সেস"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD অডিও: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD অডিও"</string>
+    <!-- no translation found for bluetooth_profile_hearing_aid (7999237886427812595) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (7188282786730266159) -->
+    <skip />
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"মিডিয়া অডিওতে সংযুক্ত রয়েছে"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"ফোন অডিওতে সংযুক্ত"</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"ফাইল স্থানান্তর সার্ভারের সঙ্গে সংযুক্ত"</string>
@@ -91,6 +95,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"ফোন অডিওয়ের জন্য ব্যবহার করুন"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"ফাইল স্থানান্তরের জন্য ব্যবহার করুন"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"ইনপুটের জন্য ব্যবহার করুন"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (908775281788309484) -->
+    <skip />
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"যুক্ত করুন"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"যুক্ত করুন"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"বাতিল করুন"</string>
@@ -327,9 +333,10 @@
     <item msgid="8280754435979370728">"স্বাভাবিক ভাবে আমরা চোখে যেমনটি দেখি সেইরূপ প্রাকৃতিক রঙ"</item>
     <item msgid="5363960654009010371">"ডিজিট্যাল সামগ্রীর জন্য অপ্টিমাইজ করা রঙগুলি"</item>
   </string-array>
-    <string name="inactive_apps_title" msgid="1317817863508274533">"নিষ্ক্রিয় অ্যাপ্লিকেশানগুলি"</string>
+    <string name="inactive_apps_title" msgid="9042996804461901648">"স্ট্যান্ডবাই অ্যাপ"</string>
     <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"নিষ্ক্রিয় রয়েছে৷ টগল করতে আলতো চাপুন৷"</string>
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"সক্রিয় রয়েছে৷ টগল করতে আলতো চাপুন৷"</string>
+    <string name="standby_bucket_summary" msgid="6567835350910684727">"অ্যাপ স্ট্যান্ডবাই-এর অবস্থা:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="runningservices_settings_title" msgid="8097287939865165213">"এখন চলছে যে পরিষেবাগুলি"</string>
     <string name="runningservices_settings_summary" msgid="854608995821032748">"বর্তমান চলমান পরিষেবাগুলি দেখুন এবং নিয়ন্ত্রণ করুন"</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"ওয়েবভিউ প্রয়োগ"</string>
@@ -351,16 +358,24 @@
     <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>
+    <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"<xliff:g id="THRESHOLD">%1$s</xliff:g> এর থেকেও কম বাকি আছে"</string>
+    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="THRESHOLD">%2$s</xliff:g> এর থেকেও কম বাকি আছে"</string>
+    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g><xliff:g id="TIME_REMAINING">%2$s</xliff:g> এর থেকে বেশি বাকি আছে"</string>
+    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> এর থেকে বেশি বাকি আছে"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"ফোন শীঘ্রই বন্ধ হয়ে যেতে পারে"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"ট্যাবলেট শীঘ্রই বন্ধ হয়ে যেতে পারে"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"ডিভাইসটি শীঘ্রই বন্ধ হয়ে যেতে পারে"</string>
+    <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>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> - ফোন শীঘ্রই বন্ধ হয়ে যেতে পারে"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> - ট্যাবলেট শীঘ্রই বন্ধ হয়ে যেতে পারে"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> - ডিভাইসটি শীঘ্রই বন্ধ হয়ে যেতে পারে"</string>
     <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 +429,8 @@
     <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>
+    <string name="zen_alarm_warning_indef" msgid="3007988140196673193">"<xliff:g id="WHEN">%1$s</xliff:g> এর আগে এটি বন্ধ না করা পর্যন্ত পরবর্তী অ্যালার্ম শুনতে পাবেন না"</string>
+    <string name="zen_alarm_warning" msgid="6236690803924413088">"<xliff:g id="WHEN">%1$s</xliff:g> এর সময় আপনার পরবর্তী অ্যালার্ম শুনতে পাবেন না"</string>
+    <string name="alarm_template" msgid="4996153414057676512">"সময় <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template_far" msgid="3779172822607461675">"তারিখ ও সময় <xliff:g id="WHEN">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml
index 433bbdb..bbe4767 100644
--- a/packages/SettingsLib/res/values-bs/strings.xml
+++ b/packages/SettingsLib/res/values-bs/strings.xml
@@ -53,16 +53,16 @@
     <string name="bluetooth_disconnected" msgid="6557104142667339895">"Isključen"</string>
     <string name="bluetooth_disconnecting" msgid="8913264760027764974">"Prekidanje veze…"</string>
     <string name="bluetooth_connecting" msgid="8555009514614320497">"Povezivanje…"</string>
-    <string name="bluetooth_connected" msgid="6038755206916626419">"Povezano"</string>
+    <string name="bluetooth_connected" msgid="5427152882755735944">"Povezano<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
     <string name="bluetooth_pairing" msgid="1426882272690346242">"Uparivanje…"</string>
-    <string name="bluetooth_connected_no_headset" msgid="2866994875046035609">"Povezano (bez telefona)"</string>
-    <string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Povezano (bez medija)"</string>
-    <string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Povezano (bez pristupa porukama)"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Povezano (bez zvuka telefona ili medija)"</string>
-    <string name="bluetooth_connected_battery_level" msgid="7049181126136692368">"Povezano, baterija <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_headset_battery_level" msgid="5504193961248406027">"Povezano (bez telefona), baterija <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="4751724026365870779">"Povezano (bez medija), baterija <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1549265779323455261">"Povezano (bez telefona ili medija), baterija <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset" msgid="616068069034994802">"Povezano (bez telefona)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp" msgid="3736431800395923868">"Povezano (bez medija)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_map" msgid="3200033913678466453">"Povezano (bez pristupa porukama)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2047403011284187056">"Povezano (bez telefona ili medija)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_battery_level" msgid="5162924691231307748">"Povezano, baterija <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"Povezano (bez telefona), baterija <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"Povezano (bez medija), baterija <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"Povezano (bez telefona ili medija), baterija <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Zvuk medija"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"Telefonski pozivi"</string>
     <string name="bluetooth_profile_opp" msgid="9168139293654233697">"Prenošenje fajla"</string>
@@ -75,6 +75,10 @@
     <string name="bluetooth_profile_sap" msgid="5764222021851283125">"Pristup SIM-u"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD audio: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD audio"</string>
+    <!-- no translation found for bluetooth_profile_hearing_aid (7999237886427812595) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (7188282786730266159) -->
+    <skip />
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Povezano sa zvukom medija"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Povezano na zvuk telefona"</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Povezan na server za prijenos podataka"</string>
@@ -91,6 +95,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Koristi za zvuk telefona"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Koristi za prijenos fajlova"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Koristi kao ulaz"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (908775281788309484) -->
+    <skip />
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Upari"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"UPARI"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Otkaži"</string>
@@ -196,7 +202,7 @@
     <string name="debug_networking_category" msgid="7044075693643009662">"Umrežavanje"</string>
     <string name="wifi_display_certification" msgid="8611569543791307533">"Certifikacija bežičnog prikaza"</string>
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"Omogućiti Wi-Fi Verbose zapisivanje"</string>
-    <string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"Povezana randomizacija MAC adrese"</string>
+    <string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"Nasumični odabir MAC adrese pri povezivanju"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobilna mreža za prijenos podataka je uvijek aktivna"</string>
     <string name="tethering_hardware_offload" msgid="7470077827090325814">"Hardversko ubrzavanje dijeljenja veze"</string>
     <string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Prikaži Bluetooth uređaje bez naziva"</string>
@@ -327,9 +333,10 @@
     <item msgid="8280754435979370728">"Prirodne boje onako kako ih oko vidi"</item>
     <item msgid="5363960654009010371">"Boje optimizirane za digitalni sadržaj"</item>
   </string-array>
-    <string name="inactive_apps_title" msgid="1317817863508274533">"Neaktivne aplikacije"</string>
+    <string name="inactive_apps_title" msgid="9042996804461901648">"Aplikacije u stanju mirovanja"</string>
     <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"Neaktivno. Dodirnite za promjenu opcije."</string>
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"Aktivno. Dodirnite za promjenu opcije."</string>
+    <string name="standby_bucket_summary" msgid="6567835350910684727">"Stanje mirovanja aplikacije:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="runningservices_settings_title" msgid="8097287939865165213">"Pokrenute usluge"</string>
     <string name="runningservices_settings_summary" msgid="854608995821032748">"Prikažite trenutno pokrenute usluge i upravljajte njima"</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"Postavljanje WebViewa"</string>
@@ -351,16 +358,24 @@
     <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Ispravka boje"</string>
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Ova funkcija je eksperimentalna i može uticati na performanse."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Zamjenjuje <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only" msgid="845431008899029842">"Preostalo je otprilike još <xliff:g id="TIME">^1</xliff:g>"</string>
-    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Preostalo je još oko <xliff:g id="TIME">^1</xliff:g>, na osnovu vašeg korištenja"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Još <xliff:g id="TIME">^1</xliff:g> do potpune napunjenosti"</string>
-    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Imate još <xliff:g id="TIME">^1</xliff:g>"</string>
-    <string name="power_remaining_duration_only_short_enhanced" msgid="7450425624026394823">"Preostalo je još <xliff:g id="TIME">^1</xliff:g>, na osnovu vašeg korištenja"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">^1</xliff:g> - imate još <xliff:g id="TIME">^2</xliff:g>"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">^1</xliff:g> - preostalo je još oko <xliff:g id="TIME">^2</xliff:g>, na osnovu vašeg korištenja"</string>
-    <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> - imate još <xliff:g id="TIME">^2</xliff:g>"</string>
+    <string name="power_remaining_duration_only" msgid="845431008899029842">"Preostalo je otprilike još <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Preostalo je još oko <xliff:g id="TIME">%1$s</xliff:g>, na osnovu vašeg korištenja"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Još <xliff:g id="TIME">%1$s</xliff:g> do potpune napunjenosti"</string>
+    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Imate još <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Preostalo je manje od <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
+    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> – Preostalo je manje od <xliff:g id="THRESHOLD">%2$s</xliff:g>"</string>
+    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g>preostalo je više od <xliff:g id="TIME_REMAINING">%2$s</xliff:g>"</string>
+    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"preostalo je više od <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"telefon će se uskoro isključiti"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"tablet će se uskoro isključiti"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"uređaj će se uskoro isključiti"</string>
+    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> - imate još <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> - preostalo je još oko <xliff:g id="TIME">%2$s</xliff:g>, na osnovu vašeg korištenja"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> – telefon će se uskoro isključiti"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> – tablet će se uskoro isključiti"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> – uređaj će se uskoro isključiti"</string>
     <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> do potpune napunjenosti"</string>
+    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> do potpune napunjenosti"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Nepoznato"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Punjenje"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"punjenje"</string>
@@ -403,9 +418,9 @@
     <string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Nije registrirano"</string>
     <string name="status_unavailable" msgid="7862009036663793314">"Nije dostupno"</string>
     <plurals name="wifi_tether_connected_summary" formatted="false" msgid="3871603864314407780">
-      <item quantity="one">%1$d povezan uređaj</item>
-      <item quantity="few">%1$d povezana uređaja</item>
-      <item quantity="other">%1$d povezanih uređaja</item>
+      <item quantity="one">Povezan je %1$d uređaj</item>
+      <item quantity="few">Povezana su %1$duređaja</item>
+      <item quantity="other">Povezano je %1$d uređaja</item>
     </plurals>
     <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"Više vremena."</string>
     <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"Manje vremena."</string>
@@ -415,4 +430,8 @@
     <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"Nikada"</string>
     <string name="zen_interruption_level_priority" msgid="2078370238113347720">"Samo prioriteti"</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>
+    <string name="zen_alarm_warning_indef" msgid="3007988140196673193">"Nećete čuti sljedeći alarm u <xliff:g id="WHEN">%1$s</xliff:g> ako prije toga ovo ne isključite"</string>
+    <string name="zen_alarm_warning" msgid="6236690803924413088">"Nećete čuti sljedeći alarm u <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template" msgid="4996153414057676512">"u <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template_far" msgid="3779172822607461675">"u <xliff:g id="WHEN">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index d020f80..88f01df 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -53,16 +53,16 @@
     <string name="bluetooth_disconnected" msgid="6557104142667339895">"Desconnectat"</string>
     <string name="bluetooth_disconnecting" msgid="8913264760027764974">"S\'està desconnectant..."</string>
     <string name="bluetooth_connecting" msgid="8555009514614320497">"S\'està connectant…"</string>
-    <string name="bluetooth_connected" msgid="6038755206916626419">"Connectat"</string>
+    <string name="bluetooth_connected" msgid="5427152882755735944">"<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> connectat"</string>
     <string name="bluetooth_pairing" msgid="1426882272690346242">"S\'està vinculant..."</string>
-    <string name="bluetooth_connected_no_headset" msgid="2866994875046035609">"Connectats (sense telèfon)"</string>
-    <string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Connectat (sense fitxers multimèdia)"</string>
-    <string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Connectat (no hi ha accés als missatges)"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Connectat (sense telèfon o disp. mult.)"</string>
-    <string name="bluetooth_connected_battery_level" msgid="7049181126136692368">"Connectat (<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria)"</string>
-    <string name="bluetooth_connected_no_headset_battery_level" msgid="5504193961248406027">"Connectat, sense telèfon (<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria)"</string>
-    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="4751724026365870779">"Connectat, sense àudio multimèdia (<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria)"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1549265779323455261">"Connectat, sense telèfon ni àudio multimèdia (<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria)"</string>
+    <string name="bluetooth_connected_no_headset" msgid="616068069034994802">"<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> connectat (sense accés al telèfon)"</string>
+    <string name="bluetooth_connected_no_a2dp" msgid="3736431800395923868">"<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> connectat (sense contingut multimèdia)"</string>
+    <string name="bluetooth_connected_no_map" msgid="3200033913678466453">"<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> connectat (sense accés als missatges)"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2047403011284187056">"<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> connectat (sense telèfon ni multimèdia)"</string>
+    <string name="bluetooth_connected_battery_level" msgid="5162924691231307748">"<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> connectat, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria"</string>
+    <string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> connectat (sense accés al telèfon), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria"</string>
+    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> connectat (sense accés al contingut multimèdia), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> connectat (sense accés al telèfon ni al contingut multimèdia), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria"</string>
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Àudio multimèdia"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"Trucades telefòniques"</string>
     <string name="bluetooth_profile_opp" msgid="9168139293654233697">"Transferència del fitxer"</string>
@@ -75,6 +75,10 @@
     <string name="bluetooth_profile_sap" msgid="5764222021851283125">"Accés a la SIM"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"Àudio HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"Àudio HD"</string>
+    <!-- no translation found for bluetooth_profile_hearing_aid (7999237886427812595) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (7188282786730266159) -->
+    <skip />
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Connectat a l\'àudio del mitjà"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Connectat a àudio del telèfon"</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Connectat al servidor de transferència de fitxers"</string>
@@ -91,6 +95,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Utilitza-ho per a l\'àudio del telèfon"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Utilitza per a la transferència de fitxers"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Utilitza per a entrada"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (908775281788309484) -->
+    <skip />
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Vincula"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"VINCULA"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Cancel·la"</string>
@@ -327,9 +333,10 @@
     <item msgid="8280754435979370728">"Colors naturals tal com els veu l\'ull humà"</item>
     <item msgid="5363960654009010371">"Colors optimitzats per al contingut digital"</item>
   </string-array>
-    <string name="inactive_apps_title" msgid="1317817863508274533">"Aplicacions inactives"</string>
+    <string name="inactive_apps_title" msgid="9042996804461901648">"Aplicacions inactives"</string>
     <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"Aplicació inactiva. Toca per activar-la."</string>
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"Aplicació activa. Toca per desactivar-la."</string>
+    <string name="standby_bucket_summary" msgid="6567835350910684727">"Estat de les aplicacions inactives: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="runningservices_settings_title" msgid="8097287939865165213">"Serveis en execució"</string>
     <string name="runningservices_settings_summary" msgid="854608995821032748">"Visualitza i controla els serveis en execució"</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"Implementació de WebView"</string>
@@ -351,16 +358,24 @@
     <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Correcció del color"</string>
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Aquesta funció és experimental i pot afectar el rendiment."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"S\'ha substituït per <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only" msgid="845431008899029842">"Temps restant aproximat: <xliff:g id="TIME">^1</xliff:g>"</string>
-    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Temps restant aproximat segons l\'ús que en fas: <xliff:g id="TIME">^1</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">^1</xliff:g> per completar la càrrega"</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">"Temps restant segons l\'ús que en fas: <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> aproximadament per esgotar la bateria"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">^1</xliff:g>; temps restant aproximat segons l\'ús que en fas: <xliff:g id="TIME">^2</xliff:g>"</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">"Temps restant aproximat: <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Temps restant aproximat segons l\'ús que en fas: <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> per completar la càrrega"</string>
+    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Temps restant: <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Queda menys d\'un <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
+    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g>: queda menys d\'un <xliff:g id="THRESHOLD">%2$s</xliff:g>"</string>
+    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g>: el temps restant és superior a <xliff:g id="TIME_REMAINING">%2$s</xliff:g>"</string>
+    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"el temps restant és superior a <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"és possible que el telèfon s\'apagui aviat"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"és possible que la tauleta s\'apagui aviat"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"és possible que el dispositiu s\'apagui aviat"</string>
+    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> aproximadament per esgotar la bateria"</string>
+    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g>; temps restant aproximat segons l\'ús que en fas: <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g>: és possible que el telèfon s\'apagui aviat"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g>: és possible que la tauleta s\'apagui aviat"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g>: és possible que el dispositiu s\'apagui aviat"</string>
     <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> per completar la càrrega"</string>
+    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> per completar la càrrega"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Desconegut"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"S\'està carregant"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"s\'està carregant"</string>
@@ -414,4 +429,8 @@
     <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"Mai"</string>
     <string name="zen_interruption_level_priority" msgid="2078370238113347720">"Només amb prioritat"</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>
+    <string name="zen_alarm_warning_indef" msgid="3007988140196673193">"Si no desactives aquesta opció abans, no sentiràs la pròxima alarma (<xliff:g id="WHEN">%1$s</xliff:g>)"</string>
+    <string name="zen_alarm_warning" msgid="6236690803924413088">"No sentiràs la pròxima alarma (<xliff:g id="WHEN">%1$s</xliff:g>)"</string>
+    <string name="alarm_template" msgid="4996153414057676512">"Hora: <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template_far" msgid="3779172822607461675">"Data: <xliff:g id="WHEN">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml
index c29973c..e5dde7e 100644
--- a/packages/SettingsLib/res/values-cs/strings.xml
+++ b/packages/SettingsLib/res/values-cs/strings.xml
@@ -53,16 +53,16 @@
     <string name="bluetooth_disconnected" msgid="6557104142667339895">"Odpojeno"</string>
     <string name="bluetooth_disconnecting" msgid="8913264760027764974">"Odpojování..."</string>
     <string name="bluetooth_connecting" msgid="8555009514614320497">"Připojování..."</string>
-    <string name="bluetooth_connected" msgid="6038755206916626419">"Připojeno"</string>
+    <string name="bluetooth_connected" msgid="5427152882755735944">"Připojeno k zařízení <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
     <string name="bluetooth_pairing" msgid="1426882272690346242">"Párování..."</string>
-    <string name="bluetooth_connected_no_headset" msgid="2866994875046035609">"Připojeno (žádný telefon)"</string>
-    <string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Připojeno (žádná média)"</string>
-    <string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Připojeno (bez přístupu ke zprávám)"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Připojeno (žádný telefon nebo média)"</string>
-    <string name="bluetooth_connected_battery_level" msgid="7049181126136692368">"Připojeno, baterie: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_headset_battery_level" msgid="5504193961248406027">"Připojeno (žádný telefon), baterie: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="4751724026365870779">"Připojeno (žádná média), baterie: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1549265779323455261">"Připojeno (žádný telefon ani média), baterie: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset" msgid="616068069034994802">"Připojeno k zařízení <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> (bez telefonu)"</string>
+    <string name="bluetooth_connected_no_a2dp" msgid="3736431800395923868">"Připojeno k zařízení <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> (bez médií)"</string>
+    <string name="bluetooth_connected_no_map" msgid="3200033913678466453">"Připojeno k zařízení <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> (bez přístupu ke zprávám)"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2047403011284187056">"Připojeno k zařízení <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> (bez telefonu a médií)"</string>
+    <string name="bluetooth_connected_battery_level" msgid="5162924691231307748">"Připojeno k zařízení <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>, úroveň baterie <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"Připojeno k zařízení <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (bez telefonu), úroveň baterie <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"Připojeno k zařízení <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (bez médií), úroveň baterie <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"Připojeno k zařízení <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (bez telefonu a médií), úroveň baterie <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Zvuk médií"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"Telefonní hovory"</string>
     <string name="bluetooth_profile_opp" msgid="9168139293654233697">"Přenos souborů"</string>
@@ -75,6 +75,10 @@
     <string name="bluetooth_profile_sap" msgid="5764222021851283125">"Přístup k SIM kartě"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD zvuk: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD zvuk"</string>
+    <!-- no translation found for bluetooth_profile_hearing_aid (7999237886427812595) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (7188282786730266159) -->
+    <skip />
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Připojeno ke zvukovému médiu"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Připojeno k náhlavní soupravě"</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Připojeno k serveru pro přenos dat"</string>
@@ -91,6 +95,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Umožňuje připojení náhlavní soupravy"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Použít pro přenos souborů"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Použít pro vstup"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (908775281788309484) -->
+    <skip />
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Párovat"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"PÁROVAT"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Zrušit"</string>
@@ -327,9 +333,10 @@
     <item msgid="8280754435979370728">"Přirozené barvy, jak je vidí oči"</item>
     <item msgid="5363960654009010371">"Barvy optimalizované pro digitální obsah"</item>
   </string-array>
-    <string name="inactive_apps_title" msgid="1317817863508274533">"Neaktivní aplikace"</string>
+    <string name="inactive_apps_title" msgid="9042996804461901648">"Aplikace v pohotovostním režimu"</string>
     <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"Neaktivní. Klepnutím možnost přepnete."</string>
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"Aktivní. Klepnutím možnost přepnete."</string>
+    <string name="standby_bucket_summary" msgid="6567835350910684727">"Stav pohotovostního režimu aplikace: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="runningservices_settings_title" msgid="8097287939865165213">"Spuštěné služby"</string>
     <string name="runningservices_settings_summary" msgid="854608995821032748">"Umožňuje zobrazit a ovládat aktuálně spuštěné služby"</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"Implementace WebView"</string>
@@ -351,16 +358,24 @@
     <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Korekce barev"</string>
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Funkce je experimentální a může mít vliv na výkon."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Přepsáno nastavením <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only" msgid="845431008899029842">"Zbývá asi <xliff:g id="TIME">^1</xliff:g>"</string>
-    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Při vašem obvyklém využití zbývá asi <xliff:g id="TIME">^1</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Plně se nabije za <xliff:g id="TIME">^1</xliff:g>"</string>
-    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Zbývající čas: <xliff:g id="TIME">^1</xliff:g>"</string>
-    <string name="power_remaining_duration_only_short_enhanced" msgid="7450425624026394823">"Při vašem obvyklém využití zbývá <xliff:g id="TIME">^1</xliff:g>"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">^1</xliff:g> – zbývá přibližně <xliff:g id="TIME">^2</xliff:g>"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">^1</xliff:g> – při vašem obvyklém využití zbývá asi <xliff:g id="TIME">^2</xliff:g>"</string>
-    <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> – zbývá <xliff:g id="TIME">^2</xliff:g>"</string>
+    <string name="power_remaining_duration_only" msgid="845431008899029842">"Zbývá asi <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Při vašem obvyklém využití zbývá asi <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Plně se nabije za <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Zbývající čas: <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Zbývá méně než <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
+    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> – zbývá méně než <xliff:g id="THRESHOLD">%2$s</xliff:g>"</string>
+    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g> – zbývá více než <xliff:g id="TIME_REMAINING">%2$s</xliff:g>"</string>
+    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"zbývá více než <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"telefon se brzy vypne"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"tablet se brzy vypne"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"zařízení se brzy vypne"</string>
+    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> – zbývá přibližně <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> – při vašem obvyklém využití zbývá asi <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> – telefon se brzy vypne"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> – tablet se brzy vypne"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> – zařízení se brzy vypne"</string>
     <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> – plně se nabije za <xliff:g id="TIME">^2</xliff:g>"</string>
+    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> – plně se nabije za <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Neznámé"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Nabíjí se"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"nabíjení"</string>
@@ -416,4 +431,8 @@
     <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"Nikdy"</string>
     <string name="zen_interruption_level_priority" msgid="2078370238113347720">"Pouze prioritní"</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>
+    <string name="zen_alarm_warning_indef" msgid="3007988140196673193">"Pokud tento režim nevypnete, svůj další budík <xliff:g id="WHEN">%1$s</xliff:g> neuslyšíte"</string>
+    <string name="zen_alarm_warning" msgid="6236690803924413088">"Svůj další budík <xliff:g id="WHEN">%1$s</xliff:g> neuslyšíte"</string>
+    <string name="alarm_template" msgid="4996153414057676512">"v <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template_far" msgid="3779172822607461675">"v <xliff:g id="WHEN">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index 14d07ff..88125d9 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -53,16 +53,16 @@
     <string name="bluetooth_disconnected" msgid="6557104142667339895">"Afbrudt"</string>
     <string name="bluetooth_disconnecting" msgid="8913264760027764974">"Afbryder ..."</string>
     <string name="bluetooth_connecting" msgid="8555009514614320497">"Opretter forbindelse..."</string>
-    <string name="bluetooth_connected" msgid="6038755206916626419">"Tilsluttet"</string>
+    <string name="bluetooth_connected" msgid="5427152882755735944">"Tilsluttet <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
     <string name="bluetooth_pairing" msgid="1426882272690346242">"Parrer..."</string>
-    <string name="bluetooth_connected_no_headset" msgid="2866994875046035609">"Forbundet (ingen telefon)"</string>
-    <string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Tilsluttet (intet medie)"</string>
-    <string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Forbundet (ingen adgang til meddelelse)"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Forbundet (ingen telefon eller medier)"</string>
-    <string name="bluetooth_connected_battery_level" msgid="7049181126136692368">"Tilsluttet – batteriniveau <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_headset_battery_level" msgid="5504193961248406027">"Tilsluttet (ingen telefon) – batteriniveau <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="4751724026365870779">"Tilsluttet (ingen medier) – batteriniveau <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1549265779323455261">"Tilsluttet (ingen telefon eller medier) – batteriniveau <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset" msgid="616068069034994802">"Tilsluttet <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> (ingen telefon)"</string>
+    <string name="bluetooth_connected_no_a2dp" msgid="3736431800395923868">"Tilsluttet <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> (ingen medier)"</string>
+    <string name="bluetooth_connected_no_map" msgid="3200033913678466453">"Tilsluttet <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> (ingen adgang til beskeder)"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2047403011284187056">"Tilsluttet <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> (ingen telefon eller medier)"</string>
+    <string name="bluetooth_connected_battery_level" msgid="5162924691231307748">"Tilsluttet <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> – batteriniveau <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"Tilsluttet <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (ingen telefon) – batteriniveau <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"Tilsluttet <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (ingen medier) – batteriniveau <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"Tilsluttet <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (ingen telefon eller medier) – batteriniveau <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Medielyd"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"Telefonopkald"</string>
     <string name="bluetooth_profile_opp" msgid="9168139293654233697">"Filoverførsel"</string>
@@ -75,6 +75,10 @@
     <string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM-adgang"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD-lyd: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD-lyd"</string>
+    <!-- no translation found for bluetooth_profile_hearing_aid (7999237886427812595) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (7188282786730266159) -->
+    <skip />
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Forbundet til medielyd"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Forbundet til telefonlyd"</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Forbundet til filoverførselsserver"</string>
@@ -91,6 +95,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Brug til telefonlyd"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Brug til filoverførsel"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Brug til input"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (908775281788309484) -->
+    <skip />
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Par"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"ACCEPTÉR PARRING"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Annuller"</string>
@@ -327,9 +333,10 @@
     <item msgid="8280754435979370728">"Naturlige farver, som øjet opfatter dem"</item>
     <item msgid="5363960654009010371">"Farver, der er optimeret til digitalt indhold"</item>
   </string-array>
-    <string name="inactive_apps_title" msgid="1317817863508274533">"Inaktive apps"</string>
+    <string name="inactive_apps_title" msgid="9042996804461901648">"Apps på standby"</string>
     <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"Inaktiv. Tryk for at skifte."</string>
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"Aktiv. Tryk for at skifte."</string>
+    <string name="standby_bucket_summary" msgid="6567835350910684727">"Standbystatus for appen:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="runningservices_settings_title" msgid="8097287939865165213">"Kørende tjenester"</string>
     <string name="runningservices_settings_summary" msgid="854608995821032748">"Vis og administrer kørende tjenester"</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView-implementering"</string>
@@ -351,16 +358,24 @@
     <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Korriger farver"</string>
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Denne funktion er eksperimentel og kan påvirke ydeevnen."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Tilsidesat af <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only" msgid="845431008899029842">"Ca. <xliff:g id="TIME">^1</xliff:g> tilbage"</string>
-    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Der er ca. <xliff:g id="TIME">^1</xliff:g> tilbage, alt efter hvordan du bruger enheden"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">^1</xliff:g> til det er fuldt opladet"</string>
-    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">^1</xliff:g> tilbage"</string>
-    <string name="power_remaining_duration_only_short_enhanced" msgid="7450425624026394823">"Der er <xliff:g id="TIME">^1</xliff:g> tilbage, alt efter hvordan du bruger enheden"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">^1</xliff:g> – ca. <xliff:g id="TIME">^2</xliff:g> tilbage"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">^1</xliff:g> – der er ca. <xliff:g id="TIME">^2</xliff:g> tilbage, alt efter hvordan du bruger enheden"</string>
-    <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> – <xliff:g id="TIME">^2</xliff:g> tilbage"</string>
+    <string name="power_remaining_duration_only" msgid="845431008899029842">"Ca. <xliff:g id="TIME">%1$s</xliff:g> tilbage"</string>
+    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Der er ca. <xliff:g id="TIME">%1$s</xliff:g> tilbage, alt efter hvordan du bruger enheden"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> til det er fuldt opladet"</string>
+    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">%1$s</xliff:g> tilbage"</string>
+    <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Der er mindre end <xliff:g id="THRESHOLD">%1$s</xliff:g> tilbage"</string>
+    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> – der er mindre end <xliff:g id="THRESHOLD">%2$s</xliff:g> tilbage"</string>
+    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g> – der er mere end <xliff:g id="TIME_REMAINING">%2$s</xliff:g> tilbage"</string>
+    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"der er mere end <xliff:g id="TIME_REMAINING">%1$s</xliff:g> tilbage"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"telefonen lukker muligvis snart ned"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"denne tablet lukker muligvis snart ned"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"enheden lukker muligvis snart ned"</string>
+    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> – ca. <xliff:g id="TIME">%2$s</xliff:g> tilbage"</string>
+    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> – der er ca. <xliff:g id="TIME">%2$s</xliff:g> tilbage, alt efter hvordan du bruger enheden"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> – telefonen lukker muligvis snart ned"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> – denne tablet lukker muligvis snart ned"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> – enheden lukker muligvis snart ned"</string>
     <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> til det er fuldt opladet"</string>
+    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> til det er fuldt opladet"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Ukendt"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Oplader"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"oplader"</string>
@@ -414,4 +429,8 @@
     <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"Aldrig"</string>
     <string name="zen_interruption_level_priority" msgid="2078370238113347720">"Kun prioritet"</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>
+    <string name="zen_alarm_warning_indef" msgid="3007988140196673193">"Du vil ikke kunne høre din næste alarm <xliff:g id="WHEN">%1$s</xliff:g>, medmindre du slår funktionen fra inden da"</string>
+    <string name="zen_alarm_warning" msgid="6236690803924413088">"Du vil ikke kunne høre din næste alarm <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template" msgid="4996153414057676512">"kl. <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template_far" msgid="3779172822607461675">"på <xliff:g id="WHEN">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-de/arrays.xml b/packages/SettingsLib/res/values-de/arrays.xml
index b5e3491..6f18183 100644
--- a/packages/SettingsLib/res/values-de/arrays.xml
+++ b/packages/SettingsLib/res/values-de/arrays.xml
@@ -234,10 +234,6 @@
     <item msgid="7688197031296835369">"Überschneidungsbereiche anzeigen"</item>
     <item msgid="2290859360633824369">"Bereiche für Deuteranomalie anzeigen"</item>
   </string-array>
-  <string-array name="debug_hw_renderer_entries">
-    <item msgid="2578620445459945681">"OpenGL (Standard)"</item>
-    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
-  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"Standardlimit"</item>
     <item msgid="4071574792028999443">"Keine Hintergrundprozesse"</item>
diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml
index cf8a1a2..aa4785b 100644
--- a/packages/SettingsLib/res/values-de/strings.xml
+++ b/packages/SettingsLib/res/values-de/strings.xml
@@ -53,16 +53,16 @@
     <string name="bluetooth_disconnected" msgid="6557104142667339895">"Nicht verbunden"</string>
     <string name="bluetooth_disconnecting" msgid="8913264760027764974">"Verbindung wird getrennt..."</string>
     <string name="bluetooth_connecting" msgid="8555009514614320497">"Verbindung wird hergestellt..."</string>
-    <string name="bluetooth_connected" msgid="6038755206916626419">"Verbunden"</string>
+    <string name="bluetooth_connected" msgid="5427152882755735944">"Mit <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> verbunden"</string>
     <string name="bluetooth_pairing" msgid="1426882272690346242">"Verbindung wird hergestellt…"</string>
-    <string name="bluetooth_connected_no_headset" msgid="2866994875046035609">"Verbunden (kein Telefon)"</string>
-    <string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Verbunden (außer Audiomedien)"</string>
-    <string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Verbunden (ohne Nachrichtenzugriff)"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Verbunden (außer Telefon- und Audiomedien)"</string>
-    <string name="bluetooth_connected_battery_level" msgid="7049181126136692368">"Verbunden, Akkustand: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_headset_battery_level" msgid="5504193961248406027">"Verbunden (außer Telefon), Akkustand: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="4751724026365870779">"Verbunden (außer Medienwiedergabe), Akkustand: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1549265779323455261">"Verbunden (außer Telefon und Medienwiedergabe), Akkustand: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset" msgid="616068069034994802">"Mit <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> verbunden (kein Telefon-Audio)"</string>
+    <string name="bluetooth_connected_no_a2dp" msgid="3736431800395923868">"Mit <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> verbunden (kein Media-Audio)"</string>
+    <string name="bluetooth_connected_no_map" msgid="3200033913678466453">"Mit <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> verbunden (kein Nachrichtenzugriff)"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2047403011284187056">"Mit <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> verbunden (weder Telefon- noch Media-Audio)"</string>
+    <string name="bluetooth_connected_battery_level" msgid="5162924691231307748">"Mit <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> verbunden, Akkustand bei <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"Mit <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> verbunden (kein Telefon-Audio), Akkustand bei <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"Mit <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> verbunden (kein Media-Audio), Akkustand bei <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"Mit <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> verbunden (weder Telefon- noch Media-Audio), Akkustand bei <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Media-Audio"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"Telefonanrufe"</string>
     <string name="bluetooth_profile_opp" msgid="9168139293654233697">"Dateiübertragung"</string>
@@ -75,6 +75,10 @@
     <string name="bluetooth_profile_sap" msgid="5764222021851283125">"Zugriff auf SIM"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD-Audio: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD-Audio"</string>
+    <!-- no translation found for bluetooth_profile_hearing_aid (7999237886427812595) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (7188282786730266159) -->
+    <skip />
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Verbunden mit  Audiosystem von Medien"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Verbunden mit Audiosystem des Telefons"</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Mit Dateiübertragungsserver verbunden"</string>
@@ -91,6 +95,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Für Audiosystem des Telefons verwenden"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Für Dateiübertragung verwenden"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Für Eingabe verwenden"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (908775281788309484) -->
+    <skip />
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Koppeln"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"KOPPELN"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Abbrechen"</string>
@@ -275,7 +281,6 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"Hardwareebenen-Updates"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Hardwareebenen blinken beim Aktualisieren grün"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"Debugging – GPU-Überschneidung"</string>
-    <string name="debug_hw_renderer" msgid="7568529019431785816">"GPU Renderer festlegen"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"HW-Overlays deaktivieren"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"GPU immer für Bildschirmaufbau verwenden"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"Farbraum simulieren"</string>
@@ -328,9 +333,10 @@
     <item msgid="8280754435979370728">"Natürliche Farben wie vom Auge wahrgenommen"</item>
     <item msgid="5363960654009010371">"Für digitale Inhalte optimierte Farben"</item>
   </string-array>
-    <string name="inactive_apps_title" msgid="1317817863508274533">"Inaktive Apps"</string>
+    <string name="inactive_apps_title" msgid="9042996804461901648">"Apps im Standby-Modus"</string>
     <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"Inaktiv. Zum Wechseln tippen."</string>
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"Aktiv. Zum Wechseln tippen."</string>
+    <string name="standby_bucket_summary" msgid="6567835350910684727">"Standby-Status der App:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="runningservices_settings_title" msgid="8097287939865165213">"Aktive Dienste"</string>
     <string name="runningservices_settings_summary" msgid="854608995821032748">"Momentan ausgeführte Dienste anzeigen und steuern"</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView-Implementierung"</string>
@@ -352,16 +358,24 @@
     <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Farbkorrektur"</string>
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Hierbei handelt es sich um eine experimentelle Funktion, die sich auf die Leistung auswirken kann."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Außer Kraft gesetzt von \"<xliff:g id="TITLE">%1$s</xliff:g>\""</string>
-    <string name="power_remaining_duration_only" msgid="845431008899029842">"Ca. <xliff:g id="TIME">^1</xliff:g> übrig"</string>
-    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Noch ca. <xliff:g id="TIME">^1</xliff:g>, basierend auf deiner Nutzung"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">^1</xliff:g> bis zur vollständigen Aufladung"</string>
-    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Noch <xliff:g id="TIME">^1</xliff:g>"</string>
-    <string name="power_remaining_duration_only_short_enhanced" msgid="7450425624026394823">"Noch <xliff:g id="TIME">^1</xliff:g>, basierend auf deiner Nutzung"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">^1</xliff:g> – ungefähr noch <xliff:g id="TIME">^2</xliff:g>"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">^1</xliff:g> – noch ca. <xliff:g id="TIME">^2</xliff:g>, basierend auf deiner Nutzung"</string>
-    <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> – noch <xliff:g id="TIME">^2</xliff:g>"</string>
+    <string name="power_remaining_duration_only" msgid="845431008899029842">"Ca. <xliff:g id="TIME">%1$s</xliff:g> übrig"</string>
+    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Noch ca. <xliff:g id="TIME">%1$s</xliff:g>, basierend auf deiner Nutzung"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> bis zur vollständigen Aufladung"</string>
+    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Noch <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Weniger als <xliff:g id="THRESHOLD">%1$s</xliff:g> verbleibend"</string>
+    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> – weniger als <xliff:g id="THRESHOLD">%2$s</xliff:g> verbleibend"</string>
+    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g> – mehr als <xliff:g id="TIME_REMAINING">%2$s</xliff:g> verbleibend"</string>
+    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"mehr als <xliff:g id="TIME_REMAINING">%1$s</xliff:g> verbleibend"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"Smartphone wird bald ausgeschaltet"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"Tablet wird bald ausgeschaltet"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"Gerät wird bald ausgeschaltet"</string>
+    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> – ungefähr noch <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> – noch ca. <xliff:g id="TIME">%2$s</xliff:g>, basierend auf deiner Nutzung"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> – Smartphone wird bald ausgeschaltet"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> – Tablet wird bald ausgeschaltet"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> – Gerät wird bald ausgeschaltet"</string>
     <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> bis vollständig geladen"</string>
+    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> bis vollständig geladen"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Unbekannt"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Wird aufgeladen"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"wird aufgeladen..."</string>
@@ -409,4 +423,14 @@
     </plurals>
     <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"Mehr Zeit."</string>
     <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"Weniger Zeit."</string>
+    <string name="zen_mode_enable_dialog_turn_on" msgid="8287824809739581837">"Aktivieren"</string>
+    <string name="cancel" msgid="6859253417269739139">"Abbrechen"</string>
+    <string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"\"Bitte nicht stören\" aktivieren"</string>
+    <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"Nie"</string>
+    <string name="zen_interruption_level_priority" msgid="2078370238113347720">"Nur wichtige Unterbrechungen"</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>
+    <string name="zen_alarm_warning_indef" msgid="3007988140196673193">"Falls du diesen Modus nicht vorher ausschaltest, wirst du deinen nächsten Weckruf <xliff:g id="WHEN">%1$s</xliff:g> nicht hören können"</string>
+    <string name="zen_alarm_warning" msgid="6236690803924413088">"Du wirst deinen nächsten Weckruf <xliff:g id="WHEN">%1$s</xliff:g> nicht hören können"</string>
+    <string name="alarm_template" msgid="4996153414057676512">"um <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template_far" msgid="3779172822607461675">"am <xliff:g id="WHEN">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-el/arrays.xml b/packages/SettingsLib/res/values-el/arrays.xml
index 1b740e6..8d3e3fa 100644
--- a/packages/SettingsLib/res/values-el/arrays.xml
+++ b/packages/SettingsLib/res/values-el/arrays.xml
@@ -234,10 +234,6 @@
     <item msgid="7688197031296835369">"Εμφάνιση περιοχών υπέρβασης"</item>
     <item msgid="2290859360633824369">"Εμφάνιση περιοχών για Deuteranomaly"</item>
   </string-array>
-  <string-array name="debug_hw_renderer_entries">
-    <item msgid="2578620445459945681">"OpenGL (προεπιλογή)"</item>
-    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
-  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"Τυπικό όριο"</item>
     <item msgid="4071574792028999443">"Δεν υπάρχουν διεργασίες παρασκηνίου"</item>
diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml
index 95dd4cd..998ef58 100644
--- a/packages/SettingsLib/res/values-el/strings.xml
+++ b/packages/SettingsLib/res/values-el/strings.xml
@@ -53,16 +53,16 @@
     <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>
+    <string name="bluetooth_connected" msgid="5427152882755735944">"Σε σύνδεση<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
     <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>
+    <string name="bluetooth_connected_no_headset" msgid="616068069034994802">"Σε σύνδεση (χωρίς τηλέφωνο)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp" msgid="3736431800395923868">"Σε σύνδεση (χωρίς μέσα)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_map" msgid="3200033913678466453">"Σε σύνδεση (χωρίς πρόσβαση σε μηνύματα)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2047403011284187056">"Σε σύνδεση (χωρίς τηλέφωνο ή μέσα)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_battery_level" msgid="5162924691231307748">"Σε σύνδεση, μπαταρία <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"Σε σύνδεση (χωρίς τηλέφωνο), μπαταρία <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"Σε σύνδεση (χωρίς μέσα), μπαταρία <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"Σε σύνδεση (χωρίς τηλέφωνο ή μέσα), μπαταρία <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Ήχος πολυμέσων"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"Τηλεφωνικές κλήσεις"</string>
     <string name="bluetooth_profile_opp" msgid="9168139293654233697">"Μεταφορά αρχείου"</string>
@@ -75,6 +75,10 @@
     <string name="bluetooth_profile_sap" msgid="5764222021851283125">"Πρόσβαση SIM"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"Ήχος HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"Ήχος HD"</string>
+    <!-- no translation found for bluetooth_profile_hearing_aid (7999237886427812595) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (7188282786730266159) -->
+    <skip />
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Συνδέθηκε σε ήχο πολυμέσων"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Συνδεδεμένο στον ήχο τηλεφώνου"</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Συνδεδεμένο σε διακομιστή μεταφοράς αρχείων"</string>
@@ -91,6 +95,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Χρήση για ήχο τηλεφώνου"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Χρήση για τη μεταφορά αρχείων"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Χρήση για είσοδο"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (908775281788309484) -->
+    <skip />
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Σύζευξη"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"ΣΥΖΕΥΞΗ"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Ακύρωση"</string>
@@ -275,7 +281,6 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"Εμφ. ενημ. επιπ. υλικού"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Επισήμ. επιπέδων υλικού με πράσινο κατά την ενημ."</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"Κατάρ.σφαλμ.υπέρβ.GPU"</string>
-    <string name="debug_hw_renderer" msgid="7568529019431785816">"Ρύθμ. λειτ. απόδοσης GPU"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"Απενεργ. επικαλύψεων HW"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"Να γίνεται πάντα χρήση του GPU για σύνθεση οθόνης"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"Προσομοίωση χρωματικού χώρου"</string>
@@ -328,9 +333,10 @@
     <item msgid="8280754435979370728">"Φυσικά χρώματα όπως είναι ορατά στο μάτι"</item>
     <item msgid="5363960654009010371">"Βελτιστοποιημένα χρώματα για ψηφιακό περιεχόμενο"</item>
   </string-array>
-    <string name="inactive_apps_title" msgid="1317817863508274533">"Ανενεργές εφαρμογές"</string>
+    <string name="inactive_apps_title" msgid="9042996804461901648">"Εφαρμογές σε κατάσταση αναμονής"</string>
     <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"Ανενεργό. Πατήστε για εναλλαγή."</string>
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"Ενεργό. Πατήστε για εναλλαγή."</string>
+    <string name="standby_bucket_summary" msgid="6567835350910684727">"Κατάσταση αναμονής εφαρμογής:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <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>
@@ -352,16 +358,24 @@
     <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>
+    <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Απομένει/ουν λιγότερo/α από <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
+    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> - Απομένει λιγότερo από <xliff:g id="THRESHOLD">%2$s</xliff:g>"</string>
+    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g> - Απομένει περισσότερο από <xliff:g id="TIME_REMAINING">%2$s</xliff:g>"</string>
+    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"απομένουν περισσότερα/ες από <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"το τηλέφωνο μπορεί να απενεργοποιηθεί σύντομα"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"το tablet μπορεί να απενεργοποιηθεί σύντομα"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"η συσκευή μπορεί να απενεργοποιηθεί σύντομα"</string>
+    <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>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> - το τηλέφωνο μπορεί να απενεργοποιηθεί σύντομα"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> - το tablet μπορεί να απενεργοποιηθεί σύντομα"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> - η συσκευή μπορεί να απενεργοποιηθεί σύντομα"</string>
     <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>
@@ -409,4 +423,14 @@
     </plurals>
     <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"Περισσότερη ώρα."</string>
     <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"Λιγότερη ώρα."</string>
+    <string name="zen_mode_enable_dialog_turn_on" msgid="8287824809739581837">"Ενεργοποίηση"</string>
+    <string name="cancel" msgid="6859253417269739139">"Ακύρωση"</string>
+    <string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"Ενεργοποίηση λειτουργίας \"Μην ενοχλείτε\""</string>
+    <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>
+    <string name="zen_alarm_warning_indef" msgid="3007988140196673193">"Δεν θα ακούσετε το επόμενο ξυπνητήρι <xliff:g id="WHEN">%1$s</xliff:g>, εκτός εάν το απενεργοποιήσετε νωρίτερα"</string>
+    <string name="zen_alarm_warning" msgid="6236690803924413088">"Δεν θα ακούσετε το επόμενο ξυπνητήρι <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template" msgid="4996153414057676512">"στις <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template_far" msgid="3779172822607461675">"το/τη(ν) <xliff:g id="WHEN">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml
index 9b82b7c..0dc380b1 100644
--- a/packages/SettingsLib/res/values-en-rAU/strings.xml
+++ b/packages/SettingsLib/res/values-en-rAU/strings.xml
@@ -53,16 +53,16 @@
     <string name="bluetooth_disconnected" msgid="6557104142667339895">"Disconnected"</string>
     <string name="bluetooth_disconnecting" msgid="8913264760027764974">"Disconnecting…"</string>
     <string name="bluetooth_connecting" msgid="8555009514614320497">"Connecting…"</string>
-    <string name="bluetooth_connected" msgid="6038755206916626419">"Connected"</string>
+    <string name="bluetooth_connected" msgid="5427152882755735944">"Connected<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
     <string name="bluetooth_pairing" msgid="1426882272690346242">"Pairing…"</string>
-    <string name="bluetooth_connected_no_headset" msgid="2866994875046035609">"Connected (no phone)"</string>
-    <string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Connected (no media)"</string>
-    <string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Connected (no message access)"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Connected (no phone or media)"</string>
-    <string name="bluetooth_connected_battery_level" msgid="7049181126136692368">"Connected, battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_headset_battery_level" msgid="5504193961248406027">"Connected (no phone), battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="4751724026365870779">"Connected (no media), battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1549265779323455261">"Connected (no phone or media), battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset" msgid="616068069034994802">"Connected (no phone)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp" msgid="3736431800395923868">"Connected (no media)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_map" msgid="3200033913678466453">"Connected (no message access)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2047403011284187056">"Connected (no phone or media)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_battery_level" msgid="5162924691231307748">"Connected, battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"Connected (no phone), battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"Connected (no media), battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"Connected (no phone or media), battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Media audio"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"Phone calls"</string>
     <string name="bluetooth_profile_opp" msgid="9168139293654233697">"File transfer"</string>
@@ -75,6 +75,10 @@
     <string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM Access"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD audio: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD audio"</string>
+    <!-- no translation found for bluetooth_profile_hearing_aid (7999237886427812595) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (7188282786730266159) -->
+    <skip />
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Connected to media audio"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Connected to phone audio"</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Connected to file-transfer server"</string>
@@ -91,6 +95,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Use for phone audio"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Use for file transfer"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Use for input"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (908775281788309484) -->
+    <skip />
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Pair"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"PAIR"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Cancel"</string>
@@ -327,9 +333,10 @@
     <item msgid="8280754435979370728">"Natural colours as seen by the eye"</item>
     <item msgid="5363960654009010371">"Colours optimised for digital content"</item>
   </string-array>
-    <string name="inactive_apps_title" msgid="1317817863508274533">"Inactive apps"</string>
+    <string name="inactive_apps_title" msgid="9042996804461901648">"Standby apps"</string>
     <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"Inactive. Tap to toggle."</string>
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"Active. Tap to toggle."</string>
+    <string name="standby_bucket_summary" msgid="6567835350910684727">"App standby state:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="runningservices_settings_title" msgid="8097287939865165213">"Running services"</string>
     <string name="runningservices_settings_summary" msgid="854608995821032748">"View and control currently running services"</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView implementation"</string>
@@ -351,16 +358,24 @@
     <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Colour correction"</string>
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"This feature is experimental and may affect performance."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Overridden by <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only" msgid="845431008899029842">"About <xliff:g id="TIME">^1</xliff:g> left"</string>
-    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"About <xliff:g id="TIME">^1</xliff:g> left based on your usage"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">^1</xliff:g> left until fully charged"</string>
-    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">^1</xliff:g> left"</string>
-    <string name="power_remaining_duration_only_short_enhanced" msgid="7450425624026394823">"<xliff:g id="TIME">^1</xliff:g> left based on your usage"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">^1</xliff:g> – about <xliff:g id="TIME">^2</xliff:g> left"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">^1</xliff:g> - about <xliff:g id="TIME">^2</xliff:g> left based on your usage"</string>
-    <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g> left"</string>
+    <string name="power_remaining_duration_only" msgid="845431008899029842">"About <xliff:g id="TIME">%1$s</xliff:g> left"</string>
+    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"About <xliff:g id="TIME">%1$s</xliff:g> left based on your usage"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> left until fully charged"</string>
+    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">%1$s</xliff:g> left"</string>
+    <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Less than <xliff:g id="THRESHOLD">%1$s</xliff:g> remaining"</string>
+    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> - Less than <xliff:g id="THRESHOLD">%2$s</xliff:g> remaining"</string>
+    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g>more than <xliff:g id="TIME_REMAINING">%2$s</xliff:g> remaining"</string>
+    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"more than <xliff:g id="TIME_REMAINING">%1$s</xliff:g> remaining"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"phone may shutdown soon"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"tablet may shutdown soon"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"device may shutdown soon"</string>
+    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> – about <xliff:g id="TIME">%2$s</xliff:g> left"</string>
+    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> - about <xliff:g id="TIME">%2$s</xliff:g> left based on your usage"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> - phone may shutdown soon"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> - tablet may shutdown soon"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> - device may shutdown soon"</string>
     <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> until fully charged"</string>
+    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> until fully charged"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Unknown"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Charging"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"charging"</string>
@@ -414,4 +429,8 @@
     <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"Never"</string>
     <string name="zen_interruption_level_priority" msgid="2078370238113347720">"Priority only"</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>
+    <string name="zen_alarm_warning_indef" msgid="3007988140196673193">"You won\'t hear your next alarm <xliff:g id="WHEN">%1$s</xliff:g> unless you turn this off before then"</string>
+    <string name="zen_alarm_warning" msgid="6236690803924413088">"You won\'t hear your next alarm <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template" msgid="4996153414057676512">"at <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template_far" msgid="3779172822607461675">"on <xliff:g id="WHEN">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-en-rCA/strings.xml b/packages/SettingsLib/res/values-en-rCA/strings.xml
index 9b82b7c..0dc380b1 100644
--- a/packages/SettingsLib/res/values-en-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-en-rCA/strings.xml
@@ -53,16 +53,16 @@
     <string name="bluetooth_disconnected" msgid="6557104142667339895">"Disconnected"</string>
     <string name="bluetooth_disconnecting" msgid="8913264760027764974">"Disconnecting…"</string>
     <string name="bluetooth_connecting" msgid="8555009514614320497">"Connecting…"</string>
-    <string name="bluetooth_connected" msgid="6038755206916626419">"Connected"</string>
+    <string name="bluetooth_connected" msgid="5427152882755735944">"Connected<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
     <string name="bluetooth_pairing" msgid="1426882272690346242">"Pairing…"</string>
-    <string name="bluetooth_connected_no_headset" msgid="2866994875046035609">"Connected (no phone)"</string>
-    <string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Connected (no media)"</string>
-    <string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Connected (no message access)"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Connected (no phone or media)"</string>
-    <string name="bluetooth_connected_battery_level" msgid="7049181126136692368">"Connected, battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_headset_battery_level" msgid="5504193961248406027">"Connected (no phone), battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="4751724026365870779">"Connected (no media), battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1549265779323455261">"Connected (no phone or media), battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset" msgid="616068069034994802">"Connected (no phone)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp" msgid="3736431800395923868">"Connected (no media)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_map" msgid="3200033913678466453">"Connected (no message access)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2047403011284187056">"Connected (no phone or media)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_battery_level" msgid="5162924691231307748">"Connected, battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"Connected (no phone), battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"Connected (no media), battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"Connected (no phone or media), battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Media audio"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"Phone calls"</string>
     <string name="bluetooth_profile_opp" msgid="9168139293654233697">"File transfer"</string>
@@ -75,6 +75,10 @@
     <string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM Access"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD audio: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD audio"</string>
+    <!-- no translation found for bluetooth_profile_hearing_aid (7999237886427812595) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (7188282786730266159) -->
+    <skip />
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Connected to media audio"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Connected to phone audio"</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Connected to file-transfer server"</string>
@@ -91,6 +95,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Use for phone audio"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Use for file transfer"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Use for input"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (908775281788309484) -->
+    <skip />
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Pair"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"PAIR"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Cancel"</string>
@@ -327,9 +333,10 @@
     <item msgid="8280754435979370728">"Natural colours as seen by the eye"</item>
     <item msgid="5363960654009010371">"Colours optimised for digital content"</item>
   </string-array>
-    <string name="inactive_apps_title" msgid="1317817863508274533">"Inactive apps"</string>
+    <string name="inactive_apps_title" msgid="9042996804461901648">"Standby apps"</string>
     <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"Inactive. Tap to toggle."</string>
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"Active. Tap to toggle."</string>
+    <string name="standby_bucket_summary" msgid="6567835350910684727">"App standby state:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="runningservices_settings_title" msgid="8097287939865165213">"Running services"</string>
     <string name="runningservices_settings_summary" msgid="854608995821032748">"View and control currently running services"</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView implementation"</string>
@@ -351,16 +358,24 @@
     <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Colour correction"</string>
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"This feature is experimental and may affect performance."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Overridden by <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only" msgid="845431008899029842">"About <xliff:g id="TIME">^1</xliff:g> left"</string>
-    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"About <xliff:g id="TIME">^1</xliff:g> left based on your usage"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">^1</xliff:g> left until fully charged"</string>
-    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">^1</xliff:g> left"</string>
-    <string name="power_remaining_duration_only_short_enhanced" msgid="7450425624026394823">"<xliff:g id="TIME">^1</xliff:g> left based on your usage"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">^1</xliff:g> – about <xliff:g id="TIME">^2</xliff:g> left"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">^1</xliff:g> - about <xliff:g id="TIME">^2</xliff:g> left based on your usage"</string>
-    <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g> left"</string>
+    <string name="power_remaining_duration_only" msgid="845431008899029842">"About <xliff:g id="TIME">%1$s</xliff:g> left"</string>
+    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"About <xliff:g id="TIME">%1$s</xliff:g> left based on your usage"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> left until fully charged"</string>
+    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">%1$s</xliff:g> left"</string>
+    <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Less than <xliff:g id="THRESHOLD">%1$s</xliff:g> remaining"</string>
+    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> - Less than <xliff:g id="THRESHOLD">%2$s</xliff:g> remaining"</string>
+    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g>more than <xliff:g id="TIME_REMAINING">%2$s</xliff:g> remaining"</string>
+    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"more than <xliff:g id="TIME_REMAINING">%1$s</xliff:g> remaining"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"phone may shutdown soon"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"tablet may shutdown soon"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"device may shutdown soon"</string>
+    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> – about <xliff:g id="TIME">%2$s</xliff:g> left"</string>
+    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> - about <xliff:g id="TIME">%2$s</xliff:g> left based on your usage"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> - phone may shutdown soon"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> - tablet may shutdown soon"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> - device may shutdown soon"</string>
     <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> until fully charged"</string>
+    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> until fully charged"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Unknown"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Charging"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"charging"</string>
@@ -414,4 +429,8 @@
     <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"Never"</string>
     <string name="zen_interruption_level_priority" msgid="2078370238113347720">"Priority only"</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>
+    <string name="zen_alarm_warning_indef" msgid="3007988140196673193">"You won\'t hear your next alarm <xliff:g id="WHEN">%1$s</xliff:g> unless you turn this off before then"</string>
+    <string name="zen_alarm_warning" msgid="6236690803924413088">"You won\'t hear your next alarm <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template" msgid="4996153414057676512">"at <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template_far" msgid="3779172822607461675">"on <xliff:g id="WHEN">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml
index 9b82b7c..0dc380b1 100644
--- a/packages/SettingsLib/res/values-en-rGB/strings.xml
+++ b/packages/SettingsLib/res/values-en-rGB/strings.xml
@@ -53,16 +53,16 @@
     <string name="bluetooth_disconnected" msgid="6557104142667339895">"Disconnected"</string>
     <string name="bluetooth_disconnecting" msgid="8913264760027764974">"Disconnecting…"</string>
     <string name="bluetooth_connecting" msgid="8555009514614320497">"Connecting…"</string>
-    <string name="bluetooth_connected" msgid="6038755206916626419">"Connected"</string>
+    <string name="bluetooth_connected" msgid="5427152882755735944">"Connected<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
     <string name="bluetooth_pairing" msgid="1426882272690346242">"Pairing…"</string>
-    <string name="bluetooth_connected_no_headset" msgid="2866994875046035609">"Connected (no phone)"</string>
-    <string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Connected (no media)"</string>
-    <string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Connected (no message access)"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Connected (no phone or media)"</string>
-    <string name="bluetooth_connected_battery_level" msgid="7049181126136692368">"Connected, battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_headset_battery_level" msgid="5504193961248406027">"Connected (no phone), battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="4751724026365870779">"Connected (no media), battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1549265779323455261">"Connected (no phone or media), battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset" msgid="616068069034994802">"Connected (no phone)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp" msgid="3736431800395923868">"Connected (no media)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_map" msgid="3200033913678466453">"Connected (no message access)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2047403011284187056">"Connected (no phone or media)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_battery_level" msgid="5162924691231307748">"Connected, battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"Connected (no phone), battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"Connected (no media), battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"Connected (no phone or media), battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Media audio"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"Phone calls"</string>
     <string name="bluetooth_profile_opp" msgid="9168139293654233697">"File transfer"</string>
@@ -75,6 +75,10 @@
     <string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM Access"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD audio: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD audio"</string>
+    <!-- no translation found for bluetooth_profile_hearing_aid (7999237886427812595) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (7188282786730266159) -->
+    <skip />
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Connected to media audio"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Connected to phone audio"</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Connected to file-transfer server"</string>
@@ -91,6 +95,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Use for phone audio"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Use for file transfer"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Use for input"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (908775281788309484) -->
+    <skip />
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Pair"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"PAIR"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Cancel"</string>
@@ -327,9 +333,10 @@
     <item msgid="8280754435979370728">"Natural colours as seen by the eye"</item>
     <item msgid="5363960654009010371">"Colours optimised for digital content"</item>
   </string-array>
-    <string name="inactive_apps_title" msgid="1317817863508274533">"Inactive apps"</string>
+    <string name="inactive_apps_title" msgid="9042996804461901648">"Standby apps"</string>
     <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"Inactive. Tap to toggle."</string>
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"Active. Tap to toggle."</string>
+    <string name="standby_bucket_summary" msgid="6567835350910684727">"App standby state:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="runningservices_settings_title" msgid="8097287939865165213">"Running services"</string>
     <string name="runningservices_settings_summary" msgid="854608995821032748">"View and control currently running services"</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView implementation"</string>
@@ -351,16 +358,24 @@
     <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Colour correction"</string>
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"This feature is experimental and may affect performance."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Overridden by <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only" msgid="845431008899029842">"About <xliff:g id="TIME">^1</xliff:g> left"</string>
-    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"About <xliff:g id="TIME">^1</xliff:g> left based on your usage"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">^1</xliff:g> left until fully charged"</string>
-    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">^1</xliff:g> left"</string>
-    <string name="power_remaining_duration_only_short_enhanced" msgid="7450425624026394823">"<xliff:g id="TIME">^1</xliff:g> left based on your usage"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">^1</xliff:g> – about <xliff:g id="TIME">^2</xliff:g> left"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">^1</xliff:g> - about <xliff:g id="TIME">^2</xliff:g> left based on your usage"</string>
-    <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g> left"</string>
+    <string name="power_remaining_duration_only" msgid="845431008899029842">"About <xliff:g id="TIME">%1$s</xliff:g> left"</string>
+    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"About <xliff:g id="TIME">%1$s</xliff:g> left based on your usage"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> left until fully charged"</string>
+    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">%1$s</xliff:g> left"</string>
+    <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Less than <xliff:g id="THRESHOLD">%1$s</xliff:g> remaining"</string>
+    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> - Less than <xliff:g id="THRESHOLD">%2$s</xliff:g> remaining"</string>
+    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g>more than <xliff:g id="TIME_REMAINING">%2$s</xliff:g> remaining"</string>
+    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"more than <xliff:g id="TIME_REMAINING">%1$s</xliff:g> remaining"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"phone may shutdown soon"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"tablet may shutdown soon"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"device may shutdown soon"</string>
+    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> – about <xliff:g id="TIME">%2$s</xliff:g> left"</string>
+    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> - about <xliff:g id="TIME">%2$s</xliff:g> left based on your usage"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> - phone may shutdown soon"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> - tablet may shutdown soon"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> - device may shutdown soon"</string>
     <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> until fully charged"</string>
+    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> until fully charged"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Unknown"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Charging"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"charging"</string>
@@ -414,4 +429,8 @@
     <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"Never"</string>
     <string name="zen_interruption_level_priority" msgid="2078370238113347720">"Priority only"</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>
+    <string name="zen_alarm_warning_indef" msgid="3007988140196673193">"You won\'t hear your next alarm <xliff:g id="WHEN">%1$s</xliff:g> unless you turn this off before then"</string>
+    <string name="zen_alarm_warning" msgid="6236690803924413088">"You won\'t hear your next alarm <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template" msgid="4996153414057676512">"at <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template_far" msgid="3779172822607461675">"on <xliff:g id="WHEN">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml
index 9b82b7c..0dc380b1 100644
--- a/packages/SettingsLib/res/values-en-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-en-rIN/strings.xml
@@ -53,16 +53,16 @@
     <string name="bluetooth_disconnected" msgid="6557104142667339895">"Disconnected"</string>
     <string name="bluetooth_disconnecting" msgid="8913264760027764974">"Disconnecting…"</string>
     <string name="bluetooth_connecting" msgid="8555009514614320497">"Connecting…"</string>
-    <string name="bluetooth_connected" msgid="6038755206916626419">"Connected"</string>
+    <string name="bluetooth_connected" msgid="5427152882755735944">"Connected<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
     <string name="bluetooth_pairing" msgid="1426882272690346242">"Pairing…"</string>
-    <string name="bluetooth_connected_no_headset" msgid="2866994875046035609">"Connected (no phone)"</string>
-    <string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Connected (no media)"</string>
-    <string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Connected (no message access)"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Connected (no phone or media)"</string>
-    <string name="bluetooth_connected_battery_level" msgid="7049181126136692368">"Connected, battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_headset_battery_level" msgid="5504193961248406027">"Connected (no phone), battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="4751724026365870779">"Connected (no media), battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1549265779323455261">"Connected (no phone or media), battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset" msgid="616068069034994802">"Connected (no phone)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp" msgid="3736431800395923868">"Connected (no media)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_map" msgid="3200033913678466453">"Connected (no message access)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2047403011284187056">"Connected (no phone or media)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_battery_level" msgid="5162924691231307748">"Connected, battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"Connected (no phone), battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"Connected (no media), battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"Connected (no phone or media), battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Media audio"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"Phone calls"</string>
     <string name="bluetooth_profile_opp" msgid="9168139293654233697">"File transfer"</string>
@@ -75,6 +75,10 @@
     <string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM Access"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD audio: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD audio"</string>
+    <!-- no translation found for bluetooth_profile_hearing_aid (7999237886427812595) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (7188282786730266159) -->
+    <skip />
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Connected to media audio"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Connected to phone audio"</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Connected to file-transfer server"</string>
@@ -91,6 +95,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Use for phone audio"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Use for file transfer"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Use for input"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (908775281788309484) -->
+    <skip />
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Pair"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"PAIR"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Cancel"</string>
@@ -327,9 +333,10 @@
     <item msgid="8280754435979370728">"Natural colours as seen by the eye"</item>
     <item msgid="5363960654009010371">"Colours optimised for digital content"</item>
   </string-array>
-    <string name="inactive_apps_title" msgid="1317817863508274533">"Inactive apps"</string>
+    <string name="inactive_apps_title" msgid="9042996804461901648">"Standby apps"</string>
     <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"Inactive. Tap to toggle."</string>
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"Active. Tap to toggle."</string>
+    <string name="standby_bucket_summary" msgid="6567835350910684727">"App standby state:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="runningservices_settings_title" msgid="8097287939865165213">"Running services"</string>
     <string name="runningservices_settings_summary" msgid="854608995821032748">"View and control currently running services"</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView implementation"</string>
@@ -351,16 +358,24 @@
     <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Colour correction"</string>
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"This feature is experimental and may affect performance."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Overridden by <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only" msgid="845431008899029842">"About <xliff:g id="TIME">^1</xliff:g> left"</string>
-    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"About <xliff:g id="TIME">^1</xliff:g> left based on your usage"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">^1</xliff:g> left until fully charged"</string>
-    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">^1</xliff:g> left"</string>
-    <string name="power_remaining_duration_only_short_enhanced" msgid="7450425624026394823">"<xliff:g id="TIME">^1</xliff:g> left based on your usage"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">^1</xliff:g> – about <xliff:g id="TIME">^2</xliff:g> left"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">^1</xliff:g> - about <xliff:g id="TIME">^2</xliff:g> left based on your usage"</string>
-    <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g> left"</string>
+    <string name="power_remaining_duration_only" msgid="845431008899029842">"About <xliff:g id="TIME">%1$s</xliff:g> left"</string>
+    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"About <xliff:g id="TIME">%1$s</xliff:g> left based on your usage"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> left until fully charged"</string>
+    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">%1$s</xliff:g> left"</string>
+    <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Less than <xliff:g id="THRESHOLD">%1$s</xliff:g> remaining"</string>
+    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> - Less than <xliff:g id="THRESHOLD">%2$s</xliff:g> remaining"</string>
+    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g>more than <xliff:g id="TIME_REMAINING">%2$s</xliff:g> remaining"</string>
+    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"more than <xliff:g id="TIME_REMAINING">%1$s</xliff:g> remaining"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"phone may shutdown soon"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"tablet may shutdown soon"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"device may shutdown soon"</string>
+    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> – about <xliff:g id="TIME">%2$s</xliff:g> left"</string>
+    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> - about <xliff:g id="TIME">%2$s</xliff:g> left based on your usage"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> - phone may shutdown soon"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> - tablet may shutdown soon"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> - device may shutdown soon"</string>
     <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> until fully charged"</string>
+    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> until fully charged"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Unknown"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Charging"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"charging"</string>
@@ -414,4 +429,8 @@
     <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"Never"</string>
     <string name="zen_interruption_level_priority" msgid="2078370238113347720">"Priority only"</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>
+    <string name="zen_alarm_warning_indef" msgid="3007988140196673193">"You won\'t hear your next alarm <xliff:g id="WHEN">%1$s</xliff:g> unless you turn this off before then"</string>
+    <string name="zen_alarm_warning" msgid="6236690803924413088">"You won\'t hear your next alarm <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template" msgid="4996153414057676512">"at <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template_far" msgid="3779172822607461675">"on <xliff:g id="WHEN">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-en-rXC/strings.xml b/packages/SettingsLib/res/values-en-rXC/strings.xml
index 7eb1b31..2ccfe85 100644
--- a/packages/SettingsLib/res/values-en-rXC/strings.xml
+++ b/packages/SettingsLib/res/values-en-rXC/strings.xml
@@ -53,16 +53,16 @@
     <string name="bluetooth_disconnected" msgid="6557104142667339895">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‏‎‏‎‏‏‏‏‏‏‏‏‏‎‎‎‎‎‏‏‎‏‏‏‏‎‏‎‎‎‎‎‏‎‏‎‏‏‏‎‏‏‎‏‏‏‎‏‏‎‎‎‎‏‏‏‎‏‏‏‎Disconnected‎‏‎‎‏‎"</string>
     <string name="bluetooth_disconnecting" msgid="8913264760027764974">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‏‎‏‏‏‎‏‏‎‎‏‎‎‏‎‎‎‏‏‏‎‎‎‏‎‎‏‏‎‎‏‎‎‎‏‎‎‏‏‏‎‏‏‎‎‏‎‏‏‎‎‎‏‏‏‎‏‏‏‎‎Disconnecting…‎‏‎‎‏‎"</string>
     <string name="bluetooth_connecting" msgid="8555009514614320497">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‎‏‏‎‏‎‏‏‏‎‎‏‎‏‏‏‏‏‏‏‏‏‎‏‎‎‏‏‏‏‎‎‎‎‎‎‏‎‏‎‏‏‎‎‎‏‏‎‏‏‎‏‎‏‏‏‎‎‎‏‎Connecting…‎‏‎‎‏‎"</string>
-    <string name="bluetooth_connected" msgid="6038755206916626419">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‎‎‏‏‏‏‎‎‏‏‎‏‏‏‏‏‎‏‏‏‏‏‎‏‏‏‎‏‏‎‏‏‎‎‎‏‏‏‎‎‏‏‏‎‎‏‎‏‎‏‏‏‏‏‏‏‎‎‏‏‎Connected‎‏‎‎‏‎"</string>
+    <string name="bluetooth_connected" msgid="5427152882755735944">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‏‎‏‏‎‏‎‏‎‎‎‏‎‎‎‏‏‏‏‎‏‏‎‎‏‎‏‎‏‏‏‎‎‏‏‎‎‏‏‎‎‏‎‎‏‎‎‏‎‎‎‏‏‎‎‎‏‎‎‎‎Connected‎‏‎‎‏‏‎<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <string name="bluetooth_pairing" msgid="1426882272690346242">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‎‎‏‏‏‏‎‎‏‏‎‏‎‏‎‎‏‏‎‏‏‏‎‏‏‏‎‏‏‏‏‏‏‎‎‎‎‎‎‎‎‎‏‎‏‎‎‏‏‎‎‏‎‎‎‎‎‎‏‎‎Pairing…‎‏‎‎‏‎"</string>
-    <string name="bluetooth_connected_no_headset" msgid="2866994875046035609">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‎‏‏‏‏‏‎‎‏‎‎‏‏‎‎‏‏‏‎‎‏‎‏‎‎‏‏‎‎‎‎‏‏‎‏‏‏‏‏‏‏‏‎‎‎‎‎‎‎‎‎‎‏‎‎‏‏‎‎‏‎Connected (no phone)‎‏‎‎‏‎"</string>
-    <string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‏‏‏‏‏‎‎‎‎‎‎‏‏‏‏‎‎‎‏‏‎‏‎‎‏‎‎‏‏‎‎‏‎‏‏‎‎‏‏‏‎‏‎‎‎‎‎‎‏‏‎‏‎‏‎‏‎‎‎‏‎Connected (no media)‎‏‎‎‏‎"</string>
-    <string name="bluetooth_connected_no_map" msgid="6504436917057479986">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‏‎‏‎‎‏‎‎‎‏‎‎‎‏‏‎‎‏‏‎‏‏‏‎‏‎‏‎‎‎‎‎‎‎‎‏‎‎‏‎‎‏‎‏‏‏‏‎‎‏‎‏‎‎‏‏‎‎‏‎‎Connected (no message access)‎‏‎‎‏‎"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‎‏‏‏‎‏‏‏‏‎‎‏‎‎‏‏‏‏‎‏‏‏‏‎‏‏‏‎‎‎‎‎‎‎‎‎‎‏‎‎‎‏‎‎‏‎‎‎‎‏‎‎‏‎‎Connected (no phone or media)‎‏‎‎‏‎"</string>
-    <string name="bluetooth_connected_battery_level" msgid="7049181126136692368">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‎‎‎‏‏‏‎‏‎‎‏‏‏‎‏‏‏‎‎‎‏‏‏‎‎‎‏‎‏‏‎‏‎‏‎‎‏‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‎‏‎‎‎‎‎Connected, battery ‎‏‎‎‏‏‎<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
-    <string name="bluetooth_connected_no_headset_battery_level" msgid="5504193961248406027">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‏‏‎‎‎‏‏‎‎‎‏‎‏‏‎‏‎‎‏‏‎‎‏‏‏‏‏‎‏‏‎‎‏‎‏‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‏‎‎‎‎‎‏‎‏‏‎Connected (no phone), battery ‎‏‎‎‏‏‎<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
-    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="4751724026365870779">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‎‎‎‏‏‏‏‏‎‎‎‏‏‎‎‎‎‎‏‏‏‏‎‏‎‎‏‏‏‎‎‎‎‏‏‎‎‎‏‏‏‎‏‎‎‎‎‎‎‎‏‎‏‎‏‏‏‎‏‏‎Connected (no media), battery ‎‏‎‎‏‏‎<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1549265779323455261">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‎‏‎‏‏‎‎‎‎‎‎‎‎‎‎‏‏‎‎‏‎‎‎‎‎‏‎‎‏‎‎‏‎‏‏‏‎‎‏‏‏‏‏‎‎‏‎‎‎‏‏‏‎‎‎‏‏‏‎‏‎Connected (no phone or media), battery ‎‏‎‎‏‏‎<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+    <string name="bluetooth_connected_no_headset" msgid="616068069034994802">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‎‏‎‎‎‏‎‎‎‏‏‎‎‏‎‏‏‎‏‏‎‏‎‏‎‎‏‎‏‎‎‎‎‏‏‎‎‎‏‎‎‏‎‏‎‏‎‏‎‏‏‎‎‎‏‏‏‎‎‏‎‎Connected (no phone)‎‏‎‎‏‏‎<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+    <string name="bluetooth_connected_no_a2dp" msgid="3736431800395923868">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‎‎‏‏‏‏‎‏‏‎‏‎‎‏‏‏‏‎‎‎‏‏‏‎‏‏‎‏‎‎‎‎‏‏‏‎‎‎‎‏‎‎‏‎‏‎‎‎‎‎‎‏‏‎‎‏‏‏‎‎‎Connected (no media)‎‏‎‎‏‏‎<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+    <string name="bluetooth_connected_no_map" msgid="3200033913678466453">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‏‏‎‎‎‏‏‎‏‎‎‎‏‏‎‎‏‏‎‏‏‏‏‎‎‎‏‏‏‏‎‏‎‏‏‎‎‎‎‎‎‎‏‎‎‎‎‎‏‏‎‏‏‎‎‏‎‏‎‏‎Connected (no message access)‎‏‎‎‏‏‎<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2047403011284187056">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‏‏‎‎‎‏‏‎‏‎‎‏‏‏‎‏‎‏‏‎‎‎‏‏‎‎‎‎‏‏‏‎‏‏‏‏‏‎‏‎‏‎‎‎‏‎‏‏‎‏‏‏‏‎‏‏‎‎‎‎‎Connected (no phone or media)‎‏‎‎‏‏‎<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+    <string name="bluetooth_connected_battery_level" msgid="5162924691231307748">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‎‏‏‏‏‎‏‎‎‏‏‎‎‏‏‎‎‏‎‎‏‎‏‎‎‏‏‎‏‏‏‏‏‏‏‎‏‏‏‎‏‏‏‏‎‏‏‏‎‏‏‏‏‏‏‎‎‏‎‎‎Connected, battery ‎‏‎‎‏‏‎<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+    <string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‎‏‏‎‎‏‎‏‏‎‎‎‏‏‏‎‏‎‏‏‏‏‏‎‎‎‏‏‏‎‎‎‎‎‎‏‎‎‎‎‎‎‎‏‎‏‎‎‎‏‏‎‎‏‎‎‏‎‏‎‎Connected (no phone), battery ‎‏‎‎‏‏‎<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‎‏‏‎‎‎‏‏‏‏‎‏‏‎‏‎‏‎‎‏‏‎‏‏‎‎‏‎‏‎‏‎‎‏‎‏‎‏‎‎‏‎‏‎‎‏‏‏‏‏‎‎‏‏‎‏‎‏‎‎‎Connected (no media), battery ‎‏‎‎‏‏‎<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‎‎‎‎‎‎‏‎‎‏‎‏‎‏‎‏‏‏‏‏‎‏‎‎‎‎‏‏‏‏‎‏‏‏‎‎‎‎‏‏‏‏‏‎‎‏‎‎‏‏‎‏‎‎‏‏‎‏‎‎‎Connected (no phone or media), battery ‎‏‎‎‏‏‎<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‏‏‎‎‎‎‏‏‎‎‎‏‎‏‎‎‎‎‎‎‎‎‏‏‎‎‎‏‎‎‎‎‎‎‏‏‏‎‏‎‏‎‎‏‏‎‏‎‏‎‏‏‏‎‎‏‎‎‏‎‎Media audio‎‏‎‎‏‎"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‏‏‎‎‎‏‏‏‎‏‏‎‎‎‏‏‎‏‏‏‏‏‏‎‏‎‎‏‏‏‎‏‏‎‎‏‎‏‏‏‎‏‎‎‎‎‎‏‎‏‏‎‏‏‎‏‎‎‏‎‎Phone calls‎‏‎‎‏‎"</string>
     <string name="bluetooth_profile_opp" msgid="9168139293654233697">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‏‏‏‏‎‎‏‏‏‎‏‏‏‏‎‎‎‏‏‎‎‎‎‏‏‏‎‎‏‏‎‏‏‎‎‏‏‎‎‎‏‏‏‏‏‎‏‏‎‎‏‎‎‏‏‎‎‎‎‏‎File transfer‎‏‎‎‏‎"</string>
@@ -75,6 +75,10 @@
     <string name="bluetooth_profile_sap" msgid="5764222021851283125">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‏‏‏‏‏‏‏‏‏‏‏‎‏‎‏‎‎‎‎‏‎‏‏‎‎‎‏‏‏‎‎‎‎‎‏‎‏‏‏‎‏‏‎‏‏‏‏‏‏‏‏‎‏‎‏‏‎‏‎‏‎SIM Access‎‏‎‎‏‎"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‏‎‏‏‏‎‎‎‏‏‏‎‏‏‎‏‎‎‎‎‎‎‎‏‏‎‎‎‎‎‎‏‏‎‏‎‎‎‎‏‎‏‎‎‎‎‎‎‎‎‏‏‎‏‎‏‎‏‏‏‎HD audio: ‎‏‎‎‏‏‎<xliff:g id="CODEC_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‎‏‏‎‎‎‎‏‏‎‏‏‏‎‏‎‏‏‏‎‏‎‏‏‏‏‏‎‎‎‎‏‏‏‎‏‏‏‏‎‎‏‏‏‏‏‏‎‎‎‎‎‎‎‏‎‎‏‏‏‎HD audio‎‏‎‎‏‎"</string>
+    <!-- no translation found for bluetooth_profile_hearing_aid (7999237886427812595) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (7188282786730266159) -->
+    <skip />
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‎‏‏‎‏‎‏‎‏‏‏‏‎‏‎‎‏‏‎‎‏‎‏‏‏‎‎‎‏‎‎‎‏‏‎‎‏‏‏‎‏‎‏‏‎‏‎‏‏‏‎‎‏‎‏‏‏‏‏‏‎‎Connected to media audio‎‏‎‎‏‎"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‏‎‏‎‎‏‎‏‎‎‎‏‏‎‎‏‎‏‏‎‏‏‎‎‎‎‏‏‎‏‎‎‏‏‏‎‏‎‎‏‏‎‏‏‎‏‏‎‎‏‏‎‏‎‎‏‏‏‏‏‎Connected to phone audio‎‏‎‎‏‎"</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‎‎‏‎‏‏‏‏‏‎‎‎‏‏‎‏‏‏‏‎‎‏‏‏‏‎‏‎‏‎‏‏‏‏‏‎‏‎‎‏‎‏‎‎Connected to file transfer server‎‏‎‎‏‎"</string>
@@ -91,6 +95,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‏‎‎‎‏‏‎‏‎‎‎‏‎‎‎‎‏‏‎‎‏‏‎‎‏‎‏‏‎‏‏‎‎‏‏‏‏‏‎‏‎‏‏‎‎‎‏‎‏‎‏‎‎‏‏‎‎‎‏‏‎Use for phone audio‎‏‎‎‏‎"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‎‎‎‏‎‏‏‎‏‏‎‏‎‎‎‎‏‏‎‏‎‏‎‏‏‎‎‏‎‎‎‎‏‎‎‎‎‎‎‏‎‎‎‎‎‏‎‎‎‎‎‎‏‏‎‏‏‏‎‎‎Use for file transfer‎‏‎‎‏‎"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‎‏‎‏‏‎‎‏‏‏‎‏‎‏‏‎‏‎‎‎‎‎‎‎‎‎‎‏‎‏‎‎‏‏‏‏‏‏‏‎‏‏‏‏‎‎‎‎‏‎‎‏‏‎‏‎‏‎‎‏‏‎Use for input‎‏‎‎‏‎"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (908775281788309484) -->
+    <skip />
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‎‏‎‏‏‎‎‎‏‎‎‏‎‎‏‏‏‎‎‎‏‏‎‏‎‏‎‏‏‏‏‎‏‏‏‏‏‏‎‏‏‏‎‎‎‎‏‎‎‎‎‎‏‏‎‎‏‎‏‏‎Pair‎‏‎‎‏‎"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‎‏‎‎‎‎‎‏‏‏‏‏‎‏‏‏‏‎‏‏‎‏‎‏‏‏‎‏‏‎‎‎‏‏‏‎‏‎‏‏‏‎‏‏‎‏‎‎‎‎‏‏‏‎‎‏‏‏‎‏‎PAIR‎‏‎‎‏‎"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‏‎‏‎‎‎‎‏‎‏‎‏‏‎‎‏‏‎‎‏‏‎‏‏‎‎‎‎‏‏‎‏‏‎‏‏‎‎‎‎‏‎‏‎‏‎‏‎‏‏‏‎‎‎‏‎‏‏‎‎‎Cancel‎‏‎‎‏‎"</string>
@@ -327,9 +333,10 @@
     <item msgid="8280754435979370728">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‎‎‏‎‏‏‏‎‏‎‏‏‎‎‏‎‎‏‏‎‎‏‎‎‏‎‎‏‎‏‎‎‎‏‎‎‏‏‎‎‏‎‏‎‎‏‏‎‎‎‎‎‏‏‏‎‏‎‎‎‎Natural colors as seen by the eye‎‏‎‎‏‎"</item>
     <item msgid="5363960654009010371">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‏‎‏‎‎‏‏‏‎‎‎‎‏‎‎‏‏‏‎‏‏‏‎‎‏‎‏‏‏‎‎‏‏‎‏‏‎‏‏‎‎‎‎‏‎‎‎‎‏‎‎‎‏‏‎‎‎‎‏‏‎Colors optimized for digital content‎‏‎‎‏‎"</item>
   </string-array>
-    <string name="inactive_apps_title" msgid="1317817863508274533">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‎‎‏‎‎‏‎‎‏‎‎‏‏‏‎‏‎‏‎‎‎‏‎‏‏‏‎‏‎‏‏‎‎‎‎‏‎‎‎‏‎‎‏‏‎‎‏‎‏‏‎‏‎‏‏‎‎‏‎‏‎Inactive apps‎‏‎‎‏‎"</string>
+    <string name="inactive_apps_title" msgid="9042996804461901648">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‏‏‎‏‎‏‏‏‏‏‏‏‎‎‏‎‏‏‎‏‏‎‏‎‏‏‏‎‏‎‎‎‏‎‏‎‏‏‏‏‎‎‎‏‏‎‏‏‎‏‏‏‎‏‎‏‎‎‎‎‎Standby apps‎‏‎‎‏‎"</string>
     <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‎‏‏‎‏‎‏‎‏‎‎‎‎‎‏‎‏‎‎‎‎‏‎‏‎‎‎‎‏‏‏‎‏‎‎‎‎‎‏‎‏‎‎‏‎‎‏‏‎‏‏‏‎‏‏‎‏‏‎‏‎Inactive. Tap to toggle.‎‏‎‎‏‎"</string>
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‏‎‎‏‏‏‏‏‎‎‎‎‎‏‎‎‏‏‎‏‎‏‎‎‎‏‏‏‏‎‏‏‎‏‎‏‏‎‏‎‏‏‎‏‏‎‎‎‏‎‏‏‏‎‎‎‏‎‏‎‎Active. Tap to toggle.‎‏‎‎‏‎"</string>
+    <string name="standby_bucket_summary" msgid="6567835350910684727">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‏‎‏‏‎‎‏‎‎‏‎‏‏‎‏‎‎‎‏‏‎‏‏‏‎‏‎‎‎‎‏‎‏‎‏‎‎‏‎‎‏‎‎‎‏‏‎‎‏‏‏‎‎‎‏‏‎‏‏‏‎App standby state:‎‏‎‎‏‏‎<xliff:g id="BUCKET"> %s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <string name="runningservices_settings_title" msgid="8097287939865165213">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‎‎‎‎‎‏‎‏‏‏‏‏‎‏‎‏‏‎‎‎‎‏‏‏‏‎‏‎‏‏‏‎‎‎‏‏‏‎‏‏‎‏‏‏‏‎‏‏‏‏‎‏‏‎‎‏‏‏‎‏‎Running services‎‏‎‎‏‎"</string>
     <string name="runningservices_settings_summary" msgid="854608995821032748">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‎‏‎‏‏‏‏‎‏‏‏‎‎‎‎‏‎‏‏‏‎‎‏‎‏‏‎‏‎‏‎‎‏‎‎‎‏‏‏‎‎‎‏‎‎‎‎‎‏‎‏‎‏‎‎‏‎‏‏‎‎‎View and control currently running services‎‏‎‎‏‎"</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‎‎‎‎‎‎‏‏‏‏‎‎‎‎‎‏‎‎‎‎‏‏‎‎‏‎‏‎‏‎‏‎‏‏‏‏‏‏‏‏‏‎‏‎‏‏‎‏‏‏‎‏‎‎‏‏‏‎‏‏‎WebView implementation‎‏‎‎‏‎"</string>
@@ -351,16 +358,24 @@
     <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‎‎‎‎‏‎‎‎‎‎‎‎‎‏‏‏‎‎‎‏‏‎‏‏‏‎‎‏‏‏‎‎‎‎‎‏‎‏‎‎‎‏‏‎‎‏‏‏‎‏‏‎‏‎‏‎‎‎‎‎‎Color correction‎‏‎‎‏‎"</string>
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‎‎‎‎‎‏‎‏‏‏‎‏‎‎‎‏‏‎‎‎‏‏‎‏‏‎‏‎‏‏‏‏‎‎‎‏‏‏‏‎‏‎‏‏‎‎‎‎‏‏‏‎‏‏‎‏‏‏‏‏‎This feature is experimental and may affect performance.‎‏‎‎‏‎"</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‏‎‏‏‎‏‎‎‎‎‎‏‏‎‎‏‏‏‏‏‎‎‎‎‎‎‎‏‎‎‏‎‎‏‏‎‏‎‏‏‎‏‎‎‏‎‎‏‎‎‏‏‎‎‎‏‏‏‎‎‎Overridden by ‎‏‎‎‏‏‎<xliff:g id="TITLE">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
-    <string name="power_remaining_duration_only" msgid="845431008899029842">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‎‏‎‏‏‏‎‏‏‏‎‏‏‏‎‎‏‎‎‏‏‎‎‎‎‎‏‎‏‏‏‏‏‎‏‏‏‏‎‎‎‎‏‏‎‏‏‎‏‏‎‏‏‎‏‎‏‎‎‏‎‎About ‎‏‎‎‏‏‎<xliff:g id="TIME">^1</xliff:g>‎‏‎‎‏‏‏‎ left‎‏‎‎‏‎"</string>
-    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‎‎‏‏‎‎‏‎‏‎‎‏‎‏‏‏‏‎‏‏‏‎‏‎‎‎‏‏‏‏‎‎‏‏‏‏‎‎‎‏‏‏‏‏‎‏‎‎‎‎‏‎‏‎‏‎‏‏‏‎‎About ‎‏‎‎‏‏‎<xliff:g id="TIME">^1</xliff:g>‎‏‎‎‏‏‏‎ left based on your usage‎‏‎‎‏‎"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‎‎‏‏‏‎‏‏‏‎‎‎‏‏‎‎‎‏‎‏‎‎‏‎‎‏‏‏‏‏‎‏‏‎‏‏‎‏‎‏‏‏‏‏‏‎‏‎‏‏‏‎‏‏‎‏‎‏‏‎‎‎‏‎‎‏‏‎<xliff:g id="TIME">^1</xliff:g>‎‏‎‎‏‏‏‎ left until fully charged‎‏‎‎‏‎"</string>
-    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‏‎‎‏‏‏‏‏‎‏‏‎‏‏‏‎‎‎‎‎‏‎‏‎‏‏‏‏‎‎‏‏‏‎‏‏‎‏‎‏‎‎‎‎‏‎‏‏‏‎‎‏‏‏‏‎‏‎‏‏‎‎‏‎‎‏‏‎<xliff:g id="TIME">^1</xliff:g>‎‏‎‎‏‏‏‎ left‎‏‎‎‏‎"</string>
-    <string name="power_remaining_duration_only_short_enhanced" msgid="7450425624026394823">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‎‏‏‏‎‏‏‎‎‏‎‏‎‎‏‏‏‎‏‎‏‎‏‎‎‎‎‏‏‎‎‎‏‎‎‏‏‎‎‎‏‏‏‏‏‎‏‏‎‎‎‎‏‏‎‎‎‏‏‏‎‎‏‎‎‏‏‎<xliff:g id="TIME">^1</xliff:g>‎‏‎‎‏‏‏‎ left based on your usage‎‏‎‎‏‎"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‎‏‏‏‎‏‏‏‎‏‏‏‎‎‎‎‎‏‎‎‏‏‏‏‏‏‏‎‎‏‎‎‏‎‎‏‎‏‏‎‎‏‏‎‎‎‏‏‎‎‏‎‎‎‏‎‏‏‏‎‎‎‏‎‎‏‏‎<xliff:g id="LEVEL">^1</xliff:g>‎‏‎‎‏‏‏‎ - about ‎‏‎‎‏‏‎<xliff:g id="TIME">^2</xliff:g>‎‏‎‎‏‏‏‎ left‎‏‎‎‏‎"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‏‏‎‏‎‎‎‏‎‏‏‎‎‏‎‎‎‏‎‏‏‎‎‎‎‎‏‏‏‎‏‏‎‏‎‎‎‏‎‏‏‏‎‎‏‏‎‏‏‎‏‎‏‏‎‎‎‏‏‎‎‎‏‎‎‏‏‎<xliff:g id="LEVEL">^1</xliff:g>‎‏‎‎‏‏‏‎ - about ‎‏‎‎‏‏‎<xliff:g id="TIME">^2</xliff:g>‎‏‎‎‏‏‏‎ left based on your usage‎‏‎‎‏‎"</string>
-    <string name="power_discharging_duration_short" msgid="4192244429001842403">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‏‎‏‎‎‎‏‎‏‏‎‏‏‏‎‏‏‎‎‎‎‎‎‏‏‎‎‎‏‏‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‏‎‏‏‏‎‎‎‏‏‎‎‏‎‎‏‏‎<xliff:g id="LEVEL">^1</xliff:g>‎‏‎‎‏‏‏‎ - ‎‏‎‎‏‏‎<xliff:g id="TIME">^2</xliff:g>‎‏‎‎‏‏‏‎ left‎‏‎‎‏‎"</string>
+    <string name="power_remaining_duration_only" msgid="845431008899029842">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‎‏‎‏‏‏‎‏‏‏‎‏‏‏‎‎‏‎‎‏‏‎‎‎‎‎‏‎‏‏‏‏‏‎‏‏‏‏‎‎‎‎‏‏‎‏‏‎‏‏‎‏‏‎‏‎‏‎‎‏‎‎About ‎‏‎‎‏‏‎<xliff:g id="TIME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ left‎‏‎‎‏‎"</string>
+    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‎‎‏‏‎‎‏‎‏‎‎‏‎‏‏‏‏‎‏‏‏‎‏‎‎‎‏‏‏‏‎‎‏‏‏‏‎‎‎‏‏‏‏‏‎‏‎‎‎‎‏‎‏‎‏‎‏‏‏‎‎About ‎‏‎‎‏‏‎<xliff:g id="TIME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ left based on your usage‎‏‎‎‏‎"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‎‎‏‏‏‎‏‏‏‎‎‎‏‏‎‎‎‏‎‏‎‎‏‎‎‏‏‏‏‏‎‏‏‎‏‏‎‏‎‏‏‏‏‏‏‎‏‎‏‏‏‎‏‏‎‏‎‏‏‎‎‎‏‎‎‏‏‎<xliff:g id="TIME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ left until fully charged‎‏‎‎‏‎"</string>
+    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‏‎‎‏‏‏‏‏‎‏‏‎‏‏‏‎‎‎‎‎‏‎‏‎‏‏‏‏‎‎‏‏‏‎‏‏‎‏‎‏‎‎‎‎‏‎‏‏‏‎‎‏‏‏‏‎‏‎‏‏‎‎‏‎‎‏‏‎<xliff:g id="TIME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ left‎‏‎‎‏‎"</string>
+    <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‎‎‏‏‎‎‏‏‏‎‎‎‏‎‏‏‏‏‏‎‏‎‎‏‎‏‎‎‎‏‏‏‏‏‎‏‎‏‏‏‏‎‎‎‎‏‏‎‎‏‏‎‏‏‏‎‎‎‎‏‎Less than ‎‏‎‎‏‏‎<xliff:g id="THRESHOLD">%1$s</xliff:g>‎‏‎‎‏‏‏‎ remaining‎‏‎‎‏‎"</string>
+    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‏‏‏‎‏‎‎‏‎‎‎‎‏‎‏‏‏‏‏‏‎‏‎‏‏‎‎‎‎‎‎‎‏‎‎‏‏‎‎‏‏‏‏‏‎‎‏‎‎‎‏‏‏‏‏‎‎‏‏‎‎‎‏‎‎‏‏‎<xliff:g id="LEVEL">%1$s</xliff:g>‎‏‎‎‏‏‏‎ - Less than ‎‏‎‎‏‏‎<xliff:g id="THRESHOLD">%2$s</xliff:g>‎‏‎‎‏‏‏‎ remaining‎‏‎‎‏‎"</string>
+    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‏‏‏‏‎‎‎‎‎‏‎‎‎‏‏‎‏‏‎‎‎‏‏‏‏‎‏‏‎‎‏‏‎‏‏‏‎‏‎‏‏‏‏‏‎‎‎‏‎‏‏‎‎‏‏‏‏‏‎‎‎‎‏‎‎‏‏‎<xliff:g id="LEVEL">%1$s</xliff:g>‎‏‎‎‏‏‏‎more than ‎‏‎‎‏‏‎<xliff:g id="TIME_REMAINING">%2$s</xliff:g>‎‏‎‎‏‏‏‎ remaining‎‏‎‎‏‎"</string>
+    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‏‎‏‏‎‏‎‎‏‏‎‎‎‎‎‎‏‎‏‏‎‏‏‎‎‏‏‎‏‎‏‎‎‏‏‎‎‎‎‎‎‏‏‏‎‎‎‎‎‏‏‏‎‏‎‏‎‎‏‎‎more than ‎‏‎‎‏‏‎<xliff:g id="TIME_REMAINING">%1$s</xliff:g>‎‏‎‎‏‏‏‎ remaining‎‏‎‎‏‎"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‎‎‎‏‎‏‎‏‏‎‏‏‏‎‏‏‎‎‎‏‎‎‏‎‏‏‏‏‎‏‎‎‎‎‏‏‏‎‏‎‎‎‎‏‎‏‎‏‎‏‏‏‎‏‏‏‎‎‎‏‎phone may shutdown soon‎‏‎‎‏‎"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‎‎‏‎‏‎‏‎‏‎‏‏‏‎‏‏‏‏‏‎‎‏‏‏‏‏‎‏‏‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‏‎‎‎‏‏‎‏‎‎‎‏‏‎‎‎‎tablet may shutdown soon‎‏‎‎‏‎"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‏‏‎‏‏‎‏‎‏‎‏‏‏‏‏‏‎‎‎‏‎‏‎‏‎‎‏‏‏‎‏‏‏‏‎‏‎‎‏‎‎‏‎‏‏‏‏‎‎‏‏‎‎‏‎‎‏‏‎‏‎device may shutdown soon‎‏‎‎‏‎"</string>
+    <string name="power_discharging_duration" msgid="2843747179907396142">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‎‏‏‏‎‏‏‏‎‏‏‏‎‎‎‎‎‏‎‎‏‏‏‏‏‏‏‎‎‏‎‎‏‎‎‏‎‏‏‎‎‏‏‎‎‎‏‏‎‎‏‎‎‎‏‎‏‏‏‎‎‎‏‎‎‏‏‎<xliff:g id="LEVEL">%1$s</xliff:g>‎‏‎‎‏‏‏‎ - about ‎‏‎‎‏‏‎<xliff:g id="TIME">%2$s</xliff:g>‎‏‎‎‏‏‏‎ left‎‏‎‎‏‎"</string>
+    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‏‏‎‏‎‎‎‏‎‏‏‎‎‏‎‎‎‏‎‏‏‎‎‎‎‎‏‏‏‎‏‏‎‏‎‎‎‏‎‏‏‏‎‎‏‏‎‏‏‎‏‎‏‏‎‎‎‏‏‎‎‎‏‎‎‏‏‎<xliff:g id="LEVEL">%1$s</xliff:g>‎‏‎‎‏‏‏‎ - about ‎‏‎‎‏‏‎<xliff:g id="TIME">%2$s</xliff:g>‎‏‎‎‏‏‏‎ left based on your usage‎‏‎‎‏‎"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‏‎‏‎‏‎‎‏‎‎‎‏‎‏‎‎‏‏‏‎‏‏‏‎‏‏‏‏‏‎‏‏‎‏‏‏‎‏‎‏‏‏‏‏‎‎‎‎‏‎‎‎‏‏‏‎‎‏‏‏‎‎‏‎‎‏‏‎<xliff:g id="LEVEL">%1$s</xliff:g>‎‏‎‎‏‏‏‎ - phone may shutdown soon‎‏‎‎‏‎"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‎‏‎‏‏‏‎‎‏‏‏‏‏‎‏‏‏‎‎‎‎‎‏‏‎‎‏‎‎‏‎‎‏‏‏‏‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‏‏‎‏‏‏‎‏‎‏‎‎‏‎‎‏‏‎<xliff:g id="LEVEL">%1$s</xliff:g>‎‏‎‎‏‏‏‎ - tablet may shutdown soon‎‏‎‎‏‎"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‏‏‎‎‎‎‎‎‏‎‎‎‏‎‏‎‏‎‎‎‏‎‎‏‏‏‏‎‎‎‎‏‎‏‎‏‏‎‏‏‏‎‏‏‏‎‎‎‏‎‎‏‏‎‏‏‏‎‏‎‎‎‏‎‎‏‏‎<xliff:g id="LEVEL">%1$s</xliff:g>‎‏‎‎‏‏‏‎ - device may shutdown soon‎‏‎‎‏‎"</string>
     <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>‎‏‎‎‏‏‏‎ until fully charged‎‏‎‎‏‎"</string>
+    <string name="power_charging_duration" msgid="4676999980973411875">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‎‎‎‎‏‏‏‎‏‎‎‎‎‎‎‎‏‎‏‎‏‎‏‏‎‎‏‏‏‏‏‏‎‎‎‎‎‏‏‎‏‏‎‏‏‏‎‎‏‏‏‎‎‎‏‎‎‎‏‏‎‎‏‎‎‏‏‎<xliff:g id="LEVEL">%1$s</xliff:g>‎‏‎‎‏‏‏‎ - ‎‏‎‎‏‏‎<xliff:g id="TIME">%2$s</xliff:g>‎‏‎‎‏‏‏‎ until fully charged‎‏‎‎‏‎"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‎‏‎‏‎‏‎‏‏‏‎‎‎‏‏‎‎‏‎‏‏‏‎‏‏‏‏‏‎‎‎‎‎‏‏‏‎‎‏‏‏‏‏‏‏‎‎‏‏‎‎‏‏‎‎‏‏‎‎‏‏‎Unknown‎‏‎‎‏‎"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‎‏‏‏‏‎‏‎‏‎‏‎‎‎‎‎‎‏‎‎‎‎‏‎‎‎‎‎‏‏‏‎‏‎‏‏‏‎‎‎‏‎‏‎‏‏‎‏‏‏‏‏‏‎‏‎‎‏‎‎‎Charging‎‏‎‎‏‎"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‏‎‎‎‏‎‎‏‏‎‎‎‎‏‎‎‎‎‏‏‏‏‏‏‏‎‎‎‎‎‎‏‏‎‏‏‎‎‏‎‏‎‏‎‏‏‏‎‎‎‏‏‎‏‏‎‏‎‏‎‎charging‎‏‎‎‏‎"</string>
@@ -414,4 +429,8 @@
     <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‎‏‎‎‏‏‏‎‏‏‏‎‎‎‏‏‏‎‎‎‏‏‎‏‏‎‎‎‎‏‎‏‎‎‎‏‏‎‏‏‎‏‏‎‏‏‎‏‏‏‏‏‎‎‏‏‎‏‏‎‎Never‎‏‎‎‏‎"</string>
     <string name="zen_interruption_level_priority" msgid="2078370238113347720">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‏‏‎‎‏‏‎‏‎‏‏‏‏‏‎‏‏‎‏‎‏‎‏‏‏‎‎‎‎‏‎‎‏‎‏‎‎‏‏‏‏‏‎‏‎‏‏‏‏‎‎‎‏‎‎‎‏‎‎‎‎Priority only‎‏‎‎‏‎"</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>
+    <string name="zen_alarm_warning_indef" msgid="3007988140196673193">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‏‎‎‏‏‎‏‏‏‏‏‎‏‎‎‎‎‏‎‏‎‏‎‎‎‏‏‎‏‏‎‎‏‎‎‏‎‎‎‎‎‎‏‎‏‎‏‏‎‏‏‎‏‎‏‎‏‎‎‏‎You won\'t hear your next alarm ‎‏‎‎‏‏‎<xliff:g id="WHEN">%1$s</xliff:g>‎‏‎‎‏‏‏‎ unless you turn this off before then‎‏‎‎‏‎"</string>
+    <string name="zen_alarm_warning" msgid="6236690803924413088">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‎‏‏‎‏‎‎‎‏‏‎‏‎‎‏‎‏‏‎‏‎‎‏‏‏‏‏‎‎‎‏‎‎‏‎‏‏‏‎‏‏‏‎‎‎‎‏‎‏‎‏‎‏‎‏‎‎‎‎‎‎You won\'t hear your next alarm ‎‏‎‎‏‏‎<xliff:g id="WHEN">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+    <string name="alarm_template" msgid="4996153414057676512">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‎‏‎‏‎‏‎‏‎‏‎‏‏‏‏‎‎‏‏‏‎‎‎‎‏‏‏‏‎‎‏‏‎‎‎‎‎‏‎‎‎‎‏‏‎‏‎‎‏‏‏‎‏‏‏‎‎‎‎‎‎at ‎‏‎‎‏‏‎<xliff:g id="WHEN">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+    <string name="alarm_template_far" msgid="3779172822607461675">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‎‏‎‎‎‏‏‏‎‎‏‎‎‏‎‏‎‎‎‏‏‎‏‎‏‎‎‎‏‏‎‎‎‏‎‎‎‏‎‏‎‎‏‏‏‏‏‏‏‏‎‏‎‎‏‎‏‎‏‏‎on ‎‏‎‎‏‏‎<xliff:g id="WHEN">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-es-rUS/arrays.xml b/packages/SettingsLib/res/values-es-rUS/arrays.xml
index 16f725a..b46024f 100644
--- a/packages/SettingsLib/res/values-es-rUS/arrays.xml
+++ b/packages/SettingsLib/res/values-es-rUS/arrays.xml
@@ -234,10 +234,6 @@
     <item msgid="7688197031296835369">"Mostrar áreas superpuestas"</item>
     <item msgid="2290859360633824369">"Mostrar áreas para deuteranomalía"</item>
   </string-array>
-  <string-array name="debug_hw_renderer_entries">
-    <item msgid="2578620445459945681">"OpenGL (predeterminado)"</item>
-    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
-  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"Límite estándar"</item>
     <item msgid="4071574792028999443">"Sin procesos en 2.º plano"</item>
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index 5bc7594..f38643f 100644
--- a/packages/SettingsLib/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/res/values-es-rUS/strings.xml
@@ -53,16 +53,16 @@
     <string name="bluetooth_disconnected" msgid="6557104142667339895">"Desconectado"</string>
     <string name="bluetooth_disconnecting" msgid="8913264760027764974">"Desconectando…"</string>
     <string name="bluetooth_connecting" msgid="8555009514614320497">"Conectando…"</string>
-    <string name="bluetooth_connected" msgid="6038755206916626419">"Conectado"</string>
+    <string name="bluetooth_connected" msgid="5427152882755735944">"Conectado a <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
     <string name="bluetooth_pairing" msgid="1426882272690346242">"Vinculando..."</string>
-    <string name="bluetooth_connected_no_headset" msgid="2866994875046035609">"Conectado (sin teléfono)"</string>
-    <string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Conectado (sin audio multimedia)"</string>
-    <string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Conectado (sin acceso a mensajes)"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Conectado (sin tel. ni audio multimedia)"</string>
-    <string name="bluetooth_connected_battery_level" msgid="7049181126136692368">"Conectado. Batería: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_headset_battery_level" msgid="5504193961248406027">"Conectado (sin teléfono). Batería: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="4751724026365870779">"Conectado (sin audio multimedia). Batería: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1549265779323455261">"Conectado (sin teléfono ni audio multimedia). Batería: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset" msgid="616068069034994802">"Conectado (sin teléfono) a <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp" msgid="3736431800395923868">"Conectado (sin archivos multimedia) a <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_map" msgid="3200033913678466453">"Conectado (sin acceso a mensajes) a <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2047403011284187056">"Conectado (sin teléfono/multimedia) a <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_battery_level" msgid="5162924691231307748">"Conectado a <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería)"</string>
+    <string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"Conectado (sin teléfono) a <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería)"</string>
+    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"Conectado (sin archivos multimedia) a <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería)"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"Conectado (sin teléfono ni archivos multimedia) a <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería)"</string>
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Audio multimedia"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"Llamadas telefónicas"</string>
     <string name="bluetooth_profile_opp" msgid="9168139293654233697">"Transferencia de archivos"</string>
@@ -75,6 +75,10 @@
     <string name="bluetooth_profile_sap" msgid="5764222021851283125">"Acceso SIM"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"Audio en HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"Audio en HD"</string>
+    <!-- no translation found for bluetooth_profile_hearing_aid (7999237886427812595) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (7188282786730266159) -->
+    <skip />
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Conectado al audio multimedia"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Conectado al audio del dispositivo"</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Conectado al servidor de transferencia de archivo"</string>
@@ -91,6 +95,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Utilizar para el audio del dispositivo"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Utilizar para la transferencia de archivos"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Utilizar para entrada"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (908775281788309484) -->
+    <skip />
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Vincular"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"SINCRONIZAR"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Cancelar"</string>
@@ -275,7 +281,6 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"Ver actualiz. de capas de hardware"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Luz verde en capas de hardware al actualizarse"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"Depurar superpos. de GPU"</string>
-    <string name="debug_hw_renderer" msgid="7568529019431785816">"Elegir procesador de GPU"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"Desactivar superpos. HW"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"Usar GPU para combinar pantallas"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"Simular espacio de color"</string>
@@ -328,9 +333,10 @@
     <item msgid="8280754435979370728">"Colores naturales como los ve el ojo"</item>
     <item msgid="5363960654009010371">"Colores optimizados para contenido digital"</item>
   </string-array>
-    <string name="inactive_apps_title" msgid="1317817863508274533">"Aplicaciones inactivas"</string>
+    <string name="inactive_apps_title" msgid="9042996804461901648">"Apps en espera"</string>
     <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"Inactiva. Presiona para activar o desactivar."</string>
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"Activa. Presiona para activar o desactivar."</string>
+    <string name="standby_bucket_summary" msgid="6567835350910684727">"Estado de la app en espera: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="runningservices_settings_title" msgid="8097287939865165213">"En ejecución"</string>
     <string name="runningservices_settings_summary" msgid="854608995821032748">"Ver y controlar servicios actuales en ejecución"</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"Implementación de WebView"</string>
@@ -352,16 +358,24 @@
     <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Corrección de color"</string>
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Esta función es experimental y puede afectar el rendimiento."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Reemplazado por <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only" msgid="845431008899029842">"Tiempo restante aproximado: <xliff:g id="TIME">^1</xliff:g>"</string>
-    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Aproximadamente <xliff:g id="TIME">^1</xliff:g> restantes en función del uso"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">^1</xliff:g> para completar la carga"</string>
-    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Tiempo restante: <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> restantes en función del uso"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">^1</xliff:g> (tiempo restante: <xliff:g id="TIME">^2</xliff:g>)"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">^1</xliff:g> (aproximadamente <xliff:g id="TIME">^2</xliff:g> restantes en función del uso)"</string>
-    <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> - Tiempo restante: <xliff:g id="TIME">^2</xliff:g>"</string>
+    <string name="power_remaining_duration_only" msgid="845431008899029842">"Tiempo restante aproximado: <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Aproximadamente <xliff:g id="TIME">%1$s</xliff:g> restantes en función del uso"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> para completar la carga"</string>
+    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Tiempo restante: <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Tiempo restante: menos de <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
+    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> (tiempo restante: menos de <xliff:g id="THRESHOLD">%2$s</xliff:g>)"</string>
+    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g> (tiempo restante: más de <xliff:g id="TIME_REMAINING">%2$s</xliff:g>)"</string>
+    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"Tiempo restante: más de <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"es posible que pronto se apague el teléfono"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"es posible que pronto se apague la tablet"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"es posible que pronto se apague el dispositivo"</string>
+    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> (tiempo restante: <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> (aproximadamente <xliff:g id="TIME">%2$s</xliff:g> restantes en función del uso)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g>: es posible que pronto se apague el teléfono"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g>: es posible que pronto se apague la tablet"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g>: es posible que pronto se apague el dispositivo"</string>
     <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> para completar la carga)"</string>
+    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> (<xliff:g id="TIME">%2$s</xliff:g> para completar la carga)"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Desconocido"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Cargando"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"cargando"</string>
@@ -409,4 +423,14 @@
     </plurals>
     <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"Más tiempo"</string>
     <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"Menos tiempo"</string>
+    <string name="zen_mode_enable_dialog_turn_on" msgid="8287824809739581837">"Activar"</string>
+    <string name="cancel" msgid="6859253417269739139">"Cancelar"</string>
+    <string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"Activar No interrumpir"</string>
+    <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"Nunca"</string>
+    <string name="zen_interruption_level_priority" msgid="2078370238113347720">"Solo prioridad"</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>
+    <string name="zen_alarm_warning_indef" msgid="3007988140196673193">"Solo oirás la próxima alarma (<xliff:g id="WHEN">%1$s</xliff:g>) si primero desactivas esta opción"</string>
+    <string name="zen_alarm_warning" msgid="6236690803924413088">"No oirás la próxima alarma (<xliff:g id="WHEN">%1$s</xliff:g>)"</string>
+    <string name="alarm_template" msgid="4996153414057676512">"a la(s) <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template_far" msgid="3779172822607461675">"el <xliff:g id="WHEN">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index 3301941..1bf825f 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -53,16 +53,16 @@
     <string name="bluetooth_disconnected" msgid="6557104142667339895">"Desconectado"</string>
     <string name="bluetooth_disconnecting" msgid="8913264760027764974">"Desconectando…"</string>
     <string name="bluetooth_connecting" msgid="8555009514614320497">"Estableciendo conexión…"</string>
-    <string name="bluetooth_connected" msgid="6038755206916626419">"Conectado"</string>
+    <string name="bluetooth_connected" msgid="5427152882755735944">"Conectado<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
     <string name="bluetooth_pairing" msgid="1426882272690346242">"Vinculando…"</string>
-    <string name="bluetooth_connected_no_headset" msgid="2866994875046035609">"Conectado (sin teléfono)"</string>
-    <string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Conectado (sin audio multimedia)"</string>
-    <string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Conectado (sin acceso a mensajes)"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Conectado (sin teléfono ni multimedia)"</string>
-    <string name="bluetooth_connected_battery_level" msgid="7049181126136692368">"Conectado (<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería)"</string>
-    <string name="bluetooth_connected_no_headset_battery_level" msgid="5504193961248406027">"Conectado sin teléfono (<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería)"</string>
-    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="4751724026365870779">"Conectado sin audio multimedia (<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería)"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1549265779323455261">"Conectado sin teléfono ni audio multimedia (<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería)"</string>
+    <string name="bluetooth_connected_no_headset" msgid="616068069034994802">"Conectado a <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> (sin audio de teléfono)"</string>
+    <string name="bluetooth_connected_no_a2dp" msgid="3736431800395923868">"Conectado (sin audio multimedia) a <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_map" msgid="3200033913678466453">"Conectado a <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> (sin acceso a mensajes)"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2047403011284187056">"Conectado a <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> (sin audio de teléfono ni multimedia)"</string>
+    <string name="bluetooth_connected_battery_level" msgid="5162924691231307748">"Conectado a <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería)"</string>
+    <string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"Conectado (sin audio de teléfono) a <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería)"</string>
+    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"Conectado (sin audio multimedia) a <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería)"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"Conectado (sin audio de teléfono ni multimedia) a <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería)"</string>
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Audio multimedia"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"Llamadas de teléfono"</string>
     <string name="bluetooth_profile_opp" msgid="9168139293654233697">"Transferencia de archivos"</string>
@@ -75,6 +75,10 @@
     <string name="bluetooth_profile_sap" msgid="5764222021851283125">"Acceso a tarjeta SIM"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"Audio HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"Audio HD"</string>
+    <!-- no translation found for bluetooth_profile_hearing_aid (7999237886427812595) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (7188282786730266159) -->
+    <skip />
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Conectado al audio del medio"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Conectado al audio del teléfono"</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Conectado con el servidor de transferencia de archivos"</string>
@@ -91,6 +95,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Utilizar para audio del teléfono"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Uso de la transferencia de archivos"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Usar para entrada"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (908775281788309484) -->
+    <skip />
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Vincular"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"VINCULAR"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Cancelar"</string>
@@ -327,9 +333,10 @@
     <item msgid="8280754435979370728">"Colores naturales como en la vida real"</item>
     <item msgid="5363960654009010371">"Colores optimizados para contenido digital"</item>
   </string-array>
-    <string name="inactive_apps_title" msgid="1317817863508274533">"Aplicaciones inactivas"</string>
+    <string name="inactive_apps_title" msgid="9042996804461901648">"Aplicaciones en espera"</string>
     <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"Inactiva. Toca para alternar."</string>
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"Activa. Toca para alternar."</string>
+    <string name="standby_bucket_summary" msgid="6567835350910684727">"Estado de la aplicación en espera: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="runningservices_settings_title" msgid="8097287939865165213">"Servicios en uso"</string>
     <string name="runningservices_settings_summary" msgid="854608995821032748">"Ver y controlar los servicios en uso"</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"Implementación de WebView"</string>
@@ -351,16 +358,24 @@
     <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Corrección de color"</string>
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Esta función es experimental y puede afectar al rendimiento."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Anulado por <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only" msgid="845431008899029842">"Tiempo restante aproximado: <xliff:g id="TIME">^1</xliff:g>"</string>
-    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Tiempo restante aproximado según tu uso: <xliff:g id="TIME">^1</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Tiempo restante hasta carga completa: <xliff:g id="TIME">^1</xliff:g>"</string>
-    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Tiempo restante: <xliff:g id="TIME">^1</xliff:g>"</string>
-    <string name="power_remaining_duration_only_short_enhanced" msgid="7450425624026394823">"Tiempo restante aproximado según tu uso: <xliff:g id="TIME">^1</xliff:g>"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">^1</xliff:g> - tiempo aproximado restante: <xliff:g id="TIME">^2</xliff:g>"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">^1</xliff:g> (tiempo restante aproximado según tu uso: <xliff:g id="TIME">^2</xliff:g>)"</string>
-    <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> - Tiempo restante: <xliff:g id="TIME">^2</xliff:g>"</string>
+    <string name="power_remaining_duration_only" msgid="845431008899029842">"Tiempo restante aproximado: <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Tiempo restante aproximado según tu uso: <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Tiempo restante hasta carga completa: <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Tiempo restante: <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Tiempo restante: menos de <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
+    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> (tiempo restante: menos de <xliff:g id="THRESHOLD">%2$s</xliff:g>)"</string>
+    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g> (tiempo restante: más de <xliff:g id="TIME_REMAINING">%2$s</xliff:g>)"</string>
+    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"Tiempo restante: más de <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"es posible que el teléfono se apague pronto"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"es posible que el tablet se apague pronto"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"es posible que el dispositivo se apague pronto"</string>
+    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> - tiempo aproximado restante: <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> (tiempo restante aproximado según tu uso: <xliff:g id="TIME">%2$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g>: es posible que el teléfono se apague pronto"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g>: es posible que el tablet se apague pronto"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g>: es posible que el dispositivo se apague pronto"</string>
     <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> para completar la carga"</string>
+    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> para completar la carga"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Desconocido"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Cargando"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"cargando"</string>
@@ -414,4 +429,8 @@
     <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"Nunca"</string>
     <string name="zen_interruption_level_priority" msgid="2078370238113347720">"Solo prioritarias"</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>
+    <string name="zen_alarm_warning_indef" msgid="3007988140196673193">"Solo oirás la próxima alarma (<xliff:g id="WHEN">%1$s</xliff:g>) si desactivas esta opción antes"</string>
+    <string name="zen_alarm_warning" msgid="6236690803924413088">"No oirás la próxima alarma (<xliff:g id="WHEN">%1$s</xliff:g>)"</string>
+    <string name="alarm_template" msgid="4996153414057676512">"Hora: <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template_far" msgid="3779172822607461675">"Fecha: <xliff:g id="WHEN">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-et/arrays.xml b/packages/SettingsLib/res/values-et/arrays.xml
index db796f1..2908676 100644
--- a/packages/SettingsLib/res/values-et/arrays.xml
+++ b/packages/SettingsLib/res/values-et/arrays.xml
@@ -234,10 +234,6 @@
     <item msgid="7688197031296835369">"Kuva ülejoonistatud alad"</item>
     <item msgid="2290859360633824369">"Deuteranomaly jaoks alade kuvamine"</item>
   </string-array>
-  <string-array name="debug_hw_renderer_entries">
-    <item msgid="2578620445459945681">"OpenGL (vaikeseade)"</item>
-    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
-  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"Standardpiir"</item>
     <item msgid="4071574792028999443">"Taustaprotsessideta"</item>
diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml
index 3447680..382a514 100644
--- a/packages/SettingsLib/res/values-et/strings.xml
+++ b/packages/SettingsLib/res/values-et/strings.xml
@@ -53,16 +53,16 @@
     <string name="bluetooth_disconnected" msgid="6557104142667339895">"Ühendus katkestatud"</string>
     <string name="bluetooth_disconnecting" msgid="8913264760027764974">"Ühenduse katkestamine ..."</string>
     <string name="bluetooth_connecting" msgid="8555009514614320497">"Ühendamine ..."</string>
-    <string name="bluetooth_connected" msgid="6038755206916626419">"Ühendatud"</string>
+    <string name="bluetooth_connected" msgid="5427152882755735944">"Ühendatud <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
     <string name="bluetooth_pairing" msgid="1426882272690346242">"Sidumine ..."</string>
-    <string name="bluetooth_connected_no_headset" msgid="2866994875046035609">"Ühendatud (telefoni pole)"</string>
-    <string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Ühendatud (meediat pole)"</string>
-    <string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Ühendatud (sõnumita juurdepääs)"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Ühendatud (pole telefoni ega meediat)"</string>
-    <string name="bluetooth_connected_battery_level" msgid="7049181126136692368">"Ühendatud, aku <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_headset_battery_level" msgid="5504193961248406027">"Ühendatud (telefoni pole), aku <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="4751724026365870779">"Ühendatud (meediat pole), aku <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1549265779323455261">"Ühendatud (telefoni ega meediat pole), aku <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset" msgid="616068069034994802">"Ühendatud (telefoni pole)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp" msgid="3736431800395923868">"Ühendatud (meediat pole)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_map" msgid="3200033913678466453">"Ühendatud (juurdepääs sõnumitele puudub)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2047403011284187056">"Ühendatud (telefoni ega meediat pole)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_battery_level" msgid="5162924691231307748">"Ühendatud, aku <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"Ühendatud (telefoni pole), aku <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"Ühendatud (meediat pole), aku <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"Ühendatud (telefoni ega meediat pole), aku <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Meedia heli"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"Telefonikõned"</string>
     <string name="bluetooth_profile_opp" msgid="9168139293654233697">"Failiedastus"</string>
@@ -75,6 +75,10 @@
     <string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM-kaardi juurdepääs"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD-heli: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD-heli"</string>
+    <!-- no translation found for bluetooth_profile_hearing_aid (7999237886427812595) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (7188282786730266159) -->
+    <skip />
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Ühendatud meediumiheliga"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Ühendatud telefoniheliga"</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Ühendatud failiedastuse serveriga"</string>
@@ -91,6 +95,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Kasuta telefoniheli jaoks"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Kasutage failide edastamiseks"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Kasutage sisendi jaoks"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (908775281788309484) -->
+    <skip />
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Seo"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"SEO"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Tühista"</string>
@@ -275,7 +281,6 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"Kuva riistv. kiht. värsk."</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Riistvara kihid vilguvad värskendamisel roheliselt"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"Silu GPU ülejoonistust"</string>
-    <string name="debug_hw_renderer" msgid="7568529019431785816">"GPU renderdi määramine"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"Keela HW ülekatted"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"Kasuta alati GPU-d kuva koostamisel"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"Modelleeri värviruumi"</string>
@@ -328,9 +333,10 @@
     <item msgid="8280754435979370728">"Silmadele loomulikuna tunduvad värvid"</item>
     <item msgid="5363960654009010371">"Digitaalse sisu jaoks optimeeritud värvid"</item>
   </string-array>
-    <string name="inactive_apps_title" msgid="1317817863508274533">"Inaktiivsed rakendused"</string>
+    <string name="inactive_apps_title" msgid="9042996804461901648">"Ootel rakendused"</string>
     <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"Passiivne. Puudutage vahetamiseks."</string>
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"Aktiivne. Puudutage vahetamiseks."</string>
+    <string name="standby_bucket_summary" msgid="6567835350910684727">"Rakenduse ootelolek:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="runningservices_settings_title" msgid="8097287939865165213">"Käitatud teenused"</string>
     <string name="runningservices_settings_summary" msgid="854608995821032748">"Praegu käitatud teenuste vaatamine ja juhtimine"</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView\' rakendamine"</string>
@@ -352,16 +358,24 @@
     <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Värvide korrigeerimine"</string>
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"See funktsioon on katseline ja võib mõjutada toimivust."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Alistas <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only" msgid="845431008899029842">"Umbes <xliff:g id="TIME">^1</xliff:g> on jäänud"</string>
-    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Teie kasutuse alusel on jäänud ligikaudu <xliff:g id="TIME">^1</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">^1</xliff:g> täislaadimiseni"</string>
-    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">^1</xliff:g> on jäänud"</string>
-    <string name="power_remaining_duration_only_short_enhanced" msgid="7450425624026394823">"Teie kasutuse alusel on jäänud <xliff:g id="TIME">^1</xliff:g>"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">^1</xliff:g> – umbes <xliff:g id="TIME">^2</xliff:g> on jäänud"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">^1</xliff:g> – teie kasutuse alusel on jäänud ligikaudu <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> on jäänud"</string>
+    <string name="power_remaining_duration_only" msgid="845431008899029842">"Umbes <xliff:g id="TIME">%1$s</xliff:g> on jäänud"</string>
+    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Teie kasutuse alusel on jäänud ligikaudu <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> täislaadimiseni"</string>
+    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">%1$s</xliff:g> on jäänud"</string>
+    <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Jäänud on alla <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
+    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> – jäänud on alla <xliff:g id="THRESHOLD">%2$s</xliff:g>"</string>
+    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g>jäänud on üle <xliff:g id="TIME_REMAINING">%2$s</xliff:g>"</string>
+    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"jäänud on üle <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"telefon võib peagi välja lülituda"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"tahvelarvuti võib peagi välja lülituda"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"seade võib peagi välja lülituda"</string>
+    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> – umbes <xliff:g id="TIME">%2$s</xliff:g> on jäänud"</string>
+    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> – teie kasutuse alusel on jäänud ligikaudu <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> – telefon võib peagi välja lülituda"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> – tahvelarvuti võib peagi välja lülituda"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> – seade võib peagi välja lülituda"</string>
     <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> täislaadimiseni"</string>
+    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> täislaadimiseni"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Tundmatu"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Laadimine"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"laadimine"</string>
@@ -409,4 +423,14 @@
     </plurals>
     <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"Pikem aeg."</string>
     <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"Lühem aeg."</string>
+    <string name="zen_mode_enable_dialog_turn_on" msgid="8287824809739581837">"Lülita sisse"</string>
+    <string name="cancel" msgid="6859253417269739139">"Tühista"</string>
+    <string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"Valiku Mitte segada sisselülitamine"</string>
+    <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"Mitte kunagi"</string>
+    <string name="zen_interruption_level_priority" msgid="2078370238113347720">"Ainult prioriteetsed"</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>
+    <string name="zen_alarm_warning_indef" msgid="3007988140196673193">"Kuulete järgmist äratust kell <xliff:g id="WHEN">%1$s</xliff:g> vaid siis, kui lülitate selle seade enne seda välja"</string>
+    <string name="zen_alarm_warning" msgid="6236690803924413088">"Te ei kuule järgmist äratust kell <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template" msgid="4996153414057676512">"kell <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template_far" msgid="3779172822607461675">"– <xliff:g id="WHEN">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml
index 41fee20..c49be3c 100644
--- a/packages/SettingsLib/res/values-eu/strings.xml
+++ b/packages/SettingsLib/res/values-eu/strings.xml
@@ -53,16 +53,16 @@
     <string name="bluetooth_disconnected" msgid="6557104142667339895">"Deskonektatuta"</string>
     <string name="bluetooth_disconnecting" msgid="8913264760027764974">"Deskonektatzen…"</string>
     <string name="bluetooth_connecting" msgid="8555009514614320497">"Konektatzen…"</string>
-    <string name="bluetooth_connected" msgid="6038755206916626419">"Konektatuta"</string>
+    <string name="bluetooth_connected" msgid="5427152882755735944">"Konektatuta<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
     <string name="bluetooth_pairing" msgid="1426882272690346242">"Parekatzen…"</string>
-    <string name="bluetooth_connected_no_headset" msgid="2866994875046035609">"Konektatuta (ez dago telefonorik)"</string>
-    <string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Konektatuta (ez dago euskarririk)"</string>
-    <string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Konektatuta (mezuetarako sarbiderik ez)"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Konektatuta (ez dago telef./euskarririk)"</string>
-    <string name="bluetooth_connected_battery_level" msgid="7049181126136692368">"Konektatuta. Bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_headset_battery_level" msgid="5504193961248406027">"Konektatuta (telefonorik gabe). Bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="4751724026365870779">"Konektatuta (euskarririk gabe). Bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1549265779323455261">"Konektatuta (telefono edo euskarririk gabe). Bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset" msgid="616068069034994802">"Konektatuta (telefonoaren audiorik gabe)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp" msgid="3736431800395923868">"Konektatuta (gailuaren audiorik gabe)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_map" msgid="3200033913678466453">"Konektatuta (mezuetarako sarbiderik gabe)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2047403011284187056">"Konektatuta (telefonoaren edo gailuaren audiorik gabe)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_battery_level" msgid="5162924691231307748">"Konektatuta. Bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>."</string>
+    <string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"Konektatuta (telefonoaren audiorik gabe). Bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>."</string>
+    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"Konektatuta (gailuaren audiorik gabe). Bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>."</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"Konektatuta (telefonoaren edo gailuaren audiorik gabe). Bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>."</string>
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Euskarriaren audioa"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"Telefono-deiak"</string>
     <string name="bluetooth_profile_opp" msgid="9168139293654233697">"Fitxategi-transferentzia"</string>
@@ -75,6 +75,10 @@
     <string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM txartelerako sarbidea"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"Kalitate handiko audioa: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"Kalitate handiko audioa"</string>
+    <!-- no translation found for bluetooth_profile_hearing_aid (7999237886427812595) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (7188282786730266159) -->
+    <skip />
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Euskarriaren audiora konektatuta"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Telefonoaren audiora konektatuta"</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Fitxategi-transferentziako zerbitzarira konektatuta"</string>
@@ -91,6 +95,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Erabili telefonoaren audiorako"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Erabili fitxategi-transferentziarako"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Erabili idazketarako"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (908775281788309484) -->
+    <skip />
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Parekatu"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"PAREKATU"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Utzi"</string>
@@ -327,9 +333,10 @@
     <item msgid="8280754435979370728">"Kolore naturalak, bizitza errealean bezala"</item>
     <item msgid="5363960654009010371">"Eduki digitalerako optimizatutako koloreak"</item>
   </string-array>
-    <string name="inactive_apps_title" msgid="1317817863508274533">"Aplikazio inaktiboak"</string>
+    <string name="inactive_apps_title" msgid="9042996804461901648">"Egonean dauden aplikazioak"</string>
     <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"Inaktibo. Aldatzeko, sakatu hau."</string>
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"Aktibo. Aldatzeko, sakatu hau."</string>
+    <string name="standby_bucket_summary" msgid="6567835350910684727">"Egonean moduko aplikazioaren egoera: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="runningservices_settings_title" msgid="8097287939865165213">"Abian diren zerbitzuak"</string>
     <string name="runningservices_settings_summary" msgid="854608995821032748">"Ikusi eta kontrolatu unean abian diren zerbitzuak"</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView implementation"</string>
@@ -351,16 +358,24 @@
     <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Koloreen zuzenketa"</string>
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Eginbidea esperimentala da eta eragina izan dezake funtzionamenduan."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> hobespena gainjarri zaio"</string>
-    <string name="power_remaining_duration_only" msgid="845431008899029842">"<xliff:g id="TIME">^1</xliff:g> inguru gelditzen dira"</string>
-    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"<xliff:g id="TIME">^1</xliff:g> inguru gelditzen dira, erabileraren arabera"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">^1</xliff:g> falta dira guztiz kargatu arte"</string>
-    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">^1</xliff:g> guztiz kargatu arte"</string>
-    <string name="power_remaining_duration_only_short_enhanced" msgid="7450425624026394823">"<xliff:g id="TIME">^1</xliff:g> gelditzen dira, erabileraren arabera"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g> inguru gelditzen dira"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">^1</xliff:g>: <xliff:g id="TIME">^2</xliff:g> inguru gelditzen dira, erabileraren arabera"</string>
-    <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g> guztiz kargatu arte"</string>
+    <string name="power_remaining_duration_only" msgid="845431008899029842">"<xliff:g id="TIME">%1$s</xliff:g> inguru gelditzen dira"</string>
+    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"<xliff:g id="TIME">%1$s</xliff:g> inguru gelditzen dira, erabileraren arabera"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> falta dira guztiz kargatu arte"</string>
+    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">%1$s</xliff:g> guztiz kargatu arte"</string>
+    <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"<xliff:g id="THRESHOLD">%1$s</xliff:g> baino gutxiago gelditzen dira"</string>
+    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="THRESHOLD">%2$s</xliff:g> baino gutxiago gelditzen dira"</string>
+    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME_REMAINING">%2$s</xliff:g> baino gehiago gelditzen dira"</string>
+    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> baino gehiago gelditzen dira"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"baliteke telefonoa laster itzaltzea"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"baliteke tableta laster itzaltzea"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"baliteke gailua laster itzaltzea"</string>
+    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> inguru gelditzen dira"</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> inguru gelditzen dira, erabileraren arabera"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g>: baliteke telefonoa laster itzaltzea"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g>: baliteke tableta laster itzaltzea"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g>: baliteke gailua laster itzaltzea"</string>
     <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> guztiz kargatu arte"</string>
+    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> guztiz kargatu arte"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Ezezaguna"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Kargatzen"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"kargatzen"</string>
@@ -414,4 +429,8 @@
     <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"Inoiz ez"</string>
     <string name="zen_interruption_level_priority" msgid="2078370238113347720">"Lehentasuna dutenak soilik"</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>
+    <string name="zen_alarm_warning_indef" msgid="3007988140196673193">"Ez duzu entzungo hurrengo alarma (<xliff:g id="WHEN">%1$s</xliff:g>) aukera hau lehenago desaktibatzen ez baduzu"</string>
+    <string name="zen_alarm_warning" msgid="6236690803924413088">"Ez duzu entzungo hurrengo alarma (<xliff:g id="WHEN">%1$s</xliff:g>)"</string>
+    <string name="alarm_template" msgid="4996153414057676512">"ordua: <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template_far" msgid="3779172822607461675">"data: <xliff:g id="WHEN">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-fa/arrays.xml b/packages/SettingsLib/res/values-fa/arrays.xml
index 2436e79..05ae3bf 100644
--- a/packages/SettingsLib/res/values-fa/arrays.xml
+++ b/packages/SettingsLib/res/values-fa/arrays.xml
@@ -234,10 +234,6 @@
     <item msgid="7688197031296835369">"نمایش نواحی بازنویسی"</item>
     <item msgid="2290859360633824369">"نمایش مناطق برای مبتلایان به سبزدشواربینی"</item>
   </string-array>
-  <string-array name="debug_hw_renderer_entries">
-    <item msgid="2578620445459945681">"‏OpenGL (پیش‌فرض)"</item>
-    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
-  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"حد استاندارد"</item>
     <item msgid="4071574792028999443">"بدون پردازش در پس‌زمینه"</item>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index 34a3c31..97ed86c 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -53,16 +53,16 @@
     <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>
+    <string name="bluetooth_connected" msgid="5427152882755735944">"متصل<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
     <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>
+    <string name="bluetooth_connected_no_headset" msgid="616068069034994802">"متصل (بدون تلفن)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp" msgid="3736431800395923868">"متصل (بدون رسانه)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_map" msgid="3200033913678466453">"متصل (بدون دسترسی پیام)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2047403011284187056">"متصل (بدون تلفن یا رسانه)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_battery_level" msgid="5162924691231307748">"متصل، باتری <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"متصل (بدون تلفن)، باتری <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"متصل (بدون رسانه)، باتری <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"متصل (بدون تلفن یا رسانه)، باتری <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"رسانه صوتی"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"تماس‌های تلفنی"</string>
     <string name="bluetooth_profile_opp" msgid="9168139293654233697">"انتقال فایل"</string>
@@ -75,6 +75,10 @@
     <string name="bluetooth_profile_sap" msgid="5764222021851283125">"دسترسی سیم‌کارت"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"‏صدای HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"‏صدای HD"</string>
+    <!-- no translation found for bluetooth_profile_hearing_aid (7999237886427812595) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (7188282786730266159) -->
+    <skip />
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"به رسانه صوتی متصل شد"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"به تلفن صوتی متصل شد"</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"به سرور انتقال فایل متصل شد"</string>
@@ -91,6 +95,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"استفاده برای تلفن صوتی"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"استفاده برای انتقال فایل"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"استفاده برای چاپ"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (908775281788309484) -->
+    <skip />
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"مرتبط‌سازی"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"مرتبط‌سازی"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"لغو"</string>
@@ -275,7 +281,6 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"نمایش به‌روزرسانی‌های لایه‌های سخت‌افزار"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"وقتی لایه‌های سخت‌افزاری به‌روزرسانی‌ می‌شوند، به رنگ سبز درآیند"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"‏اشکال‌زدایی بازنویسی GPU"</string>
-    <string name="debug_hw_renderer" msgid="7568529019431785816">"‏تنظیم تولیدکننده تصویرGPU"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"‏غیر فعال کردن پوشش HW"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"‏همیشه از GPU در ترکیب صفحه استفاده شود"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"شبیه‌سازی فضای رنگ"</string>
@@ -328,9 +333,10 @@
     <item msgid="8280754435979370728">"رنگ‌های طبیعی به‌همان صورتی که با چشم دیده می‌شوند"</item>
     <item msgid="5363960654009010371">"رنگ‌های بهینه‌شده برای محتوای دیجیتالی"</item>
   </string-array>
-    <string name="inactive_apps_title" msgid="1317817863508274533">"برنامه‌های غیرفعال"</string>
+    <string name="inactive_apps_title" msgid="9042996804461901648">"برنامه‌های آماده به‌کار"</string>
     <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"غیرفعال. برای تغییر حالت ضربه بزنید."</string>
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"فعال. برای تغییر حالت ضربه بزنید."</string>
+    <string name="standby_bucket_summary" msgid="6567835350910684727">"وضعیت حالت آماده به‌کار برنامه:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="runningservices_settings_title" msgid="8097287939865165213">"سرویس‌های در حال اجرا"</string>
     <string name="runningservices_settings_summary" msgid="854608995821032748">"مشاهده و کنترل سرویس‌های در حال اجرای فعلی"</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"اجرای وب‌نما"</string>
@@ -352,16 +358,24 @@
     <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>
+    <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"کمتر از <xliff:g id="THRESHOLD">%1$s</xliff:g> باقی مانده"</string>
+    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> - کمتر از <xliff:g id="THRESHOLD">%2$s</xliff:g> باقی مانده"</string>
+    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g>بیشتر از <xliff:g id="TIME_REMAINING">%2$s</xliff:g> باقی مانده"</string>
+    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"بیشتر از <xliff:g id="TIME_REMAINING">%1$s</xliff:g> باقی مانده"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"ممکن است تلفن به‌زودی خاموش شود"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"ممکن است رایانه لوحی به‌زودی خاموش شود"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"ممکن است دستگاه به‌زودی خاموش شود"</string>
+    <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>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> - ممکن است تلفن به‌زودی خاموش شود"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> - ممکن است رایانه لوحی به‌زودی خاموش شود"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> - ممکن است دستگاه به‌زودی خاموش شود"</string>
     <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>
@@ -409,4 +423,14 @@
     </plurals>
     <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"زمان بیشتر."</string>
     <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"زمان کمتر."</string>
+    <string name="zen_mode_enable_dialog_turn_on" msgid="8287824809739581837">"روشن کردن"</string>
+    <string name="cancel" msgid="6859253417269739139">"لغو"</string>
+    <string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"روشن کردن «مزاحم نشوید»"</string>
+    <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>
+    <string name="zen_alarm_warning_indef" msgid="3007988140196673193">"صدای زنگ بعدی‌تان را در ساعت <xliff:g id="WHEN">%1$s</xliff:g> نخواهید شنید، مگر اینکه قبل از آن ساعت، این تنظیم را خاموش کنید"</string>
+    <string name="zen_alarm_warning" msgid="6236690803924413088">"صدای زنگ بعدی‌تان را در ساعت <xliff:g id="WHEN">%1$s</xliff:g> نخواهید شنید"</string>
+    <string name="alarm_template" msgid="4996153414057676512">"ساعت <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template_far" msgid="3779172822607461675">"روز <xliff:g id="WHEN">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml
index 5f9bf48..30a47bd 100644
--- a/packages/SettingsLib/res/values-fi/strings.xml
+++ b/packages/SettingsLib/res/values-fi/strings.xml
@@ -53,16 +53,16 @@
     <string name="bluetooth_disconnected" msgid="6557104142667339895">"Yhteys katkaistu"</string>
     <string name="bluetooth_disconnecting" msgid="8913264760027764974">"Katkaistaan yhteyttä..."</string>
     <string name="bluetooth_connecting" msgid="8555009514614320497">"Yhdistetään…"</string>
-    <string name="bluetooth_connected" msgid="6038755206916626419">"Yhdistetty"</string>
+    <string name="bluetooth_connected" msgid="5427152882755735944">"Yhdistetty <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
     <string name="bluetooth_pairing" msgid="1426882272690346242">"Laiteparia muodostetaan..."</string>
-    <string name="bluetooth_connected_no_headset" msgid="2866994875046035609">"Yhdistetty (ei puhelimen ääntä)"</string>
-    <string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Yhdistetty (ei median ääntä)"</string>
-    <string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Yhdistetty (ei MAP)"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Yhdistetty (ei puhelimen/median ääntä)"</string>
-    <string name="bluetooth_connected_battery_level" msgid="7049181126136692368">"Yhdistetty, akun varaus <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_headset_battery_level" msgid="5504193961248406027">"Yhdistetty (ei puhelimen ääntä), akun varaus <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="4751724026365870779">"Yhdistetty (ei median ääntä), akun varaus <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1549265779323455261">"Yhdistetty (ei puhelimen tai median ääntä), akun varaustaso <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset" msgid="616068069034994802">"Yhdistetty (ei puhelimen ääntä) <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp" msgid="3736431800395923868">"Yhdistetty (ei median ääntä) <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_map" msgid="3200033913678466453">"Yhdistetty (ei pääsyä viesteihin) <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2047403011284187056">"Yhdistetty (ei puhelinta tai mediaa) <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_battery_level" msgid="5162924691231307748">"Yhdistetty, akun taso <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"Yhdistetty (ei puhelimen ääntä), akun varaus <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"Yhdistetty (ei median ääntä), akun varaus <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"Yhdistetty (ei puhelimen tai median ääntä), akun varaustaso <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Median ääni"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"Puhelut"</string>
     <string name="bluetooth_profile_opp" msgid="9168139293654233697">"Tiedostonsiirto"</string>
@@ -75,6 +75,10 @@
     <string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM-kortin käyttö"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD-ääni: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD-ääni"</string>
+    <!-- no translation found for bluetooth_profile_hearing_aid (7999237886427812595) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (7188282786730266159) -->
+    <skip />
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Yhdistetty median ääneen"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Yhdistetty puhelimen ääneen"</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Yhdistetty tiedostonsiirtopalvelimeen"</string>
@@ -91,6 +95,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Käytä puhelimen äänille"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Käytä tiedostojen siirtoon"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Käytä syöttöön"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (908775281788309484) -->
+    <skip />
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Muodosta laitepari"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"MUODOSTA LAITEPARI"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Peruuta"</string>
@@ -327,9 +333,10 @@
     <item msgid="8280754435979370728">"Ihmissilmän näkemät luonnolliset värit"</item>
     <item msgid="5363960654009010371">"Digitaaliselle sisällölle parhaiten sopivat värit"</item>
   </string-array>
-    <string name="inactive_apps_title" msgid="1317817863508274533">"Epäaktiiviset sovellukset"</string>
+    <string name="inactive_apps_title" msgid="9042996804461901648">"Valmiustilasovellukset"</string>
     <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"Ei käytössä. Ota käyttöön koskettamalla."</string>
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"Käytössä. Poista käytöstä koskettamalla."</string>
+    <string name="standby_bucket_summary" msgid="6567835350910684727">"Sovelluksen valmiusluokka: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="runningservices_settings_title" msgid="8097287939865165213">"Käynnissä olevat palvelut"</string>
     <string name="runningservices_settings_summary" msgid="854608995821032748">"Tarkastele ja hallitse käynnissä olevia palveluita"</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView-käyttöönotto"</string>
@@ -351,16 +358,24 @@
     <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Värikorjaus"</string>
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Tämä ominaisuus on kokeellinen ja voi vaikuttaa suorituskykyyn."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Tämän ohittaa <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only" msgid="845431008899029842">"Noin <xliff:g id="TIME">^1</xliff:g> jäljellä"</string>
-    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Noin <xliff:g id="TIME">^1</xliff:g> jäljellä käytön perusteella"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">^1</xliff:g> kunnes täynnä"</string>
-    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">^1</xliff:g> jäljellä"</string>
-    <string name="power_remaining_duration_only_short_enhanced" msgid="7450425624026394823">"<xliff:g id="TIME">^1</xliff:g> jäljellä käytön perusteella"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">^1</xliff:g> – noin <xliff:g id="TIME">^2</xliff:g> jäljellä"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">^1</xliff:g> – noin <xliff:g id="TIME">^2</xliff:g> jäljellä käytön perusteella"</string>
-    <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> – <xliff:g id="TIME">^2</xliff:g> jäljellä"</string>
+    <string name="power_remaining_duration_only" msgid="845431008899029842">"Noin <xliff:g id="TIME">%1$s</xliff:g> jäljellä"</string>
+    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Noin <xliff:g id="TIME">%1$s</xliff:g> jäljellä käytön perusteella"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> kunnes täynnä"</string>
+    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">%1$s</xliff:g> jäljellä"</string>
+    <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Alle <xliff:g id="THRESHOLD">%1$s</xliff:g> jäljellä"</string>
+    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> – Alle <xliff:g id="THRESHOLD">%2$s</xliff:g> jäljellä"</string>
+    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g> yli <xliff:g id="TIME_REMAINING">%2$s</xliff:g> jäljellä"</string>
+    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"yli <xliff:g id="TIME_REMAINING">%1$s</xliff:g> jäljellä"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"puhelin voi pian sammua"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"tabletti voi pian sammua"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"laite voi pian sammua"</string>
+    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> – noin <xliff:g id="TIME">%2$s</xliff:g> jäljellä"</string>
+    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> – noin <xliff:g id="TIME">%2$s</xliff:g> jäljellä käytön perusteella"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> – puhelin voi pian sammua"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> – tabletti voi pian sammua"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> – laite voi pian sammua"</string>
     <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> täyteen lataukseen"</string>
+    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> täyteen lataukseen"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Tuntematon"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Ladataan"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"ladataan"</string>
@@ -414,4 +429,8 @@
     <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"Ei koskaan"</string>
     <string name="zen_interruption_level_priority" msgid="2078370238113347720">"Vain tärkeät"</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>
+    <string name="zen_alarm_warning_indef" msgid="3007988140196673193">"Et kuule seuraavaa hälytystäsi (<xliff:g id="WHEN">%1$s</xliff:g>), ellet poista tätä tilaa käytöstä ennen sitä."</string>
+    <string name="zen_alarm_warning" msgid="6236690803924413088">"Et kuule seuraavaa hälytystäsi (<xliff:g id="WHEN">%1$s</xliff:g>)."</string>
+    <string name="alarm_template" msgid="4996153414057676512">"kello <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template_far" msgid="3779172822607461675">"<xliff:g id="WHEN">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index fa6006e..e1313e0 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -53,16 +53,16 @@
     <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>
+    <string name="bluetooth_connected" msgid="5427152882755735944">"Connecté à <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
     <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>
+    <string name="bluetooth_connected_no_headset" msgid="616068069034994802">"Connecté (aucun téléphone) <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp" msgid="3736431800395923868">"Connecté (aucun média) <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_map" msgid="3200033913678466453">"Connecté (aucun accès aux messages) <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2047403011284187056">"Connecté (aucun téléphone ni média) <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_battery_level" msgid="5162924691231307748">"Connecté, pile chargée à <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"Connecté (aucun téléphone), pile chargée à <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"Connecté (aucun média), pile chargée à <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"Connecté (aucun téléphone ni média), pile chargée à <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <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>
@@ -75,6 +75,10 @@
     <string name="bluetooth_profile_sap" msgid="5764222021851283125">"Accès à la carte SIM"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"Audio HD : <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"Audio HD"</string>
+    <!-- no translation found for bluetooth_profile_hearing_aid (7999237886427812595) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (7188282786730266159) -->
+    <skip />
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Connecté aux paramètres audio du média"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Connecté à l\'audio du téléphone"</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Connexion au serveur de transfert de fichiers"</string>
@@ -91,6 +95,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Utiliser pour les paramètres audio du téléphone"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Utiliser pour le transfert de fichiers"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Utiliser comme entrée"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (908775281788309484) -->
+    <skip />
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Associer"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"ASSOCIER"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Annuler"</string>
@@ -327,9 +333,10 @@
     <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>
+    <string name="inactive_apps_title" msgid="9042996804461901648">"Applications en veille"</string>
     <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>
+    <string name="standby_bucket_summary" msgid="6567835350910684727">"État de l\'application en veille :<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <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 +358,24 @@
     <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>
+    <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Il reste moins de <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
+    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> : il reste moins de <xliff:g id="THRESHOLD">%2$s</xliff:g>"</string>
+    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g> : il reste plus de <xliff:g id="TIME_REMAINING">%2$s</xliff:g>"</string>
+    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"il reste plus de <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"il se peut que le téléphone s\'éteigne bientôt"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"il se peut que la tablette s\'éteigne bientôt"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"il se peut que l\'appareil s\'éteigne bientôt"</string>
+    <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>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> : il se peut que le téléphone s\'éteigne bientôt"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g>: il se peut que la tablette s\'éteigne bientôt"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> : il se peut que l\'appareil s\'éteigne bientôt"</string>
     <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 +429,8 @@
     <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>
+    <string name="zen_alarm_warning_indef" msgid="3007988140196673193">"Vous n\'entendrez pas votre prochaine alarme à <xliff:g id="WHEN">%1$s</xliff:g> sauf si vous désactivez préalablement cette option"</string>
+    <string name="zen_alarm_warning" msgid="6236690803924413088">"Vous n\'entendrez pas votre prochaine alarme à <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template" msgid="4996153414057676512">"à <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template_far" msgid="3779172822607461675">"le <xliff:g id="WHEN">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-fr/arrays.xml b/packages/SettingsLib/res/values-fr/arrays.xml
index 995a1ff..e88d1b5 100644
--- a/packages/SettingsLib/res/values-fr/arrays.xml
+++ b/packages/SettingsLib/res/values-fr/arrays.xml
@@ -234,10 +234,6 @@
     <item msgid="7688197031296835369">"Afficher les zones de conflit"</item>
     <item msgid="2290859360633824369">"Afficher couleurs de zones adaptées à deutéranomalie"</item>
   </string-array>
-  <string-array name="debug_hw_renderer_entries">
-    <item msgid="2578620445459945681">"OpenGL (valeur par défaut)"</item>
-    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
-  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"Limite standard"</item>
     <item msgid="4071574792028999443">"Aucun processus en arrière-plan"</item>
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index 5bf43b6..8ad9571 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -53,16 +53,16 @@
     <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…"</string>
-    <string name="bluetooth_connected" msgid="6038755206916626419">"Connecté"</string>
+    <string name="bluetooth_connected" msgid="5427152882755735944">"Connecté<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
     <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é, batterie à <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_headset_battery_level" msgid="5504193961248406027">"Connecté (aucun téléphone), batterie à <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="4751724026365870779">"Connecté (aucun contenu multimédia), batterie à <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é (aucun téléphone ni contenu multimédia), batterie à <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset" msgid="616068069034994802">"Connecté (aucun téléphone)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp" msgid="3736431800395923868">"Connecté (aucun contenu mutimédia)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_map" msgid="3200033913678466453">"Connecté (sans accès aux messages)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2047403011284187056">"Connecté (aucun tél./contenu multimédia)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_battery_level" msgid="5162924691231307748">"Connecté, batterie à <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"Connecté (aucun téléphone), batterie à <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"Connecté (aucun contenu multimédia), batterie à <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"Connecté (aucun téléphone ni contenu multimédia), batterie à <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Multimédia"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"Appels téléphoniques"</string>
     <string name="bluetooth_profile_opp" msgid="9168139293654233697">"Transfert de fichier"</string>
@@ -75,6 +75,10 @@
     <string name="bluetooth_profile_sap" msgid="5764222021851283125">"Accès à la carte SIM"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"Audio HD : <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"Audio HD"</string>
+    <!-- no translation found for bluetooth_profile_hearing_aid (7999237886427812595) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (7188282786730266159) -->
+    <skip />
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Connecté aux paramètres audio du média"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Connecté aux paramètres audio du téléphone"</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Connexion au serveur de transfert de fichiers"</string>
@@ -91,6 +95,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Utiliser pour les paramètres audio du téléphone"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Utiliser pour le transfert de fichiers"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Utiliser comme entrée"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (908775281788309484) -->
+    <skip />
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Associer"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"ASSOCIER"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Annuler"</string>
@@ -275,7 +281,6 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"Mises à jour couches matérielles"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Couches matérielles en vert une fois mises à jour"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"Déboguer les conflits GPU"</string>
-    <string name="debug_hw_renderer" msgid="7568529019431785816">"Définir moteur rendu processeur graphique"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"Désactiver superpos. matér."</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"Toujours utiliser le GPU pour la composition écran"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"Simuler espace colori."</string>
@@ -328,9 +333,10 @@
     <item msgid="8280754435979370728">"Couleurs naturelles vues par l\'œil"</item>
     <item msgid="5363960654009010371">"Couleurs optimisées pour les contenus numériques"</item>
   </string-array>
-    <string name="inactive_apps_title" msgid="1317817863508274533">"Applications inactives"</string>
+    <string name="inactive_apps_title" msgid="9042996804461901648">"Applications mises en veille"</string>
     <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"Application inactive. Appuyez ici pour l\'activer."</string>
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"Application active. Appuyez ici pour la désactiver."</string>
+    <string name="standby_bucket_summary" msgid="6567835350910684727">"État de mise en veille de l\'application : <xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <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>
@@ -352,16 +358,24 @@
     <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Correction couleur"</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">"Temps restant en fonction de votre utilisation : environ <xliff:g id="TIME">^1</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">^1</xliff:g> avant 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">"Temps restant en fonction de votre utilisation : <xliff:g id="TIME">^1</xliff:g>"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">^1</xliff:g> - encore environ <xliff:g id="TIME">^2</xliff:g>"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">^1</xliff:g> – Temps restant en fonction de votre utilisation : environ <xliff:g id="TIME">^2</xliff:g>"</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">"Temps restant en fonction de votre utilisation : environ <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> avant charge complète"</string>
+    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Temps restant : <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Il reste moins de <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
+    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> – Il reste moins de <xliff:g id="THRESHOLD">%2$s</xliff:g>"</string>
+    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g> – Il reste plus de <xliff:g id="TIME_REMAINING">%2$s</xliff:g>"</string>
+    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"Il reste plus de <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"Il est possible que le téléphone s\'éteigne bientôt"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"Il est possible que la tablette s\'éteigne bientôt"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"Il est possible que l\'appareil s\'éteigne bientôt"</string>
+    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> - encore 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> – Temps restant en fonction de votre utilisation : environ <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> – Il est possible que le téléphone s\'éteigne bientôt"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> – Il est possible que la tablette s\'éteigne bientôt"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> – Il est possible que l\'appareil s\'éteigne bientôt"</string>
     <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">"Batterie en charge"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"chargement…"</string>
@@ -409,4 +423,14 @@
     </plurals>
     <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"Plus longtemps."</string>
     <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"Moins longtemps."</string>
+    <string name="zen_mode_enable_dialog_turn_on" msgid="8287824809739581837">"Activer"</string>
+    <string name="cancel" msgid="6859253417269739139">"Annuler"</string>
+    <string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"Activer le mode \"Ne pas déranger\""</string>
+    <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"Jamais"</string>
+    <string name="zen_interruption_level_priority" msgid="2078370238113347720">"Prioritaires uniquement"</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>
+    <string name="zen_alarm_warning_indef" msgid="3007988140196673193">"Vous n\'entendrez pas votre prochaine alarme <xliff:g id="WHEN">%1$s</xliff:g>, sauf si vous désactivez cette option avant"</string>
+    <string name="zen_alarm_warning" msgid="6236690803924413088">"Vous n\'entendrez pas votre prochaine alarme <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template" msgid="4996153414057676512">"à <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template_far" msgid="3779172822607461675">"le <xliff:g id="WHEN">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml
index afd350c..f7a9a79 100644
--- a/packages/SettingsLib/res/values-gl/strings.xml
+++ b/packages/SettingsLib/res/values-gl/strings.xml
@@ -53,16 +53,16 @@
     <string name="bluetooth_disconnected" msgid="6557104142667339895">"Desconectado"</string>
     <string name="bluetooth_disconnecting" msgid="8913264760027764974">"Desconectando..."</string>
     <string name="bluetooth_connecting" msgid="8555009514614320497">"Conectando..."</string>
-    <string name="bluetooth_connected" msgid="6038755206916626419">"Conectado"</string>
+    <string name="bluetooth_connected" msgid="5427152882755735944">"Conectado a <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
     <string name="bluetooth_pairing" msgid="1426882272690346242">"Sincronizando..."</string>
-    <string name="bluetooth_connected_no_headset" msgid="2866994875046035609">"Conectado (ningún teléfono)"</string>
-    <string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Conectado (sen ficheiros multimedia)"</string>
-    <string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Conectado (sen acceso ás mensaxes)"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Conectado (ningún teléfono nin soporte)"</string>
-    <string name="bluetooth_connected_battery_level" msgid="7049181126136692368">"Dispositivo conectado. Nivel da batería: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_headset_battery_level" msgid="5504193961248406027">"Dispositivo conectado (sen teléfono). Nivel da batería: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="4751724026365870779">"Dispositivo conectado (sen audio multimedia). Nivel da batería: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1549265779323455261">"Dispositivo conectado (sen teléfono nin audio multimedia). Nivel da batería: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset" msgid="616068069034994802">"Conectado a <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> (sen teléfono)"</string>
+    <string name="bluetooth_connected_no_a2dp" msgid="3736431800395923868">"Conectado a <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> (sen audio multimedia)"</string>
+    <string name="bluetooth_connected_no_map" msgid="3200033913678466453">"Conectado a <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> (sen acceso a mensaxes)"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2047403011284187056">"Conectado a <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> (sen tel./audio multimedia)"</string>
+    <string name="bluetooth_connected_battery_level" msgid="5162924691231307748">"Conectado a <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>, batería ao <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"Conectado a <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (sen teléfono), batería ao <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"Conectado a <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (sen audio multimedia), batería ao <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"Conectado <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (sen teléfono nin audio multimedia), batería ao <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Audio multimedia"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"Chamadas telefónicas"</string>
     <string name="bluetooth_profile_opp" msgid="9168139293654233697">"Transferencia de ficheiros"</string>
@@ -75,6 +75,10 @@
     <string name="bluetooth_profile_sap" msgid="5764222021851283125">"Acceso á SIM"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"Audio en HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"Audio en HD"</string>
+    <!-- no translation found for bluetooth_profile_hearing_aid (7999237886427812595) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (7188282786730266159) -->
+    <skip />
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Conectado ao audio multimedia"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Conectado ao audio do teléfono"</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Conectado ao servidor de transferencia de ficheiros"</string>
@@ -91,6 +95,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Utilízase para o audio do teléfono"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Utilízase para a transferencia de ficheiros"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Utilízase para a entrada"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (908775281788309484) -->
+    <skip />
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Sincronizar"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"SINCRONIZAR"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Cancelar"</string>
@@ -327,9 +333,10 @@
     <item msgid="8280754435979370728">"Cores naturais tal e o como se ven"</item>
     <item msgid="5363960654009010371">"Cores optimizadas para contido dixital"</item>
   </string-array>
-    <string name="inactive_apps_title" msgid="1317817863508274533">"Aplicacións inactivas"</string>
+    <string name="inactive_apps_title" msgid="9042996804461901648">"Aplicacións en espera"</string>
     <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"Aplicación inactiva. Toca para alternar a configuración."</string>
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"Aplicación activa. Toca para alternar a configuración."</string>
+    <string name="standby_bucket_summary" msgid="6567835350910684727">"Estado en espera da aplicación: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="runningservices_settings_title" msgid="8097287939865165213">"En execución"</string>
     <string name="runningservices_settings_summary" msgid="854608995821032748">"Ver e controlar servizos actualmente en execución"</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"Implementación de WebView"</string>
@@ -351,16 +358,24 @@
     <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Corrección da cor"</string>
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Esta función é experimental e pode afectar ao rendemento."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Anulado por <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only" msgid="845431008899029842">"Tempo que queda aproximadamente: <xliff:g id="TIME">^1</xliff:g>"</string>
-    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Tempo restante aproximado en función do uso: <xliff:g id="TIME">^1</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Tempo que queda ata cargar de todo: <xliff:g id="TIME">^1</xliff:g>"</string>
-    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Tempo restante: <xliff:g id="TIME">^1</xliff:g>"</string>
-    <string name="power_remaining_duration_only_short_enhanced" msgid="7450425624026394823">"Tempo restante en función do uso: <xliff:g id="TIME">^1</xliff:g>"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">^1</xliff:g> (tempo restante aproximado: <xliff:g id="TIME">^2</xliff:g>)"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">^1</xliff:g> - Tempo restante aproximado en función do uso: <xliff:g id="TIME">^2</xliff:g>"</string>
-    <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> (tempo restante: <xliff:g id="TIME">^2</xliff:g>)"</string>
+    <string name="power_remaining_duration_only" msgid="845431008899029842">"Tempo que queda aproximadamente: <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Tempo restante aproximado en función do uso: <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Tempo que queda ata cargar de todo: <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Tempo restante: <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Tempo restante inferior a <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
+    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g>: tempo restante inferior a <xliff:g id="THRESHOLD">%2$s</xliff:g>"</string>
+    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g>: tempo restante superior a <xliff:g id="TIME_REMAINING">%2$s</xliff:g>"</string>
+    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"tempo restante superior a: <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"é posible que o teléfono se apague en breve"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"é posible que a tableta se apague en breve"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"é posible que o dispositivo se apague en breve"</string>
+    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> (tempo restante aproximado: <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> - Tempo restante aproximado en función do uso: <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g>: é posible que o teléfono se apague en breve"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g>: é posible que a tableta se apague en breve"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g>: é posible que o dispositivo se apague en breve"</string>
     <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> ata completar a carga"</string>
+    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ata completar a carga"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Descoñecido"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Cargando"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"cargando"</string>
@@ -414,4 +429,8 @@
     <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"Nunca"</string>
     <string name="zen_interruption_level_priority" msgid="2078370238113347720">"Só prioridade"</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>
+    <string name="zen_alarm_warning_indef" msgid="3007988140196673193">"Non escoitarás a alarma seguinte (<xliff:g id="WHEN">%1$s</xliff:g>) a menos que desactives esta opción antes desa hora"</string>
+    <string name="zen_alarm_warning" msgid="6236690803924413088">"Non escoitarás a alarma seguinte (<xliff:g id="WHEN">%1$s</xliff:g>)"</string>
+    <string name="alarm_template" msgid="4996153414057676512">"á seguinte hora: <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template_far" msgid="3779172822607461675">"na seguinte data: <xliff:g id="WHEN">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml
index 4b5201c..617230e 100644
--- a/packages/SettingsLib/res/values-gu/strings.xml
+++ b/packages/SettingsLib/res/values-gu/strings.xml
@@ -53,16 +53,16 @@
     <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>
+    <string name="bluetooth_connected" msgid="5427152882755735944">"<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> સાથે કનેક્ટ થયેલ"</string>
     <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>
+    <string name="bluetooth_connected_no_headset" msgid="616068069034994802">"<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> સાથે કનેક્ટ થયેલ (કોઈ ફોન નથી)"</string>
+    <string name="bluetooth_connected_no_a2dp" msgid="3736431800395923868">"<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> સાથે કનેક્ટ થયેલ (કોઈ મીડિયા નથી)"</string>
+    <string name="bluetooth_connected_no_map" msgid="3200033913678466453">"<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> સાથે કનેક્ટ થયેલ (કોઈ સંદેશ ઍક્સેસ નથી)"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2047403011284187056">"<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> સાથે કનેક્ટ થયેલ (ફોન કે મીડિયા નથી)"</string>
+    <string name="bluetooth_connected_battery_level" msgid="5162924691231307748">"<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> સાથે કનેક્ટ થયેલ, બૅટરી <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> સાથે કનેક્ટ થયેલ (કોઈ ફોન નથી), બૅટરી <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> સાથે કનેક્ટ થયેલ (કોઈ મીડિયા નથી), બૅટરી <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> સાથે કનેક્ટ થયેલ (કોઈ ફોન અથવા મીડિયા નથી), બૅટરી <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"મીડિયા ઑડિઓ"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"ફોન કૉલ"</string>
     <string name="bluetooth_profile_opp" msgid="9168139293654233697">"ફાઇલ સ્થાનાંતરણ"</string>
@@ -75,6 +75,10 @@
     <string name="bluetooth_profile_sap" msgid="5764222021851283125">"સિમ ઍક્સેસ"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD ઑડિઓ: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD ઑડિઓ"</string>
+    <!-- no translation found for bluetooth_profile_hearing_aid (7999237886427812595) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (7188282786730266159) -->
+    <skip />
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"મીડિયા ઑડિઓ સાથે કનેક્ટ કર્યુ"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"ફોન ઑડિઓ સાથે કનેક્ટ થયાં"</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"ફાઇલ સ્થાનાંતરણ સેવાથી કનેક્ટ થયાં"</string>
@@ -91,6 +95,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"ફોન ઑડિઓ માટે ઉપયોગ કરો"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"ફાઇલ સ્થાનાંતર માટે ઉપયોગ કરો"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"ઇનપુટ માટે ઉપયોગ કરો"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (908775281788309484) -->
+    <skip />
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"જોડી"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"જોડાણ બનાવો"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"રદ કરો"</string>
@@ -327,9 +333,10 @@
     <item msgid="8280754435979370728">"આંખો વડે જોઈ શકાતાં કુદરતી રંગો"</item>
     <item msgid="5363960654009010371">"ડિજિટલ કન્ટેન્ટ માટે ઓપ્ટિમાઇઝ કરાયેલા રંગો"</item>
   </string-array>
-    <string name="inactive_apps_title" msgid="1317817863508274533">"નિષ્ક્રિય ઍપ્લિકેશનો"</string>
+    <string name="inactive_apps_title" msgid="9042996804461901648">"સ્ટૅન્ડબાય રાખેલી ઍપ"</string>
     <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"નિષ્ક્રિય. ટોગલ કરવા માટે ટૅપ કરો."</string>
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"સક્રિય. ટોગલ કરવા માટે ટૅપ કરો."</string>
+    <string name="standby_bucket_summary" msgid="6567835350910684727">"ઍપ સ્ટૅન્ડબાયની સ્થિતિ:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <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 +358,24 @@
     <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>
+    <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"<xliff:g id="THRESHOLD">%1$s</xliff:g> કરતાં ઓછો સમય બાકી છે"</string>
+    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="THRESHOLD">%2$s</xliff:g> કરતાં ઓછો સમય બાકી છે"</string>
+    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g><xliff:g id="TIME_REMAINING">%2$s</xliff:g> કરતાં વધુ સમય બાકી છે"</string>
+    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> કરતાં વધુ સમય બાકી છે"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"ફોન થોડી વારમાં બંધ થઈ શકે છે"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"ટૅબ્લેટ થોડી વારમાં બંધ થઈ શકે છે"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"ઉપકરણ થોડી વારમાં બંધ થઈ શકે છે"</string>
+    <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>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> - ફોન થોડી વારમાં બંધ થઈ શકે છે"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> - ટૅબ્લેટ થોડી વારમાં બંધ થઈ શકે છે"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> - ઉપકરણ થોડી વારમાં બંધ થઈ શકે છે"</string>
     <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 +429,8 @@
     <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>
+    <string name="zen_alarm_warning_indef" msgid="3007988140196673193">"તમે તમારું આગલું <xliff:g id="WHEN">%1$s</xliff:g>નું અલાર્મ નહીં સાંભળી શકો, જો તમે તે સમય પહેલાં આને બંધ નહીં કરો તો"</string>
+    <string name="zen_alarm_warning" msgid="6236690803924413088">"તમે <xliff:g id="WHEN">%1$s</xliff:g>નું તમારું આગલું અલાર્મ સાંભળી નહીં શકો"</string>
+    <string name="alarm_template" msgid="4996153414057676512">"<xliff:g id="WHEN">%1$s</xliff:g> વાગ્યે"</string>
+    <string name="alarm_template_far" msgid="3779172822607461675">"<xliff:g id="WHEN">%1$s</xliff:g> વાગ્યે"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index 16654be..4a12196 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -53,16 +53,16 @@
     <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>
+    <string name="bluetooth_connected" msgid="5427152882755735944">"<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> से जुड़ गया"</string>
     <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>
+    <string name="bluetooth_connected_no_headset" msgid="616068069034994802">"जुड़ गया (फ़ोन के ऑडियो को छोड़कर)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp" msgid="3736431800395923868">"जुड़ गया (मीडिया ऑडियो को छोड़कर)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_map" msgid="3200033913678466453">"जुड़ गया (मैसेज का एक्सेस नहीं)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2047403011284187056">"जुड़ गया (फ़ोन या मीडिया ऑडियो को छोड़कर)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_battery_level" msgid="5162924691231307748">"जुड़ गया, बैटरी का लेवल <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"जुड़ गया (फ़ोन के ऑडियो को छोड़कर), बैटरी का लेवल <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"जुड़ गया (मीडिया ऑडियो को छोड़कर), बैटरी का लेवल <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"जुड़ गया (फ़ोन या मीडिया ऑडियो को छोड़कर), बैटरी का लेवल <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"मीडिया ऑडियो"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"फ़ोन कॉल"</string>
     <string name="bluetooth_profile_opp" msgid="9168139293654233697">"फ़ाइल स्थानांतरण"</string>
@@ -75,6 +75,10 @@
     <string name="bluetooth_profile_sap" msgid="5764222021851283125">"सिम ऐक्सेस"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD ऑडियो: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD ऑडियो"</string>
+    <!-- no translation found for bluetooth_profile_hearing_aid (7999237886427812595) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (7188282786730266159) -->
+    <skip />
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"मीडिया ऑडियो से कनेक्‍ट किया गया"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"फ़ोन ऑडियो से कनेक्‍ट किया गया"</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"फ़ाइल स्‍थानांतरण सर्वर से कनेक्‍ट किया गया"</string>
@@ -91,6 +95,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"फ़ोन ऑडियो के लिए उपयोग करें"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"फ़ाइल स्‍थानांतरण के लिए उपयोग करें"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"इनपुट के लिए उपयोग करें"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (908775281788309484) -->
+    <skip />
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"युग्‍म बनाएं"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"दूसरे डिवाइस से जोड़ें"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"रद्द करें"</string>
@@ -327,9 +333,10 @@
     <item msgid="8280754435979370728">"आंखों को दिखाई देने वाले प्राकृतिक रंग"</item>
     <item msgid="5363960654009010371">"डिजिटल सामग्री के लिए ऑप्टिमाइज़़ किए गए रंग"</item>
   </string-array>
-    <string name="inactive_apps_title" msgid="1317817863508274533">"बंद एेप"</string>
+    <string name="inactive_apps_title" msgid="9042996804461901648">"स्टैंडबाय ऐप्लिकेशन"</string>
     <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"बंद है. टॉगल करने के लिए टैप करें."</string>
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"सक्रिय. टॉगल करने के लिए टैप करें."</string>
+    <string name="standby_bucket_summary" msgid="6567835350910684727">"ऐप्लिकेशन स्टैंडबाय की स्थिति:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="runningservices_settings_title" msgid="8097287939865165213">"चल रही सेवाएं"</string>
     <string name="runningservices_settings_summary" msgid="854608995821032748">"वर्तमान में चल रही सेवाओं को देखें और नियंत्रित करें"</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"वेबव्यू लागू करें"</string>
@@ -351,16 +358,24 @@
     <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>
+    <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"<xliff:g id="THRESHOLD">%1$s</xliff:g> से कम समय बचा है"</string>
+    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="THRESHOLD">%2$s</xliff:g> से कम बैटरी बची है"</string>
+    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g> <xliff:g id="TIME_REMAINING">%2$s</xliff:g> से ज़्यादा बैटरी बची है"</string>
+    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> से ज़्यादा बैटरी बची है"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"फ़ोन जल्दी ही बंद हो सकता है"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"टैबलेट जल्दी ही बंद हो सकता है"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"डिवाइस जल्दी ही बंद हो सकता है"</string>
+    <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>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> - फ़ोन जल्दी ही बंद हो सकता है"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> - टैबलेट जल्दी ही बंद हो सकता है"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> - डिवाइस जल्दी ही बंद हो सकता है"</string>
     <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 +429,8 @@
     <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>
+    <string name="zen_alarm_warning_indef" msgid="3007988140196673193">"आपको <xliff:g id="WHEN">%1$s</xliff:g> पर अपना अगला अलार्म तब तक सुनाई नहीं देगा, जब तक आप इसे (परेशान न करें सुविधा) तय समय से पहले बंद नहीं कर देते"</string>
+    <string name="zen_alarm_warning" msgid="6236690803924413088">"आपको <xliff:g id="WHEN">%1$s</xliff:g> पर अपना अगला अलार्म नहीं सुनाई देगा"</string>
+    <string name="alarm_template" msgid="4996153414057676512">"अलार्म <xliff:g id="WHEN">%1$s</xliff:g> पर बजेगा"</string>
+    <string name="alarm_template_far" msgid="3779172822607461675">"अलार्म <xliff:g id="WHEN">%1$s</xliff:g> को बजेगा"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-hr/arrays.xml b/packages/SettingsLib/res/values-hr/arrays.xml
index ffc76e8..3473ea5 100644
--- a/packages/SettingsLib/res/values-hr/arrays.xml
+++ b/packages/SettingsLib/res/values-hr/arrays.xml
@@ -234,10 +234,6 @@
     <item msgid="7688197031296835369">"Pokaži područja slojnih iscrtavanja"</item>
     <item msgid="2290859360633824369">"Prikaži područja za deuteranomaliju"</item>
   </string-array>
-  <string-array name="debug_hw_renderer_entries">
-    <item msgid="2578620445459945681">"OpenGL (zadano)"</item>
-    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
-  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"Standardna ograničenje"</item>
     <item msgid="4071574792028999443">"Nema pozadinskih procesa"</item>
diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml
index 6ca3e07..a9377e0 100644
--- a/packages/SettingsLib/res/values-hr/strings.xml
+++ b/packages/SettingsLib/res/values-hr/strings.xml
@@ -53,16 +53,16 @@
     <string name="bluetooth_disconnected" msgid="6557104142667339895">"Niste povezani"</string>
     <string name="bluetooth_disconnecting" msgid="8913264760027764974">"Isključivanje…"</string>
     <string name="bluetooth_connecting" msgid="8555009514614320497">"Povezivanje…"</string>
-    <string name="bluetooth_connected" msgid="6038755206916626419">"Povezan"</string>
+    <string name="bluetooth_connected" msgid="5427152882755735944">"Povezano: <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
     <string name="bluetooth_pairing" msgid="1426882272690346242">"Uparivanje…"</string>
-    <string name="bluetooth_connected_no_headset" msgid="2866994875046035609">"Povezano (bez telefona)"</string>
-    <string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Povezano (bez medija)"</string>
-    <string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Povezano (bez pristupa porukama)"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Povezano (bez telefona ili medija)"</string>
-    <string name="bluetooth_connected_battery_level" msgid="7049181126136692368">"Povezano, baterija <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_headset_battery_level" msgid="5504193961248406027">"Povezano (bez telefona), baterija <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="4751724026365870779">"Povezano (bez medija), baterija <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1549265779323455261">"Povezano (bez telefona i medija), baterija <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset" msgid="616068069034994802">"Povezano (bez telefona): <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp" msgid="3736431800395923868">"Povezano (bez medija): <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_map" msgid="3200033913678466453">"Povezano (bez pristupa porukama): <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2047403011284187056">"Povezano (bez telefona i medija): <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_battery_level" msgid="5162924691231307748">"Povezano, baterija <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"Povezano (bez telefona), baterija <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"Povezano (bez medija), baterija <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"Povezano (bez telefona i medija), baterija <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Medijski zvuk"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"Telefonski pozivi"</string>
     <string name="bluetooth_profile_opp" msgid="9168139293654233697">"Prijenos datoteke"</string>
@@ -75,6 +75,10 @@
     <string name="bluetooth_profile_sap" msgid="5764222021851283125">"Pristup SIM-u"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD audio: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD audio"</string>
+    <!-- no translation found for bluetooth_profile_hearing_aid (7999237886427812595) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (7188282786730266159) -->
+    <skip />
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Povezano s medijskim zvukom"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Povezano sa telefonskim zvukom"</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Povezano s poslužiteljem za prijenos datoteka"</string>
@@ -91,6 +95,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Koristi za telefonski zvuk"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Koristi za prijenos datoteke"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Upotrijebi za ulaz"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (908775281788309484) -->
+    <skip />
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Upari"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"UPARI"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Odustani"</string>
@@ -275,7 +281,6 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"Prikaži ažuriranja hardverskih slojeva"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Hardverski slojevi bljeskaju zeleno pri ažuriranju."</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"Rješavanje GPU preklapanja"</string>
-    <string name="debug_hw_renderer" msgid="7568529019431785816">"Postavi ispunjivač GPU-a"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"Onemogući dijeljenje mem."</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"Uvijek koristi GPU za slaganje zaslona"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"Simuliraj prostor boja"</string>
@@ -328,9 +333,10 @@
     <item msgid="8280754435979370728">"Prirodan doživljaj boje"</item>
     <item msgid="5363960654009010371">"Boje optimizirane za digitalni sadržaj"</item>
   </string-array>
-    <string name="inactive_apps_title" msgid="1317817863508274533">"Neaktivne aplikacije"</string>
+    <string name="inactive_apps_title" msgid="9042996804461901648">"Aplikacije u stanju mirovanja"</string>
     <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"Nije aktivno. Dodirnite da biste to promijenili."</string>
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"Aktivno. Dodirnite da biste to promijenili."</string>
+    <string name="standby_bucket_summary" msgid="6567835350910684727">"Stanje aplikacije u mirovanju: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="runningservices_settings_title" msgid="8097287939865165213">"Pokrenute usluge"</string>
     <string name="runningservices_settings_summary" msgid="854608995821032748">"Pogledajte i nadzirite pokrenute procese"</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"Implementacija WebViewa"</string>
@@ -352,16 +358,24 @@
     <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Korekcija boje"</string>
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Ova je značajka eksperimentalna i može utjecati na performanse."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Premošćeno postavkom <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only" msgid="845431008899029842">"Još otprilike <xliff:g id="TIME">^1</xliff:g>"</string>
-    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Još otprilike <xliff:g id="TIME">^1</xliff:g> na temelju vaše upotrebe"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Još <xliff:g id="TIME">^1</xliff:g> do potpune napunjenosti"</string>
-    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Još <xliff:g id="TIME">^1</xliff:g>"</string>
-    <string name="power_remaining_duration_only_short_enhanced" msgid="7450425624026394823">"Još <xliff:g id="TIME">^1</xliff:g> na temelju vaše upotrebe"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">^1</xliff:g> – preostalo je približno <xliff:g id="TIME">^2</xliff:g>"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">^1</xliff:g> – još otprilike <xliff:g id="TIME">^2</xliff:g> na temelju vaše upotrebe"</string>
-    <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> – još <xliff:g id="TIME">^2</xliff:g>"</string>
+    <string name="power_remaining_duration_only" msgid="845431008899029842">"Još otprilike <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Još otprilike <xliff:g id="TIME">%1$s</xliff:g> na temelju vaše upotrebe"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Još <xliff:g id="TIME">%1$s</xliff:g> do potpune napunjenosti"</string>
+    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Još <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Preostalo je manje od <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
+    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> – preostalo je manje od <xliff:g id="THRESHOLD">%2$s</xliff:g>"</string>
+    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g> – preostalo je više od <xliff:g id="TIME_REMAINING">%2$s</xliff:g>"</string>
+    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"preostalo je više od <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"telefon bi se uskoro mogao isključiti"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"tablet bi se uskoro mogao isključiti"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"uređaj bi se uskoro mogao isključiti"</string>
+    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> – preostalo je približno <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> – još otprilike <xliff:g id="TIME">%2$s</xliff:g> na temelju vaše upotrebe"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> – telefon bi se uskoro mogao isključiti"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> – tablet bi se uskoro mogao isključiti"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> – uređaj bi se uskoro mogao isključiti"</string>
     <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> do potpune napunjenosti"</string>
+    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do potpune napunjenosti"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Nepoznato"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Punjenje"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"punjenje"</string>
@@ -410,4 +424,14 @@
     </plurals>
     <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"Više vremena."</string>
     <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"Manje vremena."</string>
+    <string name="zen_mode_enable_dialog_turn_on" msgid="8287824809739581837">"Uključi"</string>
+    <string name="cancel" msgid="6859253417269739139">"Odustani"</string>
+    <string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"Uključite opciju Ne uznemiravaj."</string>
+    <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"Nikada"</string>
+    <string name="zen_interruption_level_priority" msgid="2078370238113347720">"Samo prioritetno"</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>
+    <string name="zen_alarm_warning_indef" msgid="3007988140196673193">"Nećete čuti sljedeći alarm <xliff:g id="WHEN">%1$s</xliff:g> ako to ne isključite prije njega"</string>
+    <string name="zen_alarm_warning" msgid="6236690803924413088">"Nećete čuti sljedeći alarm <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template" msgid="4996153414057676512">"u <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template_far" msgid="3779172822607461675">"u <xliff:g id="WHEN">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-hu/arrays.xml b/packages/SettingsLib/res/values-hu/arrays.xml
index 7ad170a..129944f 100644
--- a/packages/SettingsLib/res/values-hu/arrays.xml
+++ b/packages/SettingsLib/res/values-hu/arrays.xml
@@ -234,10 +234,6 @@
     <item msgid="7688197031296835369">"Tartalom-felülírási területek mutatása"</item>
     <item msgid="2290859360633824369">"A deuteranomália területeinek megjelenítése"</item>
   </string-array>
-  <string-array name="debug_hw_renderer_entries">
-    <item msgid="2578620445459945681">"OpenGL (alapértelmezett)"</item>
-    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
-  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"Normál korlátozás"</item>
     <item msgid="4071574792028999443">"Nincsenek háttérfolyamatok"</item>
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index a842d06..8e5cf7d 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -53,16 +53,16 @@
     <string name="bluetooth_disconnected" msgid="6557104142667339895">"Szétkapcsolva"</string>
     <string name="bluetooth_disconnecting" msgid="8913264760027764974">"Szétkapcsolás..."</string>
     <string name="bluetooth_connecting" msgid="8555009514614320497">"Csatlakozás…"</string>
-    <string name="bluetooth_connected" msgid="6038755206916626419">"Csatlakozva"</string>
+    <string name="bluetooth_connected" msgid="5427152882755735944">"Csatlakoztatva<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
     <string name="bluetooth_pairing" msgid="1426882272690346242">"Párosítás..."</string>
-    <string name="bluetooth_connected_no_headset" msgid="2866994875046035609">"Csatlakoztatva (nincs telefon)"</string>
-    <string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Csatlakoztatva (nincs hordozó)"</string>
-    <string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Csatlakoztatva (nincs üzenet-hozzáférés)"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Csatlakoztatva (nincs telefon vagy hordozó)"</string>
-    <string name="bluetooth_connected_battery_level" msgid="7049181126136692368">"Csatlakoztatva; az akkumulátor töltöttségi szintje: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_headset_battery_level" msgid="5504193961248406027">"Csatlakoztatva (telefonhang nélkül); az akkumulátor töltöttségi szintje: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="4751724026365870779">"Csatlakoztatva (médiahang nélkül); az akkumulátor töltöttségi szintje: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1549265779323455261">"Csatlakoztatva (telefon- vagy médiahang nélkül); az akkumulátor töltöttségi szintje:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset" msgid="616068069034994802">"Csatlakoztatva (telefonhang nélkül)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp" msgid="3736431800395923868">"Csatlakoztatva (médiahang nélkül)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_map" msgid="3200033913678466453">"Csatlakoztatva (nincs üzenet-hozzáférés)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2047403011284187056">"Csatlakoztatva (nincs telefon- és médiahang)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_battery_level" msgid="5162924691231307748">"Csatlakoztatva, az akkumulátor töltöttsége: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"Csatlakoztatva (telefonhang nélkül); az akkumulátor töltöttségi szintje: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"Csatlakoztatva (médiahang nélkül); az akkumulátor töltöttségi szintje: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"Csatlakoztatva (nincs telefon- és médiahang); az akkumulátor töltöttségi szintje: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Média audió"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"Telefonhívások"</string>
     <string name="bluetooth_profile_opp" msgid="9168139293654233697">"Fájlátvitel"</string>
@@ -75,6 +75,10 @@
     <string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM-elérés"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD audio: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD audio"</string>
+    <!-- no translation found for bluetooth_profile_hearing_aid (7999237886427812595) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (7188282786730266159) -->
+    <skip />
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Csatlakoztatva az eszköz hangjához"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Csatlakoztatva a telefon hangjához"</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Csatlakozva a fájlküldő szerverhez"</string>
@@ -91,6 +95,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Felhasználás a telefon hangjához"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Felhasználás fájlátvitelre"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Használat beviteli eszközként"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (908775281788309484) -->
+    <skip />
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Párosítás"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"PÁROSÍTÁS"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Mégse"</string>
@@ -275,7 +281,6 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"Hardverréteg-frissítések"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Frissítéskor a hardverrétegek zölden villognak"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"GPU tartalom-felülírási hibakeresés"</string>
-    <string name="debug_hw_renderer" msgid="7568529019431785816">"GPU-megjelenítő megadása"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"HW fedvények letiltása"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"Mindig a GPU használata képernyő-feldolgozáshoz"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"Színtérszimuláció"</string>
@@ -328,9 +333,10 @@
     <item msgid="8280754435979370728">"Természetes színek, ahogyan azt az emberi szem is látja"</item>
     <item msgid="5363960654009010371">"Digitális tartalomhoz optimalizált színek"</item>
   </string-array>
-    <string name="inactive_apps_title" msgid="1317817863508274533">"Inaktív alkalmazások"</string>
+    <string name="inactive_apps_title" msgid="9042996804461901648">"Készenlétben lévő alkalmazások"</string>
     <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"Kikapcsolva. Koppintson ide a váltáshoz."</string>
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"Bekapcsolva. Koppintson ide a váltáshoz."</string>
+    <string name="standby_bucket_summary" msgid="6567835350910684727">"Alkalmazás készenléti állapota:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="runningservices_settings_title" msgid="8097287939865165213">"Futó szolgáltatások"</string>
     <string name="runningservices_settings_summary" msgid="854608995821032748">"A jelenleg futó szolgáltatások megtekintése és vezérlése"</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView-megvalósítás"</string>
@@ -352,16 +358,24 @@
     <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Színkorrekció"</string>
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Ez egy kísérleti funkció, és hatással lehet a teljesítményre."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Felülírva erre: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only" msgid="845431008899029842">"Körülbelül <xliff:g id="TIME">^1</xliff:g> maradt hátra"</string>
-    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Körülbelül <xliff:g id="TIME">^1</xliff:g> van hátra az eszköz igénybevétele alapján"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">^1</xliff:g> a teljes töltöttségig"</string>
-    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">^1</xliff:g> van hátra"</string>
-    <string name="power_remaining_duration_only_short_enhanced" msgid="7450425624026394823">"<xliff:g id="TIME">^1</xliff:g> van hátra az eszköz igénybevétele alapján"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">^1</xliff:g> - körülbelül <xliff:g id="TIME">^2</xliff:g> van hátra"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">^1</xliff:g> – körülbelül <xliff:g id="TIME">^2</xliff:g> van hátra az eszköz igénybevétele alapján"</string>
-    <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> – <xliff:g id="TIME">^2</xliff:g> van hátra"</string>
+    <string name="power_remaining_duration_only" msgid="845431008899029842">"Körülbelül <xliff:g id="TIME">%1$s</xliff:g> maradt hátra"</string>
+    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Körülbelül <xliff:g id="TIME">%1$s</xliff:g> van hátra az eszköz igénybevétele alapján"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> a teljes töltöttségig"</string>
+    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">%1$s</xliff:g> van hátra"</string>
+    <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Kevesebb mint <xliff:g id="THRESHOLD">%1$s</xliff:g> van hátra"</string>
+    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> – kevesebb mint <xliff:g id="THRESHOLD">%2$s</xliff:g> van hátra"</string>
+    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g> – több mint <xliff:g id="TIME_REMAINING">%2$s</xliff:g> van hátra"</string>
+    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"több mint <xliff:g id="TIME_REMAINING">%1$s</xliff:g> van hátra"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"előfordulhat, hogy a telefon hamarosan leáll"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"előfordulhat, hogy a táblagép hamarosan leáll"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"előfordulhat, hogy az eszköz hamarosan leáll"</string>
+    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> - körülbelül <xliff:g id="TIME">%2$s</xliff:g> van hátra"</string>
+    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> – körülbelül <xliff:g id="TIME">%2$s</xliff:g> van hátra az eszköz igénybevétele alapján"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> – előfordulhat, hogy a telefon hamarosan leáll"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> – előfordulhat, hogy a táblagép hamarosan leáll"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> – előfordulhat, hogy az eszköz hamarosan leáll"</string>
     <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> a teljes feltöltésig"</string>
+    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> a teljes feltöltésig"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Ismeretlen"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Töltés"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"töltés"</string>
@@ -409,4 +423,14 @@
     </plurals>
     <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"Több idő."</string>
     <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"Kevesebb idő."</string>
+    <string name="zen_mode_enable_dialog_turn_on" msgid="8287824809739581837">"Bekapcsolás"</string>
+    <string name="cancel" msgid="6859253417269739139">"Mégse"</string>
+    <string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"A Ne zavarjanak mód bekapcsolása"</string>
+    <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"Soha"</string>
+    <string name="zen_interruption_level_priority" msgid="2078370238113347720">"Csak prioritásos"</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>
+    <string name="zen_alarm_warning_indef" msgid="3007988140196673193">"Ha előbb ezt nem kapcsolja ki, nem fogja hallani a következő ébresztést. Időpontja: <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="zen_alarm_warning" msgid="6236690803924413088">"Nem fogja hallani a következő ébresztést. Időpontja: <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template" msgid="4996153414057676512">"ekkor: <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template_far" msgid="3779172822607461675">"ezen a napon: <xliff:g id="WHEN">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml
index 7c3c3ad..e5e5beb 100644
--- a/packages/SettingsLib/res/values-hy/strings.xml
+++ b/packages/SettingsLib/res/values-hy/strings.xml
@@ -53,16 +53,16 @@
     <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>
+    <string name="bluetooth_connected" msgid="5427152882755735944">"Միացավ <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> սարքին"</string>
     <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>
+    <string name="bluetooth_connected_no_headset" msgid="616068069034994802">"Միացավ <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> սարքին (հեռախոս չկա)"</string>
+    <string name="bluetooth_connected_no_a2dp" msgid="3736431800395923868">"Միացավ <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> սարքին (մեդիա չկա)"</string>
+    <string name="bluetooth_connected_no_map" msgid="3200033913678466453">"Միացավ <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> սարքին (հաղորդագրություններ չկան)"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2047403011284187056">"Միացավ <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> սարքին (հեռախոս կամ մեդիա չկա)"</string>
+    <string name="bluetooth_connected_battery_level" msgid="5162924691231307748">"Միացված է, մարտկոցի լիցքը՝ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"Միացված է (հեռախոս չկա), մարտկոցի լիցքը՝ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"Միացված է (մեդիա չկա), մարտկոցի լիցքը՝ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"Միացված է (հեռախոս կամ մեդիա չկա), մարտկոցի լիցքը՝ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Մեդիա աուդիո"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"Հեռախոսազանգեր"</string>
     <string name="bluetooth_profile_opp" msgid="9168139293654233697">"Ֆայլերի փոխանցում"</string>
@@ -75,6 +75,10 @@
     <string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM քարտի հասանելիություն"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD աուդիո՝ <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD աուդիո"</string>
+    <!-- no translation found for bluetooth_profile_hearing_aid (7999237886427812595) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (7188282786730266159) -->
+    <skip />
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Միացված է մեդիա աուդիոյին"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Միացված է հեռախոսի ձայնային տվյալներին"</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Միացված է ֆայլերի փոխանցման սերվերին"</string>
@@ -91,6 +95,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Օգտագործել հեռախոսի աուդիոյի համար"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Օգտագործել ֆայլի փոխանցման համար"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Օգտագործել ներմուծման համար"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (908775281788309484) -->
+    <skip />
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Զուգավորել"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"Զուգավորել"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Չեղարկել"</string>
@@ -275,7 +281,6 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"Ցույց տալ սարքաշարի ծածկույթի թարմացումները"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Թող սարքաշարի ծածկույթները կանաչ գույնով առկայծեն, երբ  թարմացվեն"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"Վրիպազերծել GPU գերազանցումները"</string>
-    <string name="debug_hw_renderer" msgid="7568529019431785816">"Կարգավորել GPU Renderer"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"Կասեցնել HW վերադրումները"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"Միշտ օգտագործել GPU-ն` էկրանի կազմման համար"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"Նմանակել գունատարածքը"</string>
@@ -328,9 +333,10 @@
     <item msgid="8280754435979370728">"Բնական գույներ"</item>
     <item msgid="5363960654009010371">"Թվային բովանդակության համար հարմարեցված գույներ"</item>
   </string-array>
-    <string name="inactive_apps_title" msgid="1317817863508274533">"Անգործուն հավելվածներ"</string>
+    <string name="inactive_apps_title" msgid="9042996804461901648">"Սպասման կարգավիճակով հավելվածներ"</string>
     <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"Ակտիվ չէ: Հպեք՝ փոխելու համար:"</string>
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"Ակտիվ է: Հպեք՝ փոխելու համար:"</string>
+    <string name="standby_bucket_summary" msgid="6567835350910684727">"Հավելվածի սպասման կարգավիճակ՝ <xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <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>
@@ -352,16 +358,24 @@
     <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>
+    <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Մնացել է <xliff:g id="THRESHOLD">%1$s</xliff:g>-ից պակաս"</string>
+    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g>՝ մնացել է <xliff:g id="THRESHOLD">%2$s</xliff:g>-ից պակաս"</string>
+    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g>՝ մնացել է ավելի քան <xliff:g id="TIME_REMAINING">%2$s</xliff:g>"</string>
+    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"մնացել է ավելի քան <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"հնարավոր է հեռախոսը շուտով կանջատվի"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"հնարավոր է պլանշետը շուտով կանջատվի"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"հնարավոր է սարքը շուտով կանջատվի"</string>
+    <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>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g>՝ հնարավոր է հեռախոսը շուտով կանջատվի"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g>՝ հնարավոր է պլանշետը շուտով կանջատվի"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g>՝ հնարավոր է սարքը շուտով կանջատվի"</string>
     <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>
@@ -409,4 +423,14 @@
     </plurals>
     <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"Ավելացնել ժամանակը:"</string>
     <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"Պակասեցնել ժամանակը:"</string>
+    <string name="zen_mode_enable_dialog_turn_on" msgid="8287824809739581837">"Միացնել"</string>
+    <string name="cancel" msgid="6859253417269739139">"Չեղարկել"</string>
+    <string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"Միացրեք «Չանհանգստացնել» ռեժիմը"</string>
+    <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>
+    <string name="zen_alarm_warning_indef" msgid="3007988140196673193">"Ժամը <xliff:g id="WHEN">%1$s</xliff:g>-ի զարթուցիչը չի զանգի, եթե մինչ այդ չանջատեք այս կարգավորումը"</string>
+    <string name="zen_alarm_warning" msgid="6236690803924413088">"Ժամը <xliff:g id="WHEN">%1$s</xliff:g>-ի զարթուցիչը չի զանգի"</string>
+    <string name="alarm_template" msgid="4996153414057676512">"<xliff:g id="WHEN">%1$s</xliff:g>-ին"</string>
+    <string name="alarm_template_far" msgid="3779172822607461675">"<xliff:g id="WHEN">%1$s</xliff:g>-ին"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index 69a593c..5bf53b6 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -53,16 +53,16 @@
     <string name="bluetooth_disconnected" msgid="6557104142667339895">"Sambungan terputus"</string>
     <string name="bluetooth_disconnecting" msgid="8913264760027764974">"Memutus sambungan..."</string>
     <string name="bluetooth_connecting" msgid="8555009514614320497">"Menyambung…"</string>
-    <string name="bluetooth_connected" msgid="6038755206916626419">"Terhubung"</string>
+    <string name="bluetooth_connected" msgid="5427152882755735944">"Terhubung<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
     <string name="bluetooth_pairing" msgid="1426882272690346242">"Menyandingkan..."</string>
-    <string name="bluetooth_connected_no_headset" msgid="2866994875046035609">"Terhubung (bukan telepon)"</string>
-    <string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Terhubung (kecuali media)"</string>
-    <string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Tersambung (tidak ada akses pesan)"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Terhubung (bukan telepon atau media)"</string>
-    <string name="bluetooth_connected_battery_level" msgid="7049181126136692368">"Terhubung, baterai <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_headset_battery_level" msgid="5504193961248406027">"Terhubung (tanpa ponsel), baterai <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="4751724026365870779">"Terhubung (tanpa media), baterai <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1549265779323455261">"Terhubung (tanpa ponsel atau media), baterai <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset" msgid="616068069034994802">"Terhubung (tanpa ponsel)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp" msgid="3736431800395923868">"Terhubung (tanpa media)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_map" msgid="3200033913678466453">"Terhubung (tanpa akses pesan)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2047403011284187056">"Terhubung (tanpa ponsel atau media)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_battery_level" msgid="5162924691231307748">"Terhubung, baterai <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"Terhubung (tanpa ponsel), baterai <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"Terhubung (tanpa media), baterai <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"Terhubung (tanpa ponsel atau media), baterai <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Audio media"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"Panggilan telepon"</string>
     <string name="bluetooth_profile_opp" msgid="9168139293654233697">"Transfer file"</string>
@@ -75,6 +75,10 @@
     <string name="bluetooth_profile_sap" msgid="5764222021851283125">"Akses SIM"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"Audio HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"Audio HD"</string>
+    <!-- no translation found for bluetooth_profile_hearing_aid (7999237886427812595) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (7188282786730266159) -->
+    <skip />
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Tersambung ke media audio"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Tersambung ke audio ponsel"</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Sambungkan ke server transfer file"</string>
@@ -91,6 +95,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Gunakan untuk audio ponsel"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Gunakan untuk transfer file"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Gunakan untuk masukan"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (908775281788309484) -->
+    <skip />
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Sandingkan"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"SANDINGKAN"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Batal"</string>
@@ -327,9 +333,10 @@
     <item msgid="8280754435979370728">"Warna-warni alami seperti yang dilihat oleh mata"</item>
     <item msgid="5363960654009010371">"Warna yang dioptimalkan untuk konten digital"</item>
   </string-array>
-    <string name="inactive_apps_title" msgid="1317817863508274533">"Aplikasi yang tidak aktif"</string>
+    <string name="inactive_apps_title" msgid="9042996804461901648">"Aplikasi standby"</string>
     <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"Tidak aktif. Ketuk untuk beralih."</string>
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"Aktif. Ketuk untuk beralih."</string>
+    <string name="standby_bucket_summary" msgid="6567835350910684727">"Status standby aplikasi:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="runningservices_settings_title" msgid="8097287939865165213">"Layanan yang sedang berjalan"</string>
     <string name="runningservices_settings_summary" msgid="854608995821032748">"Melihat dan mengontrol layanan yang sedang berjalan"</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"Penerapan WebView"</string>
@@ -351,16 +358,24 @@
     <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Koreksi warna"</string>
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Fitur ini bersifat eksperimental dan dapat memengaruhi kinerja."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Digantikan oleh <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only" msgid="845431008899029842">"Sekitar <xliff:g id="TIME">^1</xliff:g> lagi"</string>
-    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Kira-kira <xliff:g id="TIME">^1</xliff:g> lagi berdasarkan penggunaan Anda"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">^1</xliff:g> lagi hingga terisi penuh"</string>
-    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">^1</xliff:g> tersisa"</string>
-    <string name="power_remaining_duration_only_short_enhanced" msgid="7450425624026394823">"<xliff:g id="TIME">^1</xliff:g> lagi berdasarkan penggunaan Anda"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">^1</xliff:g> - kira-kira <xliff:g id="TIME">^2</xliff:g> lagi"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">^1</xliff:g> - kira-kira <xliff:g id="TIME">^2</xliff:g> lagi berdasarkan penggunaan Anda"</string>
-    <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g> tersisa"</string>
+    <string name="power_remaining_duration_only" msgid="845431008899029842">"Sekitar <xliff:g id="TIME">%1$s</xliff:g> lagi"</string>
+    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Kira-kira <xliff:g id="TIME">%1$s</xliff:g> lagi berdasarkan penggunaan Anda"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> lagi hingga terisi penuh"</string>
+    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">%1$s</xliff:g> tersisa"</string>
+    <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Tersisa kurang dari <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
+    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> - Tersisa kurang dari <xliff:g id="THRESHOLD">%2$s</xliff:g>"</string>
+    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g>tersisa lebih dari <xliff:g id="TIME_REMAINING">%2$s</xliff:g>"</string>
+    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"tersisa lebih dari <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"ponsel mungkin segera dimatikan"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"tablet mungkin segera dimatikan"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"perangkat mungkin segera dimatikan"</string>
+    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> - kira-kira <xliff:g id="TIME">%2$s</xliff:g> lagi"</string>
+    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> - kira-kira <xliff:g id="TIME">%2$s</xliff:g> lagi berdasarkan penggunaan Anda"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> - ponsel mungkin segera dimatikan"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> - tablet mungkin segera dimatikan"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> - perangkat mungkin segera dimatikan"</string>
     <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> lagi terisi penuh"</string>
+    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> lagi terisi penuh"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Tidak diketahui"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Mengisi daya"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"mengisi daya baterai"</string>
@@ -414,4 +429,8 @@
     <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"Tidak pernah"</string>
     <string name="zen_interruption_level_priority" msgid="2078370238113347720">"Hanya untuk prioritas"</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>
+    <string name="zen_alarm_warning_indef" msgid="3007988140196673193">"Anda tidak akan mendengar alarm berikutnya <xliff:g id="WHEN">%1$s</xliff:g>, jika Anda tidak menonaktifkannya sebelum waktu tersebut"</string>
+    <string name="zen_alarm_warning" msgid="6236690803924413088">"Anda tidak akan mendengar alarm berikutnya <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template" msgid="4996153414057676512">"pukul <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template_far" msgid="3779172822607461675">"pada <xliff:g id="WHEN">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-is/arrays.xml b/packages/SettingsLib/res/values-is/arrays.xml
index a8a01a4..08d49aa 100644
--- a/packages/SettingsLib/res/values-is/arrays.xml
+++ b/packages/SettingsLib/res/values-is/arrays.xml
@@ -234,10 +234,6 @@
     <item msgid="7688197031296835369">"Sýna yfirteiknuð svæði"</item>
     <item msgid="2290859360633824369">"Sýna svæði fyrir litblinda"</item>
   </string-array>
-  <string-array name="debug_hw_renderer_entries">
-    <item msgid="2578620445459945681">"OpenGL (sjálfgefið)"</item>
-    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
-  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"Venjulegt hámark"</item>
     <item msgid="4071574792028999443">"Engar bakgrunnsvinnslur"</item>
diff --git a/packages/SettingsLib/res/values-is/strings.xml b/packages/SettingsLib/res/values-is/strings.xml
index 2c0a08b..c92dd25 100644
--- a/packages/SettingsLib/res/values-is/strings.xml
+++ b/packages/SettingsLib/res/values-is/strings.xml
@@ -53,16 +53,16 @@
     <string name="bluetooth_disconnected" msgid="6557104142667339895">"Aftengt"</string>
     <string name="bluetooth_disconnecting" msgid="8913264760027764974">"Aftengist…"</string>
     <string name="bluetooth_connecting" msgid="8555009514614320497">"Tengist…"</string>
-    <string name="bluetooth_connected" msgid="6038755206916626419">"Tengt"</string>
+    <string name="bluetooth_connected" msgid="5427152882755735944">"Tengt við <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
     <string name="bluetooth_pairing" msgid="1426882272690346242">"Parar…"</string>
-    <string name="bluetooth_connected_no_headset" msgid="2866994875046035609">"Tengt (ekki sími)"</string>
-    <string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Tengt (ekki efnisspilun)"</string>
-    <string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Tengt (enginn skilaboðaaðgangur)"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Tengt (ekki sími eða efnisspilun)"</string>
-    <string name="bluetooth_connected_battery_level" msgid="7049181126136692368">"Tengt, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> rafhlaða"</string>
-    <string name="bluetooth_connected_no_headset_battery_level" msgid="5504193961248406027">"Tengt (ekki sími), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> rafhlaða"</string>
-    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="4751724026365870779">"Tengt (ekki efnisspilun), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> rafhlaða"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1549265779323455261">"Tengt (ekki sími eða efnisspilun), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> rafhlaða"</string>
+    <string name="bluetooth_connected_no_headset" msgid="616068069034994802">"Tengt (enginn sími) <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp" msgid="3736431800395923868">"Tengt (ekkert efni) <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_map" msgid="3200033913678466453">"Tengt (enginn aðgangur að skilaboðum) <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2047403011284187056">"Tengt (enginn sími eða efni) <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_battery_level" msgid="5162924691231307748">"Tengt, staða rafhlöðu <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"Tengt (enginn sími), staða rafhlöðu <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"Tengt (ekkert efni), staða rafhlöðu <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"Tengt (enginn sími eða efni), staða rafhlöðu <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Hljóð efnis"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"Símtöl"</string>
     <string name="bluetooth_profile_opp" msgid="9168139293654233697">"Skráaflutningur"</string>
@@ -75,6 +75,10 @@
     <string name="bluetooth_profile_sap" msgid="5764222021851283125">"Aðgangur að SIM-korti"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD-hljóð: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD-hljóð"</string>
+    <!-- no translation found for bluetooth_profile_hearing_aid (7999237886427812595) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (7188282786730266159) -->
+    <skip />
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Tengt við hljóðspilun efnis"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Tengt við hljóð símans"</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Tengt við skráaflutningsþjón"</string>
@@ -91,6 +95,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Nota fyrir hljóð símans"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Nota við skráaflutning"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Nota fyrir inntak"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (908775281788309484) -->
+    <skip />
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Para"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"PARA"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Hætta við"</string>
@@ -275,7 +281,6 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"Sýna uppfærslur vélbúnaðar"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Láta vélbúnaðarlög blikka græn við uppfærslu"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"Yfirteiknun skjákorts"</string>
-    <string name="debug_hw_renderer" msgid="7568529019431785816">"Stilla skjákortsteiknun"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"Slökkva á vélb.yfirlögnum"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"Nota alltaf skjákort við samsetningu skjámyndar"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"Herma eftir litasviði"</string>
@@ -328,9 +333,10 @@
     <item msgid="8280754435979370728">"Náttúrulegir litir eins og augað nemur þá"</item>
     <item msgid="5363960654009010371">"Litir sérhannaðir fyrir stafrænt efni"</item>
   </string-array>
-    <string name="inactive_apps_title" msgid="1317817863508274533">"Óvirk forrit"</string>
+    <string name="inactive_apps_title" msgid="9042996804461901648">"Forrit í biðstöðu"</string>
     <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"Óvirkt. Ýttu til að breyta."</string>
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"Virkt. Ýttu til að breyta."</string>
+    <string name="standby_bucket_summary" msgid="6567835350910684727">"Biðstaða forrits: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="runningservices_settings_title" msgid="8097287939865165213">"Þjónustur í gangi"</string>
     <string name="runningservices_settings_summary" msgid="854608995821032748">"Skoða og stjórna þjónustum í gangi"</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"Innleiðing WebView"</string>
@@ -352,16 +358,24 @@
     <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Litaleiðrétting"</string>
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Þessi eiginleiki er á tilraunastigi og getur haft áhrif á frammistöðu."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Hnekkt af <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only" msgid="845431008899029842">"Um það bil <xliff:g id="TIME">^1</xliff:g> eftir"</string>
-    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"U.þ.b. <xliff:g id="TIME">^1</xliff:g> eftir miðað við notkun þína"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">^1</xliff:g> þar til hleðslu er lokið"</string>
-    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">^1</xliff:g> eftir"</string>
-    <string name="power_remaining_duration_only_short_enhanced" msgid="7450425624026394823">"<xliff:g id="TIME">^1</xliff:g> eftir miðað við notkun þína"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">^1</xliff:g> – um <xliff:g id="TIME">^2</xliff:g> eftir"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">^1</xliff:g> – u.þ.b. <xliff:g id="TIME">^2</xliff:g> eftir miðað við notkun þína"</string>
-    <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> – <xliff:g id="TIME">^2</xliff:g> eftir"</string>
+    <string name="power_remaining_duration_only" msgid="845431008899029842">"Um það bil <xliff:g id="TIME">%1$s</xliff:g> eftir"</string>
+    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"U.þ.b. <xliff:g id="TIME">%1$s</xliff:g> eftir miðað við notkun þína"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> þar til hleðslu er lokið"</string>
+    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">%1$s</xliff:g> eftir"</string>
+    <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Minna en <xliff:g id="THRESHOLD">%1$s</xliff:g> eftir"</string>
+    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> – Minna en <xliff:g id="THRESHOLD">%2$s</xliff:g> eftir"</string>
+    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g>meira en <xliff:g id="TIME_REMAINING">%2$s</xliff:g> eftir"</string>
+    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"meira en <xliff:g id="TIME_REMAINING">%1$s</xliff:g> eftir"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"síminn gæti slökkt á sér fljótlega"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"spjaldtölvan gæti slökkt á sér fljótlega"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"tækið gæti slökkt á sér fljótlega"</string>
+    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> – um <xliff:g id="TIME">%2$s</xliff:g> eftir"</string>
+    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> – u.þ.b. <xliff:g id="TIME">%2$s</xliff:g> eftir miðað við notkun þína"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> – síminn gæti slökkt á sér fljótlega"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> – spjaldtölvan gæti slökkt á sér fljótlega"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> – tækið gæti slökkt á sér fljótlega"</string>
     <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> þar til fullri hleðslu er náð"</string>
+    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> þar til fullri hleðslu er náð"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Óþekkt"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Í hleðslu"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"í hleðslu"</string>
@@ -409,4 +423,14 @@
     </plurals>
     <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"Meiri tími."</string>
     <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"Minni tími."</string>
+    <string name="zen_mode_enable_dialog_turn_on" msgid="8287824809739581837">"Kveikja"</string>
+    <string name="cancel" msgid="6859253417269739139">"Hætta við"</string>
+    <string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"Kveikja á „Ónáðið ekki“"</string>
+    <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"Aldrei"</string>
+    <string name="zen_interruption_level_priority" msgid="2078370238113347720">"Aðeins forgangur"</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>
+    <string name="zen_alarm_warning_indef" msgid="3007988140196673193">"Ekki mun heyrast í næsta vekjara <xliff:g id="WHEN">%1$s</xliff:g> nema slökkt sé á þessu fyrir þann tíma"</string>
+    <string name="zen_alarm_warning" msgid="6236690803924413088">"Ekki mun heyrast í næsta vekjara <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template" msgid="4996153414057676512">"á/í <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template_far" msgid="3779172822607461675">"á/í <xliff:g id="WHEN">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index da73e18..4edb5b3 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -53,16 +53,16 @@
     <string name="bluetooth_disconnected" msgid="6557104142667339895">"Disconnesso"</string>
     <string name="bluetooth_disconnecting" msgid="8913264760027764974">"Disconnessione..."</string>
     <string name="bluetooth_connecting" msgid="8555009514614320497">"Connessione..."</string>
-    <string name="bluetooth_connected" msgid="6038755206916626419">"Connesso"</string>
+    <string name="bluetooth_connected" msgid="5427152882755735944">"<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> connesso"</string>
     <string name="bluetooth_pairing" msgid="1426882272690346242">"Accoppiamento..."</string>
-    <string name="bluetooth_connected_no_headset" msgid="2866994875046035609">"Collegato (telefono escluso)"</string>
-    <string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Collegato (contenuti multimed. esclusi)"</string>
-    <string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Connesso (nessun accesso ai messaggi)"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Collegato (telef. o conten. mult. esclusi)"</string>
-    <string name="bluetooth_connected_battery_level" msgid="7049181126136692368">"Connesso, batteria al <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_headset_battery_level" msgid="5504193961248406027">"Connesso (telefono escluso), batteria al <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="4751724026365870779">"Connesso (contenuti multimediali esclusi), batteria al <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1549265779323455261">"Connesso (telefono o contenuti multimediali esclusi), batteria al <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset" msgid="616068069034994802">"<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> connesso (telefono escluso)"</string>
+    <string name="bluetooth_connected_no_a2dp" msgid="3736431800395923868">"<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> connesso (contenuti multimediali esclusi)"</string>
+    <string name="bluetooth_connected_no_map" msgid="3200033913678466453">"<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> connesso (nessun accesso ai messaggi)"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2047403011284187056">"<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> connesso (telefono o media esclusi)"</string>
+    <string name="bluetooth_connected_battery_level" msgid="5162924691231307748">"<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> connesso, batteria al <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> connesso (telefono escluso), batteria al <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> connesso (contenuti multimediali esclusi), batteria al <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> connesso (telefono o contenuti multimediali esclusi), batteria al <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Audio multimediale"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"Telefonate"</string>
     <string name="bluetooth_profile_opp" msgid="9168139293654233697">"Trasferimento file"</string>
@@ -75,6 +75,10 @@
     <string name="bluetooth_profile_sap" msgid="5764222021851283125">"Accesso alla SIM"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"Audio HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"Audio HD"</string>
+    <!-- no translation found for bluetooth_profile_hearing_aid (7999237886427812595) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (7188282786730266159) -->
+    <skip />
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Collegato ad audio media"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Collegato ad audio telefono"</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Collegato al server di trasferimento file"</string>
@@ -91,6 +95,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Usa per audio telefono"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Usa per trasferimento file"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Utilizza per l\'input"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (908775281788309484) -->
+    <skip />
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Accoppia"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"ACCOPPIA"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Annulla"</string>
@@ -327,9 +333,10 @@
     <item msgid="8280754435979370728">"Colori naturali e realistici"</item>
     <item msgid="5363960654009010371">"Colori ottimizzati per i contenuti digitali"</item>
   </string-array>
-    <string name="inactive_apps_title" msgid="1317817863508274533">"App non attive"</string>
+    <string name="inactive_apps_title" msgid="9042996804461901648">"App in standby"</string>
     <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"Non attiva. Tocca per attivare/disattivare."</string>
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"Attiva. Tocca per attivare/disattivare."</string>
+    <string name="standby_bucket_summary" msgid="6567835350910684727">"Stato di standby dell\'app: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="runningservices_settings_title" msgid="8097287939865165213">"Servizi in esecuzione"</string>
     <string name="runningservices_settings_summary" msgid="854608995821032748">"Visualizza e controlla i servizi attualmente in esecuzione"</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"Implementazione di WebView"</string>
@@ -351,16 +358,24 @@
     <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Correzione del colore"</string>
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Questa funzione è sperimentale e potrebbe influire sulle prestazioni."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Valore sostituito da <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only" msgid="845431008899029842">"Tempo approssimativo rimanente: <xliff:g id="TIME">^1</xliff:g>"</string>
-    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Tempo rimanente in base al tuo utilizzo: <xliff:g id="TIME">^1</xliff:g> circa"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Tempo rimanente alla carica completa: <xliff:g id="TIME">^1</xliff:g>"</string>
-    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Tempo rimanente: <xliff:g id="TIME">^1</xliff:g>"</string>
-    <string name="power_remaining_duration_only_short_enhanced" msgid="7450425624026394823">"Tempo rimanente in base al tuo utilizzo: <xliff:g id="TIME">^1</xliff:g>"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">^1</xliff:g> - ancora circa <xliff:g id="TIME">^2</xliff:g>"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">^1</xliff:g> - Tempo rimanente in base al tuo utilizzo: <xliff:g id="TIME">^2</xliff:g> circa"</string>
-    <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> - Tempo rimanente: <xliff:g id="TIME">^2</xliff:g>"</string>
+    <string name="power_remaining_duration_only" msgid="845431008899029842">"Tempo approssimativo rimanente: <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Tempo rimanente in base al tuo utilizzo: <xliff:g id="TIME">%1$s</xliff:g> circa"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Tempo rimanente alla carica completa: <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Tempo rimanente: <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Tempo rimanente: meno di <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
+    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> - Tempo rimanente: meno di <xliff:g id="THRESHOLD">%2$s</xliff:g>"</string>
+    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g> - Tempo rimanente: più di <xliff:g id="TIME_REMAINING">%2$s</xliff:g>"</string>
+    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"Tempo rimanente: più di <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"Il telefono potrebbe spegnersi a breve"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"Il tablet potrebbe spegnersi a breve"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"Il dispositivo potrebbe spegnersi a breve"</string>
+    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> - ancora circa <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> - Tempo rimanente in base al tuo utilizzo: <xliff:g id="TIME">%2$s</xliff:g> circa"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g>: il telefono potrebbe spegnersi a breve"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g>: il tablet potrebbe spegnersi a breve"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g>: il dispositivo potrebbe spegnersi a breve"</string>
     <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> alla carica completa"</string>
+    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> alla carica completa"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Sconosciuta"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"In carica"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"in carica"</string>
@@ -414,4 +429,8 @@
     <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"Mai"</string>
     <string name="zen_interruption_level_priority" msgid="2078370238113347720">"Solo con priorità"</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>
+    <string name="zen_alarm_warning_indef" msgid="3007988140196673193">"Non sentirai la prossima sveglia <xliff:g id="WHEN">%1$s</xliff:g> se non disattivi questa impostazione prima della sveglia"</string>
+    <string name="zen_alarm_warning" msgid="6236690803924413088">"Non sentirai la prossima sveglia <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template" msgid="4996153414057676512">"alle ore <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template_far" msgid="3779172822607461675">"il giorno <xliff:g id="WHEN">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-iw/arrays.xml b/packages/SettingsLib/res/values-iw/arrays.xml
index b8197a8..d758ed9 100644
--- a/packages/SettingsLib/res/values-iw/arrays.xml
+++ b/packages/SettingsLib/res/values-iw/arrays.xml
@@ -234,10 +234,6 @@
     <item msgid="7688197031296835369">"הצגת אזורים עם חריגה"</item>
     <item msgid="2290859360633824369">"הצגת אזורים לעיוורון צבעים"</item>
   </string-array>
-  <string-array name="debug_hw_renderer_entries">
-    <item msgid="2578620445459945681">"‏OpenGL (ברירת מחדל)"</item>
-    <item msgid="2839130076198120436">"OpenGL (Skia)‎"</item>
-  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"הגבלה סטנדרטית"</item>
     <item msgid="4071574792028999443">"אין תהליכים ברקע"</item>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index adfa890..b957898 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -53,16 +53,16 @@
     <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>
+    <string name="bluetooth_connected" msgid="5427152882755735944">"<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> מחובר"</string>
     <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>
+    <string name="bluetooth_connected_no_headset" msgid="616068069034994802">"מחובר (ללא טלפון)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp" msgid="3736431800395923868">"מחובר (ללא מדיה)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_map" msgid="3200033913678466453">"מחובר (ללא גישה להודעות)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2047403011284187056">"מחובר (ללא טלפון או מדיה)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_battery_level" msgid="5162924691231307748">"מחובר, שיעור הסוללה <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"מחובר (ללא טלפון), שיעור הסוללה <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"מחובר (ללא מדיה), שיעור הסוללה <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"מחובר (ללא טלפון או מדיה), שיעור הסוללה <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"אודיו של מדיה"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"שיחות טלפון"</string>
     <string name="bluetooth_profile_opp" msgid="9168139293654233697">"העברת קבצים"</string>
@@ -75,6 +75,10 @@
     <string name="bluetooth_profile_sap" msgid="5764222021851283125">"‏גישה ל-SIM"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"‏אודיו באיכות HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"‏אודיו באיכות HD"</string>
+    <!-- no translation found for bluetooth_profile_hearing_aid (7999237886427812595) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (7188282786730266159) -->
+    <skip />
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"מחובר לאודיו של מדיה"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"מחובר לאודיו של הטלפון"</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"מחובר לשרת העברת קבצים"</string>
@@ -91,6 +95,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"השתמש עבור האודיו של הטלפון"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"השתמש להעברת קבצים"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"השתמש לקלט"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (908775281788309484) -->
+    <skip />
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"התאם"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"התאם"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"ביטול"</string>
@@ -275,7 +281,6 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"הצג עדכוני שכבות חומרה"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"הצג הבהוב ירוק לשכבות חומרה כשהן מתעדכנות"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"‏חריגה בניפוי באגים ב-GPU"</string>
-    <string name="debug_hw_renderer" msgid="7568529019431785816">"‏הגדר את כלי העיבוד ל-GPU"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"‏השבת שכבות על של HW"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"‏השתמש תמיד ב-GPU להרכבת מסך"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"צור הדמיה של מרחב צבעים"</string>
@@ -328,9 +333,10 @@
     <item msgid="8280754435979370728">"צבעים טבעיים כפי שהם נראים לעין"</item>
     <item msgid="5363960654009010371">"צבעים מותאמים באופן אופטימלי לתוכן דיגיטלי"</item>
   </string-array>
-    <string name="inactive_apps_title" msgid="1317817863508274533">"אפליקציות לא פעילות"</string>
+    <string name="inactive_apps_title" msgid="9042996804461901648">"אפליקציות בהמתנה"</string>
     <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"אפליקציה לא פעילה. הקש כדי להחליף מצב."</string>
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"אפליקציה פעילה. הקש כדי להחליף מצב."</string>
+    <string name="standby_bucket_summary" msgid="6567835350910684727">"אפליקציה במצב המתנה:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <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>
@@ -352,16 +358,24 @@
     <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>
+    <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"נותרו פחות מ-<xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
+    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> - הזמן שנותר, פחות מ-<xliff:g id="THRESHOLD">%2$s</xliff:g>"</string>
+    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g>הזמן שנותר: יותר מ-<xliff:g id="TIME_REMAINING">%2$s</xliff:g>"</string>
+    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"הזמן שנותר: יותר מ-<xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"ייתכן שהטלפון ייכבה בקרוב"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"ייתכן שהטאבלט ייכבה בקרוב"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"ייתכן שהמכשיר ייכבה בקרוב"</string>
+    <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>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> - ייתכן שהטלפון ייכבה בקרוב"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> - ייתכן שהטאבלט ייכבה בקרוב"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> - ייתכן שהמכשיר ייכבה בקרוב"</string>
     <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>
@@ -411,4 +425,14 @@
     </plurals>
     <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"יותר זמן."</string>
     <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"פחות זמן."</string>
+    <string name="zen_mode_enable_dialog_turn_on" msgid="8287824809739581837">"הפעלה"</string>
+    <string name="cancel" msgid="6859253417269739139">"ביטול"</string>
+    <string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"הפעלת מצב נא לא להפריע"</string>
+    <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>
+    <string name="zen_alarm_warning_indef" msgid="3007988140196673193">"לא תושמע ההתראה הבאה <xliff:g id="WHEN">%1$s</xliff:g>, אלא אם ההגדרה הזו תושבת לפני כן"</string>
+    <string name="zen_alarm_warning" msgid="6236690803924413088">"לא תושמע ההתראה הבאה <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template" msgid="4996153414057676512">"בשעה <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template_far" msgid="3779172822607461675">"ב-<xliff:g id="WHEN">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ja/arrays.xml b/packages/SettingsLib/res/values-ja/arrays.xml
index aa20097..d024f01 100644
--- a/packages/SettingsLib/res/values-ja/arrays.xml
+++ b/packages/SettingsLib/res/values-ja/arrays.xml
@@ -234,10 +234,6 @@
     <item msgid="7688197031296835369">"オーバードロー領域の表示"</item>
     <item msgid="2290859360633824369">"第二色弱の方向けの領域の表示"</item>
   </string-array>
-  <string-array name="debug_hw_renderer_entries">
-    <item msgid="2578620445459945681">"OpenGL(デフォルト)"</item>
-    <item msgid="2839130076198120436">"OpenGL(Skia)"</item>
-  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"標準の上限"</item>
     <item msgid="4071574792028999443">"バックグラウンドプロセスを使用しない"</item>
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index 1c0a941..953b2e3 100644
--- a/packages/SettingsLib/res/values-ja/strings.xml
+++ b/packages/SettingsLib/res/values-ja/strings.xml
@@ -53,16 +53,16 @@
     <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>
+    <string name="bluetooth_connected" msgid="5427152882755735944">"接続済み: <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
     <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>
+    <string name="bluetooth_connected_no_headset" msgid="616068069034994802">"接続済み(電話なし): <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp" msgid="3736431800395923868">"接続済み(メディアなし): <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_map" msgid="3200033913678466453">"接続済み(メッセージ アクセスなし): <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2047403011284187056">"接続済み(電話、メディアなし): <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_battery_level" msgid="5162924691231307748">"接続済み、電池残量 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>: <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"接続済み(電話なし)、電池残量 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>: <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"接続済み(メディアなし)、電池残量 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>: <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"接続済み(電話、メディアなし)、電池残量 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>: <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"メディアの音声"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"電話"</string>
     <string name="bluetooth_profile_opp" msgid="9168139293654233697">"ファイル転送"</string>
@@ -75,6 +75,10 @@
     <string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIMアクセス"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD オーディオ: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD オーディオ"</string>
+    <!-- no translation found for bluetooth_profile_hearing_aid (7999237886427812595) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (7188282786730266159) -->
+    <skip />
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"メディアの音声に接続"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"携帯電話の音声に接続"</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"ファイル転送サーバーに接続"</string>
@@ -91,6 +95,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"携帯電話の音声に使用"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"ファイル転送に使用"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"入力に使用"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (908775281788309484) -->
+    <skip />
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"ペア設定する"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"ペア設定する"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"キャンセル"</string>
@@ -275,7 +281,6 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"ハードウェア層情報を表示"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"ハードウェア層が更新されると緑を表示する"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"GPUオーバードローをデバッグ"</string>
-    <string name="debug_hw_renderer" msgid="7568529019431785816">"GPU レンダラの設定"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"HWオーバーレイを無効"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"画面合成に常にGPUを使用する"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"色空間シミュレート"</string>
@@ -328,9 +333,10 @@
     <item msgid="8280754435979370728">"目に自然な色"</item>
     <item msgid="5363960654009010371">"デジタルコンテンツに最適な色"</item>
   </string-array>
-    <string name="inactive_apps_title" msgid="1317817863508274533">"休止中のアプリ"</string>
+    <string name="inactive_apps_title" msgid="9042996804461901648">"スタンバイ状態のアプリ"</string>
     <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"無効です。タップすると切り替わります。"</string>
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"有効です。タップすると切り替わります。"</string>
+    <string name="standby_bucket_summary" msgid="6567835350910684727">"アプリ スタンバイ状態: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <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>
@@ -352,16 +358,24 @@
     <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>
+    <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"残り時間: <xliff:g id="THRESHOLD">%1$s</xliff:g>未満"</string>
+    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> - 残り時間: <xliff:g id="THRESHOLD">%2$s</xliff:g>未満"</string>
+    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g> ー 残り時間: <xliff:g id="TIME_REMAINING">%2$s</xliff:g>以上"</string>
+    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"残り時間: <xliff:g id="TIME_REMAINING">%1$s</xliff:g>以上"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"スマートフォンの電源がもうすぐ切れます"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"タブレットの電源がもうすぐ切れます"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"端末の電源がもうすぐ切れます"</string>
+    <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>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> - スマートフォンの電源がもうすぐ切れます"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> - タブレットの電源がもうすぐ切れます"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> - 端末の電源がもうすぐ切れます"</string>
     <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>
@@ -411,4 +425,14 @@
     </plurals>
     <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"長くします。"</string>
     <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"短くします。"</string>
+    <string name="zen_mode_enable_dialog_turn_on" msgid="8287824809739581837">"ON にする"</string>
+    <string name="cancel" msgid="6859253417269739139">"キャンセル"</string>
+    <string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"マナーモードを ON にする"</string>
+    <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>
+    <string name="zen_alarm_warning_indef" msgid="3007988140196673193">"この設定を OFF にしないと次回のアラーム(<xliff:g id="WHEN">%1$s</xliff:g>)は鳴りません"</string>
+    <string name="zen_alarm_warning" msgid="6236690803924413088">"次回のアラーム(<xliff:g id="WHEN">%1$s</xliff:g>)は鳴りません"</string>
+    <string name="alarm_template" msgid="4996153414057676512">"<xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template_far" msgid="3779172822607461675">"<xliff:g id="WHEN">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ka/arrays.xml b/packages/SettingsLib/res/values-ka/arrays.xml
index 7e36f86..6e6d19c 100644
--- a/packages/SettingsLib/res/values-ka/arrays.xml
+++ b/packages/SettingsLib/res/values-ka/arrays.xml
@@ -234,10 +234,6 @@
     <item msgid="7688197031296835369">"overdraw არეების ჩვენება"</item>
     <item msgid="2290859360633824369">"დეუტერანომალიის არეების ჩვენება"</item>
   </string-array>
-  <string-array name="debug_hw_renderer_entries">
-    <item msgid="2578620445459945681">"OpenGL (ნაგულისხმევი)"</item>
-    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
-  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"სტანდარტული ლიმიტი"</item>
     <item msgid="4071574792028999443">"ფონური პროცესები არ არის"</item>
diff --git a/packages/SettingsLib/res/values-ka/strings.xml b/packages/SettingsLib/res/values-ka/strings.xml
index 6c08a98..a5fd213 100644
--- a/packages/SettingsLib/res/values-ka/strings.xml
+++ b/packages/SettingsLib/res/values-ka/strings.xml
@@ -53,16 +53,16 @@
     <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>
+    <string name="bluetooth_connected" msgid="5427152882755735944">"დაკავშირებულია<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
     <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>
+    <string name="bluetooth_connected_no_headset" msgid="616068069034994802">"დაკავშირებულია (ტელეფონი არ არის)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp" msgid="3736431800395923868">"დაკავშირებულია (მედია არ არის)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_map" msgid="3200033913678466453">"დაკავშირებულია (შეტყობინებებზე წვდომა არ არის)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2047403011284187056">"დაკავშირებულია (ტელეფონი ამ მედია არ არის)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_battery_level" msgid="5162924691231307748">"დაკავშირებულია. ბატარეის დონე: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"დაკავშირებულია (ტელეფონი არ არის). ბატარეის დონე: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"დაკავშირებულია (მედია არ არის). ბატარეა: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"დაკავშირებულია (ტელეფონი ან მედია არ არის). ბატარეის დონე: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"მედია აუდიო"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"სატელეფონო ზარები"</string>
     <string name="bluetooth_profile_opp" msgid="9168139293654233697">"ფაილების გადაცემა"</string>
@@ -75,6 +75,10 @@
     <string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM წვდომა"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD აუდიო: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD აუდიო"</string>
+    <!-- no translation found for bluetooth_profile_hearing_aid (7999237886427812595) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (7188282786730266159) -->
+    <skip />
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"დაკავშირებულია აუდიო მულტიმედიურ სისტემასთან"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"დაკავშირებულია ტელეფონის აუდიო მოწყობილობასთან"</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"დაკავშირებულია ფაილების გადაცემის სერვერთან"</string>
@@ -91,6 +95,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"გამოიყენეთ ტელეფონის აუდიომოწყობილობაში"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"ფაილების ტრანსფერისათვის გამოყენება"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"შეტანისთვის გამოყენება"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (908775281788309484) -->
+    <skip />
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"დაწყვილება"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"დაწყვილება"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"გაუქმება"</string>
@@ -275,7 +281,6 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"აპარატურის დონეების განახლებების ჩვენება"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"განახლებისას სააპარატო დონეების მწვანით მონიშვნა"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"GPU overdraw-ს გამართვა"</string>
-    <string name="debug_hw_renderer" msgid="7568529019431785816">"GPU Renderer-ის დაყენება"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"HW გადაფარვის გამორთვა"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"ეკრანის კომპოზიციისთვის ყოველთვის გამოიყენე GPU"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"ფერთა სივრცის სიმულაცია"</string>
@@ -328,9 +333,10 @@
     <item msgid="8280754435979370728">"თვალისთვის ხილული ბუნებრივი ფერები"</item>
     <item msgid="5363960654009010371">"ციფრული კონტენტისთვის ოპტიმიზებული ფერები"</item>
   </string-array>
-    <string name="inactive_apps_title" msgid="1317817863508274533">"უმოქმედო აპები"</string>
+    <string name="inactive_apps_title" msgid="9042996804461901648">"აპები მოლოდინის რეჟიმში"</string>
     <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"უმოქმედო. შეეხეთ გადასართავად."</string>
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"აქტიური. შეეხეთ გადასართავად."</string>
+    <string name="standby_bucket_summary" msgid="6567835350910684727">"აპის მოლოდინის რეჟიმის მდგომარეობა:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <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>
@@ -352,16 +358,24 @@
     <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>
+    <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"დარჩენილია <xliff:g id="THRESHOLD">%1$s</xliff:g>-ზე ნაკლები"</string>
+    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> — დარჩენილია <xliff:g id="THRESHOLD">%2$s</xliff:g>-ზე ნაკლები"</string>
+    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g>დარჩენილია <xliff:g id="TIME_REMAINING">%2$s</xliff:g>-ზე მეტი"</string>
+    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"დარჩენილია <xliff:g id="TIME_REMAINING">%1$s</xliff:g>-ზე მეტი"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"ტელეფონი შეიძლება მალე გაითიშოს"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"ტაბლეტი შეიძლება მალე გაითიშოს"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"მოწყობილობა შეიძლება მალე გაითიშოს"</string>
+    <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>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> — ტელეფონი შეიძლება მალე გაითიშოს"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> — ტაბლეტი შეიძლება მალე გაითიშოს"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> — მოწყობილობა შეიძლება მალე გაითიშოს"</string>
     <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>
@@ -409,4 +423,14 @@
     </plurals>
     <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"მეტი დრო."</string>
     <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"ნაკლები დრო."</string>
+    <string name="zen_mode_enable_dialog_turn_on" msgid="8287824809739581837">"ჩართვა"</string>
+    <string name="cancel" msgid="6859253417269739139">"გაუქმება"</string>
+    <string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"„არ შემაწუხოთ“ რეჟიმის ჩართვა"</string>
+    <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>
+    <string name="zen_alarm_warning_indef" msgid="3007988140196673193">"ვერ გაიგონებთ მომდევნო მაღვიძარას <xliff:g id="WHEN">%1$s</xliff:g>-ზე, თუ არ გამორთავთ ამას მანამდე"</string>
+    <string name="zen_alarm_warning" msgid="6236690803924413088">"ვერ გაიგონებთ მომდევნო მაღვიძარას <xliff:g id="WHEN">%1$s</xliff:g>-ზე"</string>
+    <string name="alarm_template" msgid="4996153414057676512">"<xliff:g id="WHEN">%1$s</xliff:g>-ზე"</string>
+    <string name="alarm_template_far" msgid="3779172822607461675">"<xliff:g id="WHEN">%1$s</xliff:g>-ზე"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml
index d9a7d03..7ac1f89 100644
--- a/packages/SettingsLib/res/values-kk/strings.xml
+++ b/packages/SettingsLib/res/values-kk/strings.xml
@@ -53,16 +53,16 @@
     <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>
+    <string name="bluetooth_connected" msgid="5427152882755735944">"<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> жалғанды"</string>
     <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>
+    <string name="bluetooth_connected_no_headset" msgid="616068069034994802">"<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> жалғанды (телефонсыз)"</string>
+    <string name="bluetooth_connected_no_a2dp" msgid="3736431800395923868">"<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> жалғанды (аудиосыз)"</string>
+    <string name="bluetooth_connected_no_map" msgid="3200033913678466453">"<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> жалғанды (хабарларға кіруге рұқсат жоқ)"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2047403011284187056">"<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> жалғанды (телефонсыз не аудиосыз)"</string>
+    <string name="bluetooth_connected_battery_level" msgid="5162924691231307748">"Жалғанды, батарея заряды: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"Жалғанды (телефонсыз), батарея заряды: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"Жалғанды (аудиосыз), батарея заряды: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"Жалғанды (телефонсыз не аудиосыз), батарея заряды: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Meдиа аудиосы"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"Телефон қоңыраулары"</string>
     <string name="bluetooth_profile_opp" msgid="9168139293654233697">"Файл жіберу"</string>
@@ -75,6 +75,10 @@
     <string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM картасына кіру"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD форматты аудиомазмұн: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD форматты аудиомазмұн"</string>
+    <!-- no translation found for bluetooth_profile_hearing_aid (7999237886427812595) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (7188282786730266159) -->
+    <skip />
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Медиа аудиосына жалғанған"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Телефон аудиосына қосылған"</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Файл жіберу серверіне жалғанған"</string>
@@ -91,6 +95,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Телефон аудиосы үшін қолдану"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Файлды жіберу үшін қолдану"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Кіріс үшін қолдану"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (908775281788309484) -->
+    <skip />
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Жұптау"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"ЖҰПТАУ"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Бас тарту"</string>
@@ -327,9 +333,10 @@
     <item msgid="8280754435979370728">"Көзбен көргендегі табиғи түстер"</item>
     <item msgid="5363960654009010371">"Сандық мазмұн үшін оңтайландырылған түстер"</item>
   </string-array>
-    <string name="inactive_apps_title" msgid="1317817863508274533">"Белсенді емес қолданбалар"</string>
+    <string name="inactive_apps_title" msgid="9042996804461901648">"Күту режиміндегі қолданбалар"</string>
     <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"Белсенді емес. Ауыстырып қосу үшін түртіңіз."</string>
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"Белсенді. Ауыстырып қосу үшін түртіңіз."</string>
+    <string name="standby_bucket_summary" msgid="6567835350910684727">"Қолданбаның күту режимі: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <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 +358,24 @@
     <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>
+    <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"<xliff:g id="THRESHOLD">%1$s</xliff:g> мәнінен аз қалды"</string>
+    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="THRESHOLD">%2$s</xliff:g> мәнінен аз қалды"</string>
+    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g><xliff:g id="TIME_REMAINING">%2$s</xliff:g> үстінде қалды"</string>
+    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> үстінде қалды"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"телефон көп ұзамай өшуі мүмкін"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"планшет көп ұзамай өшуі мүмкін"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"құрылғы көп ұзамай өшуі мүмкін"</string>
+    <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>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> – телефон көп ұзамай өшуі мүмкін"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> – планшет көп ұзамай өшуі мүмкін"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> – құрылғы көп ұзамай өшуі мүмкін"</string>
     <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 +429,8 @@
     <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>
+    <string name="zen_alarm_warning_indef" msgid="3007988140196673193">"Мұны ертерек өшіріп қоймасаңыз, келесі дабыл (уақыты: <xliff:g id="WHEN">%1$s</xliff:g>) естілмейді"</string>
+    <string name="zen_alarm_warning" msgid="6236690803924413088">"Келесі дабылыңыз (уақыты: <xliff:g id="WHEN">%1$s</xliff:g>) естілмейді"</string>
+    <string name="alarm_template" msgid="4996153414057676512">"Уақыты: <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template_far" msgid="3779172822607461675">"Күні: <xliff:g id="WHEN">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml
index da55fbf..c3c5f82 100644
--- a/packages/SettingsLib/res/values-km/strings.xml
+++ b/packages/SettingsLib/res/values-km/strings.xml
@@ -53,16 +53,16 @@
     <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>
+    <string name="bluetooth_connected" msgid="5427152882755735944">"បាន​ភ្ជាប់ <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
     <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>
+    <string name="bluetooth_connected_no_headset" msgid="616068069034994802">"បាន​ភ្ជាប់ (គ្មាន​ទូរសព្ទ​ទេ)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp" msgid="3736431800395923868">"បាន​ភ្ជាប់ (គ្មាន​មេឌៀ​ទេ)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_map" msgid="3200033913678466453">"បាន​ភ្ជាប់ (គ្មាន​ការ​ចូល​ប្រើ​សារ​ទេ)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2047403011284187056">"បាន​ភ្ជាប់ (គ្មាន​ទូរសព្ទ ឬ​មេឌៀ​ទេ)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_battery_level" msgid="5162924691231307748">"បានភ្ជាប់ ហើយ​ថ្ម​មាន​កម្រិត <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"បាន​ភ្ជាប់ (គ្មាន​ទូរសព្ទ​ទេ) ហើយ​ថ្ម​មាន​កម្រិត <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"បាន​ភ្ជាប់ (គ្មាន​មេឌៀ​ទេ) ហើយ​ថ្ម​មាន​កម្រិត <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"បាន​ភ្ជាប់ (គ្មាន​ទូរសព្ទ ឬ​មេឌៀ​ទេ) ហើយ​ថ្ម​មាន​កម្រិត <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"សំឡេង​មេឌៀ"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"ការហៅ​ទូរសព្ទ"</string>
     <string name="bluetooth_profile_opp" msgid="9168139293654233697">"ផ្ទេរ​ឯកសារ"</string>
@@ -75,6 +75,10 @@
     <string name="bluetooth_profile_sap" msgid="5764222021851283125">"ការចូលដំណើរការស៊ីម"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"សំឡេងកម្រិត HD៖ <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"សំឡេងកម្រិត HD"</string>
+    <!-- no translation found for bluetooth_profile_hearing_aid (7999237886427812595) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (7188282786730266159) -->
+    <skip />
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"បា​ន​ភ្ជាប់​ទៅ​អូឌីយ៉ូ​មេឌៀ"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"តភ្ជាប់​ទៅ​អូឌីយ៉ូ​ទូរស័ព្ទ"</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"បាន​តភ្ជាប់​ទៅ​ម៉ាស៊ីន​មេ​ផ្ទេរ​ឯកសារ"</string>
@@ -91,6 +95,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"ប្រើ​សម្រាប់​​អូឌីយ៉ូ​ទូរស័ព្ទ"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"ប្រើ​សម្រាប់​ផ្ទេរ​ឯកសារ"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"ប្រើ​សម្រាប់​បញ្ចូល"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (908775281788309484) -->
+    <skip />
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"ផ្គូផ្គង"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"ផ្គូផ្គង"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"បោះ​បង់​"</string>
@@ -327,9 +333,10 @@
     <item msgid="8280754435979370728">"ពណ៌ធម្មជាតិដូចដែលបានឃើញដោយភ្នែក"</item>
     <item msgid="5363960654009010371">"ពណ៌ដែលបានសម្រួលសម្រាប់មាតិកាឌីជីថល"</item>
   </string-array>
-    <string name="inactive_apps_title" msgid="1317817863508274533">"កម្មវិធីដែលអសកម្ម"</string>
+    <string name="inactive_apps_title" msgid="9042996804461901648">"កម្មវិធី​ផ្អាក​ដំណើរការ"</string>
     <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"សកម្ម។ ប៉ះដើម្បីបិទ/បើក។"</string>
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"សកម្ម។ ប៉ះដើម្បីបិទ/បើក។"</string>
+    <string name="standby_bucket_summary" msgid="6567835350910684727">"ស្ថាន​ភាព​មុខងារ​ផ្អាក​ដំណើរការ​កម្មវិធី៖<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <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 +358,24 @@
     <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>
+    <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"នៅ​សល់​តិច​ជាង <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
+    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g>៖ នៅ​សល់​តិច​ជាង <xliff:g id="THRESHOLD">%2$s</xliff:g>"</string>
+    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g>៖ នៅ​សល់​ច្រើន​ជាង <xliff:g id="TIME_REMAINING">%2$s</xliff:g>"</string>
+    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"នៅ​សល់​ច្រើន​ជាង <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"ទូរសព្ទ​អាច​នឹង​បិទ​ក្នុង​ពេល​បន្តិច​ទៀត"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"ថេប្លេត​អាច​នឹង​បិទ​ក្នុង​ពេល​បន្តិច​ទៀត"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"ឧបករណ៍​អាច​នឹង​បិទ​ក្នុង​ពេល​បន្តិច​ទៀត"</string>
+    <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>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g>៖ ទូរសព្ទ​អាច​នឹង​បិទ​ក្នុង​ពេល​បន្តិច​ទៀត"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g>៖ ថេប្លេត​អាច​នឹង​បិទ​ក្នុង​ពេល​បន្តិច​ទៀត"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g>៖ ឧបករណ៍​អាច​នឹង​បិទ​ក្នុង​ពេល​បន្តិច​ទៀត"</string>
     <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 +429,8 @@
     <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>
+    <string name="zen_alarm_warning_indef" msgid="3007988140196673193">"អ្នក​នឹង​មិន​ឮ​ម៉ោង​រោទ៍​បន្ទាប់​របស់​អ្នក​នៅ​ម៉ោង <xliff:g id="WHEN">%1$s</xliff:g> ទេ លុះត្រាតែអ្នក​​បិទ​វា​មុន​ពេល​នោះ"</string>
+    <string name="zen_alarm_warning" msgid="6236690803924413088">"អ្នក​នឹង​មិន​ឮ​ម៉ោង​រោទ៍​បន្ទាប់​របស់​អ្នក​នៅ​ម៉ោង <xliff:g id="WHEN">%1$s</xliff:g> ទេ"</string>
+    <string name="alarm_template" msgid="4996153414057676512">"នៅ​ម៉ោង <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template_far" msgid="3779172822607461675">"នៅ​ថ្ងៃ <xliff:g id="WHEN">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml
index 1e53b88..400be09 100644
--- a/packages/SettingsLib/res/values-kn/strings.xml
+++ b/packages/SettingsLib/res/values-kn/strings.xml
@@ -53,16 +53,16 @@
     <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>
+    <string name="bluetooth_connected" msgid="5427152882755735944">"<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> ಗೆ ಸಂಪರ್ಕಗೊಂಡಿದೆ"</string>
     <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>
+    <string name="bluetooth_connected_no_headset" msgid="616068069034994802">"ಸಂಪರ್ಕಗೊಂಡಿದೆ (ಫೋನ್ ಇಲ್ಲ)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp" msgid="3736431800395923868">"ಸಂಪರ್ಕಗೊಂಡಿದೆ (ಮಾಧ್ಯಮವಿಲ್ಲ)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_map" msgid="3200033913678466453">"<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> ಗೆ (ಸಂದೇಶ ಪ್ರವೇಶವಿಲ್ಲ) ಸಂಪರ್ಕಗೊಂಡಿದೆ"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2047403011284187056">"ಸಂಪರ್ಕಗೊಂಡಿದೆ (ಫೋನ್ ಅಥವಾ ಮಾಧ್ಯಮವಿಲ್ಲ)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_battery_level" msgid="5162924691231307748">"ಸಂಪರ್ಕಗೊಂಡಿದೆ, ಬ್ಯಾಟರಿ ಚಾರ್ಜ್‌ ಮಟ್ಟ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"ಸಂಪರ್ಕಗೊಂಡಿದೆ (ಫೋನ್ ಇಲ್ಲ), ಬ್ಯಾಟರಿ ಚಾರ್ಜ್‌ ಮಟ್ಟ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"ಸಂಪರ್ಕಗೊಂಡಿದೆ (ಮಾಧ್ಯಮವಿಲ್ಲ), ಬ್ಯಾಟರಿ ಚಾರ್ಜ್‌ ಮಟ್ಟ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"ಸಂಪರ್ಕಗೊಂಡಿದೆ (ಫೋನ್ ಅಥವಾ ಮಾಧ್ಯಮವಿಲ್ಲ), ಬ್ಯಾಟರಿ ಚಾರ್ಜ್‌ ಮಟ್ಟ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"ಮಾಧ್ಯಮ ಆಡಿಯೋ"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"ಫೋನ್ ಕರೆಗಳು"</string>
     <string name="bluetooth_profile_opp" msgid="9168139293654233697">"ಫೈಲ್ ವರ್ಗಾವಣೆ"</string>
@@ -75,6 +75,10 @@
     <string name="bluetooth_profile_sap" msgid="5764222021851283125">"ಸಿಮ್ ಪ್ರವೇಶ"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD ಆಡಿಯೋ: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD ಆಡಿಯೋ"</string>
+    <!-- no translation found for bluetooth_profile_hearing_aid (7999237886427812595) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (7188282786730266159) -->
+    <skip />
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"ಮಾಧ್ಯಮ ಆಡಿಯೋಗೆ ಸಂಪರ್ಕಗೊಂಡಿದೆ"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"ಫೋನ್ ಆಡಿಯೋಗೆ ಸಂಪರ್ಕಗೊಂಡಿದೆ"</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"ಫೈಲ್ ವರ್ಗಾವಣೆ ಸರ್ವರ್‌ಗೆ ಸಂಪರ್ಕಗೊಂಡಿದೆ"</string>
@@ -91,6 +95,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"ಫೋನ್‌ ಆಡಿಯೋಗಾಗಿ ಬಳಕೆ"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"ಫೈಲ್‌ ವರ್ಗಾವಣೆಗಾಗಿ ಬಳಸು"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"ಇನ್‌ಪುಟ್‌ಗಾಗಿ ಬಳಸು"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (908775281788309484) -->
+    <skip />
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"ಜೋಡಿ"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"ಜೋಡಿ ಮಾಡು"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"ರದ್ದುಮಾಡಿ"</string>
@@ -327,9 +333,10 @@
     <item msgid="8280754435979370728">"ಕಣ್ಣಿಗೆ ಕಾಣಿಸುವ ರೀತಿಯಲ್ಲಿ ನೈಸರ್ಗಿಕ ಬಣ್ಣಗಳು"</item>
     <item msgid="5363960654009010371">"ಡಿಜಿಟಲ್ ವಿಷಯಕ್ಕಾಗಿ ಆಪ್ಟಿಮೈಜ್ ಮಾಡಲಾಗಿರುವ ಬಣ್ಣಗಳು"</item>
   </string-array>
-    <string name="inactive_apps_title" msgid="1317817863508274533">"ನಿಷ್ಕ್ರಿಯ ಅಪ್ಲಿಕೇಶನ್‌ಗಳು"</string>
+    <string name="inactive_apps_title" msgid="9042996804461901648">"ಸ್ಟ್ಯಾಂಡ್‌ಬೈ ಅಪ್ಲಿಕೇಶನ್‌ಗಳು"</string>
     <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"ನಿಷ್ಕ್ರಿಯ. ಟಾಗಲ್ ಮಾಡಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string>
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"ಸಕ್ರಿಯ. ಟಾಗಲ್ ಮಾಡಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string>
+    <string name="standby_bucket_summary" msgid="6567835350910684727">"ಅಪ್ಲಿಕೇಶನ್ ಸ್ಟ್ಯಾಂಡ್‌ಬೈ ಸ್ಥಿತಿ:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <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 +358,24 @@
     <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>
+    <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"<xliff:g id="THRESHOLD">%1$s</xliff:g> ನಿಮಿಷಕ್ಕಿಂತ ಕಡಿಮೆ ಸಮಯ ಉಳಿದಿದೆ"</string>
+    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> - ರಷ್ಟು <xliff:g id="THRESHOLD">%2$s</xliff:g> ಕ್ಕಿಂತ ಕಡಿಮೆ ಸಮಯ ಬಾಕಿ ಉಳಿದಿದೆ"</string>
+    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g> ರಷ್ಟು <xliff:g id="TIME_REMAINING">%2$s</xliff:g> ಕ್ಕಿಂತ ಹೆಚ್ಚು ಸಮಯ ಬಾಕಿ ಉಳಿದಿದೆ"</string>
+    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> ಕ್ಕಿಂತ ಹೆಚ್ಚು ಸಮಯ ಉಳಿದಿದೆ"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"ಫೋನ್ ಶೀಘ್ರದಲ್ಲೇ ಶಟ್ ಡೌನ್ ಆಗಬಹುದು"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"ಟ್ಯಾಬ್ಲೆಟ್‌‌ ಶೀಘ್ರದಲ್ಲೇ ಶಟ್ ಡೌನ್ ಆಗಬಹುದು"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"ಸಾಧನವು ಶೀಘ್ರದಲ್ಲೇ ಶಟ್ ಡೌನ್ ಆಗಬಹುದು"</string>
+    <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>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> - ಫೋನ್ ಶೀಘ್ರದಲ್ಲೇ ಶಟ್ ಡೌನ್ ಆಗಬಹುದು"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> - ಟ್ಯಾಬ್ಲೆಟ್‌‌ ಶೀಘ್ರದಲ್ಲೇ ಶಟ್ ಡೌನ್ ಆಗಬಹುದು"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> - ಸಾಧನವು ಶೀಘ್ರದಲ್ಲೇ ಶಟ್ ಡೌನ್ ಆಗಬಹುದು"</string>
     <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 +429,8 @@
     <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>
+    <string name="zen_alarm_warning_indef" msgid="3007988140196673193">"ನೀವು ಇದನ್ನು ಆಫ್ ಮಾಡದ ಹೊರತು <xliff:g id="WHEN">%1$s</xliff:g> ಗಂಟೆಯ ಅಲಾರಮ್ ಅನ್ನು ನೀವು ಆಲಿಸುವುದಿಲ್ಲ"</string>
+    <string name="zen_alarm_warning" msgid="6236690803924413088">"ನಿಮ್ಮ ಮುಂದಿನ <xliff:g id="WHEN">%1$s</xliff:g> ಅಲಾರಮ್ ಅನ್ನು ನೀವು ಆಲಿಸುವುದಿಲ್ಲ"</string>
+    <string name="alarm_template" msgid="4996153414057676512">"<xliff:g id="WHEN">%1$s</xliff:g> ರಲ್ಲಿ"</string>
+    <string name="alarm_template_far" msgid="3779172822607461675">"<xliff:g id="WHEN">%1$s</xliff:g> ಕ್ಕೆ"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ko/arrays.xml b/packages/SettingsLib/res/values-ko/arrays.xml
index 3dbf759..27c4c8c 100644
--- a/packages/SettingsLib/res/values-ko/arrays.xml
+++ b/packages/SettingsLib/res/values-ko/arrays.xml
@@ -234,10 +234,6 @@
     <item msgid="7688197031296835369">"오버드로 영역 표시"</item>
     <item msgid="2290859360633824369">"녹색약 영역 표시"</item>
   </string-array>
-  <string-array name="debug_hw_renderer_entries">
-    <item msgid="2578620445459945681">"OpenGL(기본)"</item>
-    <item msgid="2839130076198120436">"OpenGL(Skia)"</item>
-  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"표준 제한"</item>
     <item msgid="4071574792028999443">"백그라운드 프로세스 없음"</item>
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index f2f952d..ab02029 100644
--- a/packages/SettingsLib/res/values-ko/strings.xml
+++ b/packages/SettingsLib/res/values-ko/strings.xml
@@ -45,7 +45,7 @@
     <string name="available_via_carrier" msgid="1469036129740799053">"%1$s을(를) 통해 사용 가능"</string>
     <string name="speed_label_very_slow" msgid="1867055264243608530">"매우 느림"</string>
     <string name="speed_label_slow" msgid="813109590815810235">"느림"</string>
-    <string name="speed_label_okay" msgid="2331665440671174858">"확인"</string>
+    <string name="speed_label_okay" msgid="2331665440671174858">"보통"</string>
     <string name="speed_label_medium" msgid="3175763313268941953">"보통"</string>
     <string name="speed_label_fast" msgid="7715732164050975057">"빠름"</string>
     <string name="speed_label_very_fast" msgid="2265363430784523409">"매우 빠름"</string>
@@ -53,16 +53,16 @@
     <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>
+    <string name="bluetooth_connected" msgid="5427152882755735944">"연결됨<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
     <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>
+    <string name="bluetooth_connected_no_headset" msgid="616068069034994802">"연결됨(전화 없음)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp" msgid="3736431800395923868">"연결됨(미디어 없음)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_map" msgid="3200033913678466453">"연결됨(메시지 액세스 권한 없음)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2047403011284187056">"연결됨(전화 또는 미디어 없음)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_battery_level" msgid="5162924691231307748">"연결됨, 배터리 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"연결됨(전화 없음), 배터리 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"연결됨(미디어 없음), 배터리 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"연결됨(전화 또는 미디어 없음), 배터리 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"미디어 오디오"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"전화 통화"</string>
     <string name="bluetooth_profile_opp" msgid="9168139293654233697">"파일 전송"</string>
@@ -75,6 +75,10 @@
     <string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM 액세스"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD 오디오: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD 오디오"</string>
+    <!-- no translation found for bluetooth_profile_hearing_aid (7999237886427812595) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (7188282786730266159) -->
+    <skip />
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"미디어 오디오에 연결됨"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"휴대전화 오디오에 연결됨"</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"파일 전송 서버에 연결됨"</string>
@@ -91,6 +95,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"휴대전화 오디오에 사용"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"파일 전송에 사용"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"입력에 사용"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (908775281788309484) -->
+    <skip />
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"페어링"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"페어링"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"취소"</string>
@@ -275,7 +281,6 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"하드웨어 업데이트 표시"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"업데이트 할 때 하드웨어 레이어 깜박이기"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"GPU 오버드로 디버깅"</string>
-    <string name="debug_hw_renderer" msgid="7568529019431785816">"GPU 렌더기 설정"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"HW 오버레이 사용 안함"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"화면 합성 목적으로 항상 GPU 사용"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"색상 공간 시뮬레이션"</string>
@@ -328,9 +333,10 @@
     <item msgid="8280754435979370728">"눈으로 보는 듯한 내츄럴 색상"</item>
     <item msgid="5363960654009010371">"디지털 콘텐츠에 최적화된 색상"</item>
   </string-array>
-    <string name="inactive_apps_title" msgid="1317817863508274533">"비활성 앱"</string>
+    <string name="inactive_apps_title" msgid="9042996804461901648">"대기 앱"</string>
     <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"비활성화 상태입니다. 전환하려면 탭하세요."</string>
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"활성화되었습니다. 전환하려면 탭하세요."</string>
+    <string name="standby_bucket_summary" msgid="6567835350910684727">"앱 대기 상태:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <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>
@@ -352,16 +358,24 @@
     <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>
+    <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"<xliff:g id="THRESHOLD">%1$s</xliff:g> 미만 남음"</string>
+    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="THRESHOLD">%2$s</xliff:g> 미만 남음"</string>
+    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g><xliff:g id="TIME_REMAINING">%2$s</xliff:g> 이상 남음"</string>
+    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> 이상 남음"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"휴대전화가 곧 종료될 수 있음"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"태블릿이 곧 종료될 수 있음"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"기기가 곧 종료될 수 있음"</string>
+    <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>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> - 휴대전화가 곧 종료될 수 있음"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> - 태블릿이 곧 종료될 수 있음"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> - 기기가 곧 종료될 수 있음"</string>
     <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>
@@ -409,4 +423,14 @@
     </plurals>
     <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"시간 늘리기"</string>
     <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"시간 줄이기"</string>
+    <string name="zen_mode_enable_dialog_turn_on" msgid="8287824809739581837">"켜기"</string>
+    <string name="cancel" msgid="6859253417269739139">"취소"</string>
+    <string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"알림 일시중지 사용 설정"</string>
+    <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>
+    <string name="zen_alarm_warning_indef" msgid="3007988140196673193">"그때까지 알림 일시중지 상태를 유지하면 <xliff:g id="WHEN">%1$s</xliff:g>에 다음 알람을 들을 수 없습니다."</string>
+    <string name="zen_alarm_warning" msgid="6236690803924413088">"<xliff:g id="WHEN">%1$s</xliff:g>에 다음 알람을 들을 수 없습니다."</string>
+    <string name="alarm_template" msgid="4996153414057676512">"시간: <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template_far" msgid="3779172822607461675">"일시: <xliff:g id="WHEN">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml
index 1fc446f..993fc33 100644
--- a/packages/SettingsLib/res/values-ky/strings.xml
+++ b/packages/SettingsLib/res/values-ky/strings.xml
@@ -53,16 +53,16 @@
     <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>
+    <string name="bluetooth_connected" msgid="5427152882755735944">"Туташып турат<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
     <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>
+    <string name="bluetooth_connected_no_headset" msgid="616068069034994802">"Туташып турат (телефониясыз)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp" msgid="3736431800395923868">"Туташып турат (медиасыз)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_map" msgid="3200033913678466453">"Туташып турат (SMS/MMS жазышуусуз)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2047403011284187056">"Туташып турат (телефониясыз же медиасыз)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_battery_level" msgid="5162924691231307748">"Туташып турат, батареянын деңгээли – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"Туташып турат (телефониясыз), батареянын деңгээли – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"Туташып турат (медиасыз), батареянын деңгээли – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"Туташып турат (телефониясыз же медиасыз), батареянын деңгээли – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Аудио"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"Телефон чалуулар"</string>
     <string name="bluetooth_profile_opp" msgid="9168139293654233697">"Файл алмашуу"</string>
@@ -75,6 +75,10 @@
     <string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM картаны пайдалануу мүмкүнчүлүгү"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD форматындагы аудио: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD форматындагы аудио"</string>
+    <!-- no translation found for bluetooth_profile_hearing_aid (7999237886427812595) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (7188282786730266159) -->
+    <skip />
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Медиа аудиого туташты"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Телефон аудиосуна туташты"</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Файл өткөрүү серверине туташты"</string>
@@ -91,6 +95,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Телефон аудиосу үчүн колдонулсун"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Файл өткөрүү үчүн колдонулсун"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Киргизүү үчүн колдонулсун"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (908775281788309484) -->
+    <skip />
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Жупташтыруу"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"ЖУПТАШТЫРУУ"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Жок"</string>
@@ -327,9 +333,10 @@
     <item msgid="8280754435979370728">"Көзгө көрүнгөн табигый түстөр"</item>
     <item msgid="5363960654009010371">"Санарип мазмун үчүн оптималдаштырылган түстөр"</item>
   </string-array>
-    <string name="inactive_apps_title" msgid="1317817863508274533">"Иштебеген колдонмолор"</string>
+    <string name="inactive_apps_title" msgid="9042996804461901648">"Көшүү режиминдеги колдонмолор"</string>
     <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"Иштеген жок. Которуштуруу үчүн таптап коюңуз."</string>
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"Иштеп турат. Которуштуруу үчүн таптап коюңуз."</string>
+    <string name="standby_bucket_summary" msgid="6567835350910684727">"Көшүү режиминдеги колдонмонун абалы:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <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 +358,24 @@
     <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>
+    <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"<xliff:g id="THRESHOLD">%1$s</xliff:g> жетпеген убакыт калды"</string>
+    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="THRESHOLD">%2$s</xliff:g> жетпеген убакыт калды"</string>
+    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME_REMAINING">%2$s</xliff:g> көп убакыт калды"</string>
+    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> көп убакыт калды"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"телефон бир аздан кийин өчүп калышы мүмкүн"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"планшет бир аздан кийин өчүп калышы мүмкүн"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"түзмөк бир аздан кийин өчүп калышы мүмкүн"</string>
+    <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>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> – телефон бир аздан кийин өчүп калышы мүмкүн"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> – планшет бир аздан кийин өчүп калышы мүмкүн"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> – түзмөк бир аздан кийин өчүп калышы мүмкүн"</string>
     <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 +429,8 @@
     <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>
+    <string name="zen_alarm_warning_indef" msgid="3007988140196673193">"Бул нерсе өчүрүлмөйүнчө <xliff:g id="WHEN">%1$s</xliff:g> боло турган кийинки ойготкучту укпайсыз"</string>
+    <string name="zen_alarm_warning" msgid="6236690803924413088">"<xliff:g id="WHEN">%1$s</xliff:g> боло турган кийинки ойготкучту укпайсыз"</string>
+    <string name="alarm_template" msgid="4996153414057676512">"саат <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template_far" msgid="3779172822607461675">"<xliff:g id="WHEN">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-lo/strings.xml b/packages/SettingsLib/res/values-lo/strings.xml
index f65d894..669b055 100644
--- a/packages/SettingsLib/res/values-lo/strings.xml
+++ b/packages/SettingsLib/res/values-lo/strings.xml
@@ -53,16 +53,16 @@
     <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>
+    <string name="bluetooth_connected" msgid="5427152882755735944">"ເຊື່ອມຕໍ່ແລ້ວ<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
     <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>
+    <string name="bluetooth_connected_no_headset" msgid="616068069034994802">"ເຊື່ອມຕໍ່ແລ້ວ (ບໍ່ມີໂທລະສັບ)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp" msgid="3736431800395923868">"ເຊື່ອມຕໍ່ແລ້ວ (ບໍ່ມີມີເດຍ)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_map" msgid="3200033913678466453">"ເຊື່ອມຕໍ່ແລ້ວ (ບໍ່ມີສິດເຂົ້າອ່ານຂໍ້ຄວາມ)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2047403011284187056">"ເຊື່ອມຕໍ່ແລ້ວ (ບໍ່ມີໂທລະສັບ ຫຼື ມີເດຍ)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_battery_level" msgid="5162924691231307748">"ເຊື່ອມຕໍ່ແລ້ວ, ແບັດເຕີຣີ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"ເຊື່ອມຕໍ່ແລ້ວ (ບໍ່ມີໂທລະສັບ), ແບັດເຕີຣີ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"ເຊື່ອມຕໍ່ແລ້ວ (ບໍ່ມີມີເດຍ), ແບັດເຕີຣີ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"ເຊື່ອມຕໍ່ແລ້ວ (ບໍ່ມີໂທລະສັບ ຫຼື ມີເດຍ), ແບັດເຕີຣີ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"ສຽງ"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"ການໂທ"</string>
     <string name="bluetooth_profile_opp" msgid="9168139293654233697">"ການໂອນຍ້າຍໄຟລ໌"</string>
@@ -75,6 +75,10 @@
     <string name="bluetooth_profile_sap" msgid="5764222021851283125">"ການ​ເຂົ້າ​ເຖິງ SIM"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"ສຽງ HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"ສຽງ HD"</string>
+    <!-- no translation found for bluetooth_profile_hearing_aid (7999237886427812595) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (7188282786730266159) -->
+    <skip />
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"ເຊື່ອມຕໍ່ກັບສື່ດ້ານສຽງແລ້ວ"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"ເຊື່ອມຕໍ່ກັບສຽງໂທລະສັບແລ້ວ"</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"ເຊື່ອມຕໍ່ກັບເຊີບເວີໂອນຍ້າຍໄຟລ໌ແລ້ວ"</string>
@@ -91,6 +95,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"ໃຊ້ສຳລັບລະບົບສຽງຂອງໂທລະສັບ"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"ໃຊ້ເພື່ອໂອນຍ້າຍໄຟລ໌"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"ໃຊ້ສຳລັບການປ້ອນຂໍ້ມູນ"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (908775281788309484) -->
+    <skip />
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"ຈັບຄູ່"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"ຈັບຄູ່"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"ຍົກເລີກ"</string>
@@ -327,9 +333,10 @@
     <item msgid="8280754435979370728">"ສີ​ທຳ​ມະ​ຊາດ​ຕາມ​ທີ່​ເຫັນ​ດ້ວຍ​ຕາ"</item>
     <item msgid="5363960654009010371">"ສີ​ທີ່​ປັບ​ໃຫ້​ເໝາະ​ສົມ​ສຳ​ລັບ​ເນື້ອ​ໃນ​ດິ​ຈີ​ຕອ​ລ"</item>
   </string-array>
-    <string name="inactive_apps_title" msgid="1317817863508274533">"ແອັບ​ບໍ່​ໃຊ້​ງານ​ຢູ່"</string>
+    <string name="inactive_apps_title" msgid="9042996804461901648">"ແອັບສະແຕນບາຍ"</string>
     <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"ບໍ່ໄດ້ນຳໃຊ້. ແຕະບໍ່ສັບປ່ຽນ."</string>
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"ນຳໃຊ້ຢູ່. ແຕະເພື່ອສັບປ່ຽນ."</string>
+    <string name="standby_bucket_summary" msgid="6567835350910684727">"ສະຖານະສະແຕນບາຍແອັບ:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <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 +358,24 @@
     <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>
+    <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"ຍັງເຫຼືອໜ້ອຍກວ່າ <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
+    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> - ຍັງເຫຼືອໜ້ອຍກວ່າ <xliff:g id="THRESHOLD">%2$s</xliff:g>"</string>
+    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g>ຍັງເຫຼືອຫຼາຍກວ່າ <xliff:g id="TIME_REMAINING">%2$s</xliff:g>"</string>
+    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"ຍັງເຫຼືອຫຼາຍກວ່າ <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"ໂທລະສັບອາດຈະປິດໃນໄວໆນີ້"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"ແທັຍເລັດອາດຈະປິດໃນໄວໆນີ້"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"ອຸປະກອນອາດຈະປິດໃນໄວໆນີ້"</string>
+    <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>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> - ໂທລະສັບອາດຈະປິດໃນໄວໆນີ້"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> - ແທັບເລັດອາດຈະປິດໃນໄວໆນີ້"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> - ອຸປະກອນອາດຈະປິດໃນໄວໆນີ້"</string>
     <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 +429,8 @@
     <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>
+    <string name="zen_alarm_warning_indef" msgid="3007988140196673193">"ທ່ານຈະບໍ່ໄດ້ຍິນສຽງໂມງປຸກເທື່ອຕໍ່ໄປຂອງທ່ານເວລາ <xliff:g id="WHEN">%1$s</xliff:g> ນອກຈາກວ່າທ່ານປິດອັນນີ້ກ່ອນ"</string>
+    <string name="zen_alarm_warning" msgid="6236690803924413088">"ທ່ານຈະບໍ່ໄດ້ຍິນສຽງໂມງປຸກເທື່ອຕໍ່ໄປຂອງທ່ານເວລາ <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template" msgid="4996153414057676512">"ເວລາ <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template_far" msgid="3779172822607461675">"ເວລາ <xliff:g id="WHEN">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-lt/arrays.xml b/packages/SettingsLib/res/values-lt/arrays.xml
index b4407ea..012ab35 100644
--- a/packages/SettingsLib/res/values-lt/arrays.xml
+++ b/packages/SettingsLib/res/values-lt/arrays.xml
@@ -234,10 +234,6 @@
     <item msgid="7688197031296835369">"Rodyti perdangos sritis"</item>
     <item msgid="2290859360633824369">"Rodyti deuteranomalijos sritis"</item>
   </string-array>
-  <string-array name="debug_hw_renderer_entries">
-    <item msgid="2578620445459945681">"„OpenGL“ (numatyt.)"</item>
-    <item msgid="2839130076198120436">"„OpenGL“ („Skia“)"</item>
-  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"Standartinis apribojimas"</item>
     <item msgid="4071574792028999443">"Nėra fono procesų"</item>
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index 879054e..5341e03 100644
--- a/packages/SettingsLib/res/values-lt/strings.xml
+++ b/packages/SettingsLib/res/values-lt/strings.xml
@@ -53,16 +53,16 @@
     <string name="bluetooth_disconnected" msgid="6557104142667339895">"Atsijungęs (-usi)"</string>
     <string name="bluetooth_disconnecting" msgid="8913264760027764974">"Atjungiama..."</string>
     <string name="bluetooth_connecting" msgid="8555009514614320497">"Prisijungiama..."</string>
-    <string name="bluetooth_connected" msgid="6038755206916626419">"Prisijungta"</string>
+    <string name="bluetooth_connected" msgid="5427152882755735944">"Prisijungta (<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>)"</string>
     <string name="bluetooth_pairing" msgid="1426882272690346242">"Susiejama..."</string>
-    <string name="bluetooth_connected_no_headset" msgid="2866994875046035609">"Prijungta (be telefono)"</string>
-    <string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Prijungta (be laikmenos)"</string>
-    <string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Prisijungta (be prieigos prie pranešimų)"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Prijungta (be telefono ar laikmenos)"</string>
-    <string name="bluetooth_connected_battery_level" msgid="7049181126136692368">"Prijungta, akumuliatorius <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_headset_battery_level" msgid="5504193961248406027">"Prijungta (be telefono), akumuliatorius <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="4751724026365870779">"Prijungta (be medijos), akumuliatorius <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1549265779323455261">"Prijungta (be telefono ar medijos), akumuliatorius <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset" msgid="616068069034994802">"Prisijungta (<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>), (telefono nėra)"</string>
+    <string name="bluetooth_connected_no_a2dp" msgid="3736431800395923868">"Prisijungta (<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>), (medijos nėra)"</string>
+    <string name="bluetooth_connected_no_map" msgid="3200033913678466453">"Prisij. (<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>), (prieigos prie praneš. nėra)"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2047403011284187056">"Prisijungta (<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>), (telef. ar medijos nėra)"</string>
+    <string name="bluetooth_connected_battery_level" msgid="5162924691231307748">"Prisijungta (<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>), akumuliatoriaus įkrovos lygis: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"Prisijungta (<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>), (telefono nėra), akumuliatoriaus įkrovos lygis: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"Prisijungta (<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>), (medijos nėra), akumuliatoriaus įkrovos lygis: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"Prisijungta (<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>), (telefono ar medijos nėra), akumuliatoriaus įkrovos lygis: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Laikmenos garsas"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"Telefono skambučiai"</string>
     <string name="bluetooth_profile_opp" msgid="9168139293654233697">"Failo perkėlimas"</string>
@@ -75,6 +75,10 @@
     <string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM prieiga"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD garsas: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD garsas"</string>
+    <!-- no translation found for bluetooth_profile_hearing_aid (7999237886427812595) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (7188282786730266159) -->
+    <skip />
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Prijungta prie medijos garso įrašo"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Prijungta prie telefono garso"</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Prijungta prie failų perkėlimo serverio"</string>
@@ -91,6 +95,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Naudoti telefono garso įrašui"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Naudoti failų perkėlimui"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Naudoti įvedant"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (908775281788309484) -->
+    <skip />
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Susieti"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"SUSIETI"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Atšaukti"</string>
@@ -275,7 +281,6 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"Rod. apar. įr. sl. nauj."</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Kai atsin. apar. įr. sl., rod. juos blyks. ž. sp."</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"Derinti GPU perdangą"</string>
-    <string name="debug_hw_renderer" msgid="7568529019431785816">"Nust. graf. proc. pateik."</string>
     <string name="disable_overlays" msgid="2074488440505934665">"Neleisti HW perdangų"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"Komponuojant ekraną visada naudoti GPU"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"Imituoti spalvų erdvę"</string>
@@ -328,9 +333,10 @@
     <item msgid="8280754435979370728">"Natūralios spalvos"</item>
     <item msgid="5363960654009010371">"Skaitmeniniam turiniui optimizuotos spalvos"</item>
   </string-array>
-    <string name="inactive_apps_title" msgid="1317817863508274533">"Neaktyvios programos"</string>
+    <string name="inactive_apps_title" msgid="9042996804461901648">"Budėjimo režimu veikiančios progr."</string>
     <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"Neaktyvi. Palieskite, kad perjungtumėte."</string>
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"Aktyvi. Palieskite, kad perjungtumėte."</string>
+    <string name="standby_bucket_summary" msgid="6567835350910684727">"Programų budėjimo režimo būsena: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="runningservices_settings_title" msgid="8097287939865165213">"Vykdomos paslaugos"</string>
     <string name="runningservices_settings_summary" msgid="854608995821032748">"Žiūrėti ir valdyti dabar vykdomas paslaugas"</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"„WebView“ diegimas"</string>
@@ -352,16 +358,24 @@
     <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Spalvų taisymas"</string>
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Ši funkcija yra eksperimentinė ir ji gali turėti įtakos našumui."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Nepaisyta naudojant nuostatą „<xliff:g id="TITLE">%1$s</xliff:g>“"</string>
-    <string name="power_remaining_duration_only" msgid="845431008899029842">"Liko maždaug <xliff:g id="TIME">^1</xliff:g>"</string>
-    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Liko maždaug <xliff:g id="TIME">^1</xliff:g>, atsižvelgiant į naudojimą"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Iki visiškos įkrovos liko <xliff:g id="TIME">^1</xliff:g>"</string>
-    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Liko <xliff:g id="TIME">^1</xliff:g>"</string>
-    <string name="power_remaining_duration_only_short_enhanced" msgid="7450425624026394823">"Liko <xliff:g id="TIME">^1</xliff:g>, atsižvelgiant į naudojimą"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">^1</xliff:g> – liko maždaug <xliff:g id="TIME">^2</xliff:g>"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">^1</xliff:g> – liko maždaug <xliff:g id="TIME">^2</xliff:g>, atsižvelgiant į naudojimą"</string>
-    <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> – liko <xliff:g id="TIME">^2</xliff:g>"</string>
+    <string name="power_remaining_duration_only" msgid="845431008899029842">"Liko maždaug <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Liko maždaug <xliff:g id="TIME">%1$s</xliff:g>, atsižvelgiant į naudojimą"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Iki visiškos įkrovos liko <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Liko <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Liko mažiau nei <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
+    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> – liko mažiau nei <xliff:g id="THRESHOLD">%2$s</xliff:g>"</string>
+    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g> – liko daugiau nei <xliff:g id="TIME_REMAINING">%2$s</xliff:g>"</string>
+    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"Liko daugiau nei <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"telefonas netrukus gali būti išjungtas"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"planšetinis komp. netrukus gali būti išjungtas"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"įrenginys netrukus gali būti išjungtas"</string>
+    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> – liko maždaug <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> – liko maždaug <xliff:g id="TIME">%2$s</xliff:g>, atsižvelgiant į naudojimą"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> – telefonas netrukus gali būti išjungtas"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> – planšetinis kompiuteris netrukus gali būti išjungtas"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> – įrenginys netrukus gali būti išjungtas"</string>
     <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> iki visiško įkrovimo"</string>
+    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> iki visiško įkrovimo"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Nežinomas"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Kraunasi..."</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"įkraunama"</string>
@@ -411,4 +425,14 @@
     </plurals>
     <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"Daugiau laiko."</string>
     <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"Mažiau laiko."</string>
+    <string name="zen_mode_enable_dialog_turn_on" msgid="8287824809739581837">"Įjungti"</string>
+    <string name="cancel" msgid="6859253417269739139">"Atšaukti"</string>
+    <string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"Netrukdymo režimo įjungimas"</string>
+    <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"Niekada"</string>
+    <string name="zen_interruption_level_priority" msgid="2078370238113347720">"Tik prioritetiniai"</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>
+    <string name="zen_alarm_warning_indef" msgid="3007988140196673193">"Negirdėsite kito signalo <xliff:g id="WHEN">%1$s</xliff:g>, nebent iki to laiko išjungsite šį režimą"</string>
+    <string name="zen_alarm_warning" msgid="6236690803924413088">"Negirdėsite kito signalo <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template" msgid="4996153414057676512">"<xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template_far" msgid="3779172822607461675">"<xliff:g id="WHEN">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-lv/arrays.xml b/packages/SettingsLib/res/values-lv/arrays.xml
index 09fc613..1286770 100644
--- a/packages/SettingsLib/res/values-lv/arrays.xml
+++ b/packages/SettingsLib/res/values-lv/arrays.xml
@@ -234,10 +234,6 @@
     <item msgid="7688197031296835369">"Rādīt apgab., kur pārsn. kapacitāte"</item>
     <item msgid="2290859360633824369">"Rādīt laukumus deiteranomālijai"</item>
   </string-array>
-  <string-array name="debug_hw_renderer_entries">
-    <item msgid="2578620445459945681">"OpenGL (noklusējums)"</item>
-    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
-  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"Standarta ierobežojums"</item>
     <item msgid="4071574792028999443">"Nav fona procesu"</item>
diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml
index 345d9af..dc771f8 100644
--- a/packages/SettingsLib/res/values-lv/strings.xml
+++ b/packages/SettingsLib/res/values-lv/strings.xml
@@ -53,16 +53,16 @@
     <string name="bluetooth_disconnected" msgid="6557104142667339895">"Atvienots"</string>
     <string name="bluetooth_disconnecting" msgid="8913264760027764974">"Notiek atvienošana..."</string>
     <string name="bluetooth_connecting" msgid="8555009514614320497">"Notiek savienojuma izveide…"</string>
-    <string name="bluetooth_connected" msgid="6038755206916626419">"Izveidots savienojums"</string>
+    <string name="bluetooth_connected" msgid="5427152882755735944">"Savienojums izveidots: <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
     <string name="bluetooth_pairing" msgid="1426882272690346242">"Notiek pāra izveide..."</string>
-    <string name="bluetooth_connected_no_headset" msgid="2866994875046035609">"Savienojums ir izveidots (nav tālruņa)"</string>
-    <string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Sav. ir izveidots (nav multivides)"</string>
-    <string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Savienots (nav piekļuves ziņojumam)"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Sav. ir izveidots (nav tel. vai multiv.)"</string>
-    <string name="bluetooth_connected_battery_level" msgid="7049181126136692368">"Savienojums izveidots, akumulatora uzlādes līmenis: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_headset_battery_level" msgid="5504193961248406027">"Savienojums izveidots (nav tālrunis), akumulatora uzlādes līmenis: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="4751724026365870779">"Savienojums izveidots (nav multivide), akumulatora uzlādes līmenis: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1549265779323455261">"Savienojums izveidots (nav tālrunis vai multivide), akumulatora uzlādes līmenis: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset" msgid="616068069034994802">"Savienojums izveidots (nav tālrunis): <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp" msgid="3736431800395923868">"Savienojums izveidots (nav multivide): <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_map" msgid="3200033913678466453">"Savienots (nav piekļuves ziņojumiem): <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2047403011284187056">"Savienots (nav tālrunis vai multivide): <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_battery_level" msgid="5162924691231307748">"Savienojums izveidots (<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>), akumulatora uzlādes līmenis: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"Savienojums izveidots <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (nav tālrunis), akumulatora uzlādes līmenis: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"Savienojums izveidots (<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>) (nav multivide), akumulatora uzlādes līmenis: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"Savienojums izveidots (nav tālrunis vai multivide) (<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>), akumulatora uzlādes līmenis: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Multivides audio"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"Tālruņa zvani"</string>
     <string name="bluetooth_profile_opp" msgid="9168139293654233697">"Failu pārsūtīšana"</string>
@@ -75,6 +75,10 @@
     <string name="bluetooth_profile_sap" msgid="5764222021851283125">"Piekļuve SIM kartei"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD audio: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD audio"</string>
+    <!-- no translation found for bluetooth_profile_hearing_aid (7999237886427812595) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (7188282786730266159) -->
+    <skip />
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Savienots ar multivides audio"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Savienots ar tālruņa audio"</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Savienots ar failu pārsūtīšanas serveri"</string>
@@ -91,6 +95,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Izmantot tālruņa skaņai"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Izmantot faila pārsūtīšanai"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Izmantot ievadei"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (908775281788309484) -->
+    <skip />
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Izveidot pāri"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"SAVIENOT PĀRĪ"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Atcelt"</string>
@@ -275,7 +281,6 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"Rādīt apar. slāņu atjaun."</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Atjaunin. aparatūras slāņiem ir jāmirgo zaļā krāsā"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"Atkļūdot graf. proc. kapac. pārsn."</string>
-    <string name="debug_hw_renderer" msgid="7568529019431785816">"Iestatīt GPU renderētāju"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"Atspējot HW pārklājumus"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"Vienmēr izmantot GPU atveidi ekrāna salikšanai"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"Simulēt krāstelpu"</string>
@@ -328,9 +333,10 @@
     <item msgid="8280754435979370728">"Dabiskas krāsas"</item>
     <item msgid="5363960654009010371">"Digitālajam saturam optimizētas krāsas"</item>
   </string-array>
-    <string name="inactive_apps_title" msgid="1317817863508274533">"Neaktīvās lietotnes"</string>
+    <string name="inactive_apps_title" msgid="9042996804461901648">"Lietotnes, kas darbojas fonā"</string>
     <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"Neaktīva. Pieskarieties, lai pārslēgtu."</string>
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"Aktīva. Pieskarieties, lai pārslēgtu."</string>
+    <string name="standby_bucket_summary" msgid="6567835350910684727">"Lietotnes gaidstāves stāvoklis: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="runningservices_settings_title" msgid="8097287939865165213">"Aktīvie pakalpojumi"</string>
     <string name="runningservices_settings_summary" msgid="854608995821032748">"Pašreiz darbojošos pakalpojumu skatīšana un vadība"</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView ieviešana"</string>
@@ -352,16 +358,24 @@
     <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Krāsu korekcija"</string>
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Šī funkcija ir eksperimentāla un var ietekmēt veiktspēju."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Jaunā preference: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only" msgid="845431008899029842">"Atlikušais laiks: aptuveni <xliff:g id="TIME">^1</xliff:g>"</string>
-    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Atlikušais laiks: aptuveni <xliff:g id="TIME">^1</xliff:g> (ņemot vērā lietojumu)"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Atlikušais laiks līdz pilnai uzlādei: <xliff:g id="TIME">^1</xliff:g>"</string>
-    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Atlicis: <xliff:g id="TIME">^1</xliff:g>"</string>
-    <string name="power_remaining_duration_only_short_enhanced" msgid="7450425624026394823">"Atlikušais laiks: <xliff:g id="TIME">^1</xliff:g> (ņemot vērā lietojumu)"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">^1</xliff:g> - vēl apmēram <xliff:g id="TIME">^2</xliff:g>"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">^1</xliff:g> — atlikušais laiks: aptuveni <xliff:g id="TIME">^2</xliff:g> (ņemot vērā lietojumu)"</string>
-    <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> — atlicis: <xliff:g id="TIME">^2</xliff:g>"</string>
+    <string name="power_remaining_duration_only" msgid="845431008899029842">"Atlikušais laiks: aptuveni <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Atlikušais laiks: aptuveni <xliff:g id="TIME">%1$s</xliff:g> (ņemot vērā lietojumu)"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Atlikušais laiks līdz pilnai uzlādei: <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Atlicis: <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Atlikušais laiks — mazāk nekā <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
+    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> — atlikušais laiks ir mazāk nekā <xliff:g id="THRESHOLD">%2$s</xliff:g>"</string>
+    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g> — atlikušais laiks ir vairāk nekā <xliff:g id="TIME_REMAINING">%2$s</xliff:g>"</string>
+    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"Atlikušais laiks — vairāk nekā <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"Tālrunis, iespējams, drīz izslēgsies."</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"Planšetdators, iespējams, drīz izslēgsies."</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"Ierīce, iespējams, drīz izslēgsies."</string>
+    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> - vēl apmēram <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> — atlikušais laiks: aptuveni <xliff:g id="TIME">%2$s</xliff:g> (ņemot vērā lietojumu)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> — tālrunis, iespējams, drīz izslēgsies."</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> — planšetdators, iespējams, drīz izslēgsies."</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> — ierīce, iespējams, drīz izslēgsies."</string>
     <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>, kamēr pilnībā uzlādēts"</string>
+    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>, kamēr pilnībā uzlādēts"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Nezināms"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Uzlāde"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"notiek uzlāde"</string>
@@ -410,4 +424,14 @@
     </plurals>
     <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"Vairāk laika."</string>
     <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"Mazāk laika."</string>
+    <string name="zen_mode_enable_dialog_turn_on" msgid="8287824809739581837">"Ieslēgt"</string>
+    <string name="cancel" msgid="6859253417269739139">"Atcelt"</string>
+    <string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"Režīma “Netraucēt” ieslēgšana"</string>
+    <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"Nekad"</string>
+    <string name="zen_interruption_level_priority" msgid="2078370238113347720">"Tikai prioritārie pārtraukumi"</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>
+    <string name="zen_alarm_warning_indef" msgid="3007988140196673193">"Nākamais signāls (<xliff:g id="WHEN">%1$s</xliff:g>) netiks atskaņots, ja līdz tam laikam neizslēgsiet šo iestatījumu."</string>
+    <string name="zen_alarm_warning" msgid="6236690803924413088">"Nākamais signāls (<xliff:g id="WHEN">%1$s</xliff:g>) netiks atskaņots."</string>
+    <string name="alarm_template" msgid="4996153414057676512">"plkst. <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template_far" msgid="3779172822607461675">"<xliff:g id="WHEN">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml
index 48c7bec..4ef3e86 100644
--- a/packages/SettingsLib/res/values-mk/strings.xml
+++ b/packages/SettingsLib/res/values-mk/strings.xml
@@ -53,16 +53,16 @@
     <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>
+    <string name="bluetooth_connected" msgid="5427152882755735944">"Поврзан со <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
     <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>
+    <string name="bluetooth_connected_no_headset" msgid="616068069034994802">"Поврзан со <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> (без телефон)"</string>
+    <string name="bluetooth_connected_no_a2dp" msgid="3736431800395923868">"Поврзан со <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> (без аудиовизуелни содржини)"</string>
+    <string name="bluetooth_connected_no_map" msgid="3200033913678466453">"Поврзан со <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> (без пристап до пораките)"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2047403011284187056">"Поврзан со <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> (без телефон и аудиовизуел.)"</string>
+    <string name="bluetooth_connected_battery_level" msgid="5162924691231307748">"Поврзан со <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>, ниво на батеријата <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"Поврзан со <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (без телефон), ниво на батеријата <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"Поврзан со <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (без аудиовизуелни содржини), ниво на батеријата <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"Поврзан со <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (без телефон и аудиовизуелни содржини), ниво на батеријата <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Аудио на медиуми"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"Телефонски повици"</string>
     <string name="bluetooth_profile_opp" msgid="9168139293654233697">"Пренос на датотека"</string>
@@ -75,6 +75,10 @@
     <string name="bluetooth_profile_sap" msgid="5764222021851283125">"Пристап до SIM"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD аудио: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD аудио"</string>
+    <!-- no translation found for bluetooth_profile_hearing_aid (7999237886427812595) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (7188282786730266159) -->
+    <skip />
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Поврзан со аудио на медиуми"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Поврзан со аудио на телефон"</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Поврзан со сервер за пренос на датотеки"</string>
@@ -91,6 +95,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Користи за аудио на телефон"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Користи за пренос на датотеки"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Користи за внес"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (908775281788309484) -->
+    <skip />
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Спари"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"СПАРИ"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Откажи"</string>
@@ -327,9 +333,10 @@
     <item msgid="8280754435979370728">"Природни бои како што со гледаат со голо око"</item>
     <item msgid="5363960654009010371">"Оптимизирани бои за дигитална содржина"</item>
   </string-array>
-    <string name="inactive_apps_title" msgid="1317817863508274533">"Неактивни апликации"</string>
+    <string name="inactive_apps_title" msgid="9042996804461901648">"Апликации во мирување"</string>
     <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"Неактивно. Допрете за да смените."</string>
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"Активно. Допрете за да смените."</string>
+    <string name="standby_bucket_summary" msgid="6567835350910684727">"Состојба на мирување на апликацијата: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <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 +358,24 @@
     <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>
+    <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Уште помалку од <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
+    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> - Уште помалку од <xliff:g id="THRESHOLD">%2$s</xliff:g>"</string>
+    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g>- Уште повеќе од <xliff:g id="TIME_REMAINING">%2$s</xliff:g>"</string>
+    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"Уште повеќе од <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"телефонот може да се исклучи наскоро"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"таблетот може да се исклучи наскоро"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"уредот може да се исклучи наскоро"</string>
+    <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>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> - телефонот може да се исклучи наскоро"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> - таблетот може да се исклучи наскоро"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> - уредот може да се исклучи наскоро"</string>
     <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 +429,8 @@
     <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>
+    <string name="zen_alarm_warning_indef" msgid="3007988140196673193">"Нема да се вклучи следниот аларм <xliff:g id="WHEN">%1$s</xliff:g> освен ако претходно не го исклучите ова"</string>
+    <string name="zen_alarm_warning" msgid="6236690803924413088">"Нема да се вклучи следниот аларм <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template" msgid="4996153414057676512">"во <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template_far" msgid="3779172822607461675">"во <xliff:g id="WHEN">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml
index 93407ec..c242701 100644
--- a/packages/SettingsLib/res/values-ml/strings.xml
+++ b/packages/SettingsLib/res/values-ml/strings.xml
@@ -53,16 +53,16 @@
     <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>
+    <string name="bluetooth_connected" msgid="5427152882755735944">"കണക്റ്റ് ചെയ്‌തു<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
     <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>
+    <string name="bluetooth_connected_no_headset" msgid="616068069034994802">"കണ‌ക്റ്റ് ചെ‌യ്‌തു (ഫോൺ ഇല്ല)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp" msgid="3736431800395923868">"കണക്റ്റ് ചെയ്‌തു (മീഡിയ ഇല്ല)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_map" msgid="3200033913678466453">"കണ‌ക്റ്റ് ചെയ്‌തു (സന്ദേശ ആക്‌സസ് ഇല്ല)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2047403011284187056">"കണ‌ക്റ്റ് ചെയ്‌തു (ഫോണോ മീഡിയയോ ഇല്ല)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_battery_level" msgid="5162924691231307748">"കണക്റ്റ് ചെയ്‌തു, ബാറ്ററി <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"കണ‌ക്റ്റ് ചെയ്‌തു (ഫോൺ ഇല്ല), ബാറ്ററി നില <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"കണക്റ്റ് ചെയ്‌തു (മീഡിയ ഇല്ല), ബാറ്ററി <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"കണ‌ക്റ്റ് ചെയ്‌തു (ഫോണോ മീഡിയയോ ഇല്ല), ബാറ്ററി നില <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"മീഡിയ ഓഡിയോ"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"ഫോണ്‍‌ കോളുകൾ"</string>
     <string name="bluetooth_profile_opp" msgid="9168139293654233697">"ഫയൽ കൈമാറൽ"</string>
@@ -75,6 +75,10 @@
     <string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM ആക്സസ്"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD ഓഡിയോ: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD ഓഡിയോ"</string>
+    <!-- no translation found for bluetooth_profile_hearing_aid (7999237886427812595) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (7188282786730266159) -->
+    <skip />
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"മീഡിയ ഓഡിയോയിലേക്ക് കണ‌ക്റ്റുചെയ്‌തു"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"ഫോൺ ഓഡിയോയിൽ കണ‌ക്റ്റുചെ‌യ്‌തു"</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"ഫയൽ കൈമാറ്റ സെർവറിലേക്ക് കണ‌ക്റ്റുചെ‌യ്‌തു"</string>
@@ -91,6 +95,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"ഫോൺ ഓഡിയോയ്ക്കായി ഉപയോഗിക്കുക"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"ഫയൽ കൈമാറ്റത്തിനായി ഉപയോഗിക്കുന്നു"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"ഇൻപുട്ടിനായി ഉപയോഗിക്കുക"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (908775281788309484) -->
+    <skip />
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"ജോടിയാക്കുക"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"ജോടിയാക്കുക"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"റദ്ദാക്കുക"</string>
@@ -327,9 +333,10 @@
     <item msgid="8280754435979370728">"നമ്മൾ കാണുന്നത് പോലെയുള്ള സ്വാഭാവിക വർണ്ണങ്ങൾ"</item>
     <item msgid="5363960654009010371">"ഡിജിറ്റൽ ഉള്ളടക്കത്തിനായി വർണ്ണങ്ങൾ ഒപ്റ്റിമൈസ് ചെയ്തു"</item>
   </string-array>
-    <string name="inactive_apps_title" msgid="1317817863508274533">"നിഷ്‌ക്രിയ ആപ്പുകൾ"</string>
+    <string name="inactive_apps_title" msgid="9042996804461901648">"സ്‌റ്റാൻഡ്‌ബൈ ആപ്പുകൾ"</string>
     <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"നിഷ്‌ക്രിയം. മാറ്റുന്നതിനു ടാപ്പുചെയ്യുക."</string>
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"സജീവം. മാറ്റുന്നതിന് ടാപ്പുചെയ്യുക."</string>
+    <string name="standby_bucket_summary" msgid="6567835350910684727">"ആപ്പ് സ്‌റ്റാൻഡ്‌ബൈ നില:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <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 +358,24 @@
     <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>
+    <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"<xliff:g id="THRESHOLD">%1$s</xliff:g>-ൽ കുറവ് സമയം ശേഷിക്കുന്നു"</string>
+    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="THRESHOLD">%2$s</xliff:g>-ൽ കുറവ് സമയം ശേഷിക്കുന്നു"</string>
+    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g><xliff:g id="TIME_REMAINING">%2$s</xliff:g>-ൽ കൂടുതൽ സമയം ശേഷിക്കുന്നു"</string>
+    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g>-ൽ കൂടുതൽ സമയം ശേഷിക്കുന്നു"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"ഫോൺ ഉടൻ ഷട്ട് ഡൗൺ ആയേക്കാം"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"ടാബ്‌ലെറ്റ് ഉടൻ ഷട്ട് ഡൗൺ ആയേക്കാം"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"ഉപകരണം ഉടൻ ഷട്ട്ഡൗൺ ആയേക്കാം"</string>
+    <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>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> - ഫോൺ ഉടൻ ഷട്ട് ഡൗൺ ആയേക്കാം"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> - ടാബ്‌ലെറ്റ് ഉടൻ ഷട്ട് ഡൗൺ ആയേക്കാം"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> - ഉപകരണം ഉടൻ ഷട്ട്ഡൗൺ ആയേക്കാം"</string>
     <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 +429,8 @@
     <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>
+    <string name="zen_alarm_warning_indef" msgid="3007988140196673193">"ഇത് ഓഫാക്കിയില്ലെങ്കിൽ <xliff:g id="WHEN">%1$s</xliff:g>-നുള്ള അടുത്ത അലാറം കേൾക്കില്ല"</string>
+    <string name="zen_alarm_warning" msgid="6236690803924413088">"<xliff:g id="WHEN">%1$s</xliff:g>-നുള്ള നിങ്ങളുടെ അടുത്ത അലാറം കേൾക്കില്ല"</string>
+    <string name="alarm_template" msgid="4996153414057676512">"<xliff:g id="WHEN">%1$s</xliff:g>-ന്"</string>
+    <string name="alarm_template_far" msgid="3779172822607461675">"<xliff:g id="WHEN">%1$s</xliff:g>-ന്"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-mn/arrays.xml b/packages/SettingsLib/res/values-mn/arrays.xml
index 73f4099..e0f5ac6 100644
--- a/packages/SettingsLib/res/values-mn/arrays.xml
+++ b/packages/SettingsLib/res/values-mn/arrays.xml
@@ -234,10 +234,6 @@
     <item msgid="7688197031296835369">"Давхар дүрслэлтэй хэсгийг харуулах"</item>
     <item msgid="2290859360633824369">"Өнгө үл ялгагчид зориулсан бүсүүдийг харуулах"</item>
   </string-array>
-  <string-array name="debug_hw_renderer_entries">
-    <item msgid="2578620445459945681">"OpenGL (Өгөгдмөл)"</item>
-    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
-  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"Стандарт хязгаар"</item>
     <item msgid="4071574792028999443">"Далд процесс байхгүй"</item>
diff --git a/packages/SettingsLib/res/values-mn/strings.xml b/packages/SettingsLib/res/values-mn/strings.xml
index 5652c8d..d4ee10d 100644
--- a/packages/SettingsLib/res/values-mn/strings.xml
+++ b/packages/SettingsLib/res/values-mn/strings.xml
@@ -53,16 +53,16 @@
     <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>
+    <string name="bluetooth_connected" msgid="5427152882755735944">"Холбогдсон<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
     <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>
+    <string name="bluetooth_connected_no_headset" msgid="616068069034994802">"Холбогдсон (утас байхгүй)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp" msgid="3736431800395923868">"Холбогдсон (медиа байхгүй)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_map" msgid="3200033913678466453">"Холбогдсон (зурвасын хандалт байхгүй)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2047403011284187056">"Холбогдсон (утас эсвэл медиа байхгүй)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_battery_level" msgid="5162924691231307748">"Холбогдсон, батерей <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"Холбогдсон (утас байхгүй), батерей <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"Холбогдсон (медиа байхгүй), батерей <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"Холбогдсон (утас эсвэл медиа байхгүй), батерей <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Медиа аудио"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"Утасны дуудлага"</string>
     <string name="bluetooth_profile_opp" msgid="9168139293654233697">"Файл дамжуулалт"</string>
@@ -75,6 +75,10 @@
     <string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM Хандалт"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD аудио: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD аудио"</string>
+    <!-- no translation found for bluetooth_profile_hearing_aid (7999237886427812595) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (7188282786730266159) -->
+    <skip />
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Медиа аудиод холбогдсон"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Утасны аудид холбогдсон"</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Файл дамжуулах серверт холбогдсон"</string>
@@ -91,6 +95,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Утасны аудиод ашиглах"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Файл дамжуулахад ашиглах"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Оруулахад ашиглах"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (908775281788309484) -->
+    <skip />
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Хослуулах"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"ХОСЛУУЛАХ"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Цуцлах"</string>
@@ -275,7 +281,6 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"Техник хангамжийн давхаргын шинэчлэлтүүдийг харуулах"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Техник хангамжууд шинэчлэх үед давхаргыг анивчуулах"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"GPU давхар дүрслэлийг дебаг хийх"</string>
-    <string name="debug_hw_renderer" msgid="7568529019431785816">"GPU Renderer-г тохируулах"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"HW давхаргыг идэвхгүйжүүлэх"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"Дэлгэц нийлүүлэхэд GPU-г байнга ашиглах"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"Өнгөний орчныг дууриах"</string>
@@ -328,9 +333,10 @@
     <item msgid="8280754435979370728">"Нүдээр харж болох байгалийн өнгө"</item>
     <item msgid="5363960654009010371">"Дижитал агуулгад зориулан тааруулсан өнгө"</item>
   </string-array>
-    <string name="inactive_apps_title" msgid="1317817863508274533">"Идэвхгүй апп-ууд"</string>
+    <string name="inactive_apps_title" msgid="9042996804461901648">"Зогсолтын горимын апп"</string>
     <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"Идэвхгүй байна. Унтраах/асаахын тулд дарна уу."</string>
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"Идэвхтэй байна. Унтраах/асаахын тулд дарна уу."</string>
+    <string name="standby_bucket_summary" msgid="6567835350910684727">"Апп зогсолтын горимын төлөв:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <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>
@@ -352,16 +358,24 @@
     <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>
+    <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"<xliff:g id="THRESHOLD">%1$s</xliff:g>-с бага хугацаа үлдсэн"</string>
+    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="THRESHOLD">%2$s</xliff:g>-с бага хугацаа үлдсэн"</string>
+    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g><xliff:g id="TIME_REMAINING">%2$s</xliff:g>-с их хугацаа үлдсэн"</string>
+    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g>-с их хугацаа үлдсэн"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"утас удахгүй унтарч болзошгүй"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"таблет удахгүй унтарч болзошгүй"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"төхөөрөмж удахгүй унтарч болзошгүй"</string>
+    <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>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> - утас удахгүй унтарч болзошгүй"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> - таблет удахгүй унтарч болзошгүй"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> - төхөөрөмж удахгүй унтарч болзошгүй"</string>
     <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>
@@ -409,4 +423,14 @@
     </plurals>
     <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"Их хугацаа."</string>
     <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"Бага хугацаа."</string>
+    <string name="zen_mode_enable_dialog_turn_on" msgid="8287824809739581837">"Асаах"</string>
+    <string name="cancel" msgid="6859253417269739139">"Цуцлах"</string>
+    <string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"Бүү саад бол горимыг асаах"</string>
+    <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>
+    <string name="zen_alarm_warning_indef" msgid="3007988140196673193">"Та сэрүүлгээ <xliff:g id="WHEN">%1$s</xliff:g>-с өмнө унтраагаагүй тохиолдолд дараагийн сэрүүлгээ тус хугацаанд сонсохгүй"</string>
+    <string name="zen_alarm_warning" msgid="6236690803924413088">"Та дараагийн сэрүүлгээ <xliff:g id="WHEN">%1$s</xliff:g>-д сонсохгүй"</string>
+    <string name="alarm_template" msgid="4996153414057676512">"<xliff:g id="WHEN">%1$s</xliff:g>-д"</string>
+    <string name="alarm_template_far" msgid="3779172822607461675">"<xliff:g id="WHEN">%1$s</xliff:g>-д"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml
index c1acfd0..7934e8d 100644
--- a/packages/SettingsLib/res/values-mr/strings.xml
+++ b/packages/SettingsLib/res/values-mr/strings.xml
@@ -53,16 +53,16 @@
     <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>
+    <string name="bluetooth_connected" msgid="5427152882755735944">"<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>कनेक्ट केले"</string>
     <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>
+    <string name="bluetooth_connected_no_headset" msgid="616068069034994802">"कनेक्ट केले (फोन नाही)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp" msgid="3736431800395923868">"कनेक्ट केले (मीडिया नाही)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_map" msgid="3200033913678466453">"कनेक्ट केले (संदेश अ‍ॅक्सेस नाही)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2047403011284187056">"कनेक्ट केले (फोन किंवा मीडिया नाही)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_battery_level" msgid="5162924691231307748">"कनेक्ट केले, बॅटरी <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"कनेक्ट केले (फोन नाही), बॅटरी <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"कनेक्ट केले (मीडिया नाही), बॅटरी <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"कनेक्ट केले (फोन किंवा मीडिया नाही), बॅटरी <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"मीडिया ऑडिओ"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"फोन कॉल"</string>
     <string name="bluetooth_profile_opp" msgid="9168139293654233697">"फाइल स्थानांतरण"</string>
@@ -75,6 +75,10 @@
     <string name="bluetooth_profile_sap" msgid="5764222021851283125">"सिम प्रवेश"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD ऑडिओ: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD ऑडिओ"</string>
+    <!-- no translation found for bluetooth_profile_hearing_aid (7999237886427812595) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (7188282786730266159) -->
+    <skip />
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"मीडिया ऑडिओवर कनेक्ट केले"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"फोन ऑडिओ वर कनेक्ट केले"</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"फाईल स्थानांतर सर्व्हरवर कनेक्ट केले"</string>
@@ -91,6 +95,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"फोन ऑडिओसाठी वापरा"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"फाईल स्थानांतरणासाठी वापरा"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"इनपुट साठी वापरा"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (908775281788309484) -->
+    <skip />
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"पेअर करा"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"पेअर करा"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"रद्द करा"</string>
@@ -99,7 +105,7 @@
     <string name="bluetooth_pairing_pin_error_message" msgid="8337234855188925274">"अयोग्य पिन किंवा पासकीमुळे <xliff:g id="DEVICE_NAME">%1$s</xliff:g> सह जोडू शकलो नाही."</string>
     <string name="bluetooth_pairing_device_down_error_message" msgid="7870998403045801381">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> शी संवाद प्रस्थापित करू शकत नाही."</string>
     <string name="bluetooth_pairing_rejected_error_message" msgid="1648157108520832454">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> द्वारे पेअरींग नाकारले."</string>
-    <string name="bluetooth_talkback_computer" msgid="4875089335641234463">"संगणक"</string>
+    <string name="bluetooth_talkback_computer" msgid="4875089335641234463">"कॉंप्युटर"</string>
     <string name="bluetooth_talkback_headset" msgid="5140152177885220949">"हेडसेट"</string>
     <string name="bluetooth_talkback_phone" msgid="4260255181240622896">"फोन"</string>
     <string name="bluetooth_talkback_imaging" msgid="551146170554589119">"इमेज"</string>
@@ -327,9 +333,10 @@
     <item msgid="8280754435979370728">"डोळ्यांनी पाहिले तसे नैसर्गिक रंग"</item>
     <item msgid="5363960654009010371">"डिजिटल सामग्रीसाठी ऑप्टिमाइझ केलेले रंग"</item>
   </string-array>
-    <string name="inactive_apps_title" msgid="1317817863508274533">"निष्क्रिय अ‍ॅप्स"</string>
+    <string name="inactive_apps_title" msgid="9042996804461901648">"स्टँडबाय अॅप्स"</string>
     <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"निष्क्रिय. टॉगल करण्यासाठी टॅप करा."</string>
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"सक्रिय. टॉगल करण्यासाठी टॅप करा."</string>
+    <string name="standby_bucket_summary" msgid="6567835350910684727">"अॅप स्टँडबाय स्थिती: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="runningservices_settings_title" msgid="8097287939865165213">"चालू सेवा"</string>
     <string name="runningservices_settings_summary" msgid="854608995821032748">"सध्या चालत असलेल्या सेवा पहा आणि नियंत्रित करा"</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"वेबदृश्य अंमलबजावणी"</string>
@@ -351,16 +358,24 @@
     <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>
+    <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"<xliff:g id="THRESHOLD">%1$s</xliff:g> पेक्षा कमी शिल्लक आहे"</string>
+    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="THRESHOLD">%2$s</xliff:g> पेक्षा कमी शिल्लक आहे"</string>
+    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g><xliff:g id="TIME_REMAINING">%2$s</xliff:g> पेक्षा जास्त शिल्लक आहे"</string>
+    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> पेक्षा जास्त शिल्लक आहे"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"फोन लवकरच बंद होऊ शकतो"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"टॅबलेट लवकरच बंद होऊ शकतो"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"डिव्हाइस लवकरच बंद होऊ शकते"</string>
+    <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>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> - फोन लवकरच बंद होऊ शकतो"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> - टॅबलेट लवकरच बंद होऊ शकतो"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> - डिव्हाइस लवकरच बंद होऊ शकते"</string>
     <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 +429,8 @@
     <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>
+    <string name="zen_alarm_warning_indef" msgid="3007988140196673193">"तुम्ही आधी हे बंद केल्याशिवाय पुढील <xliff:g id="WHEN">%1$s</xliff:g> वाजता होणारा अलार्म ऐकू शकणार नाही"</string>
+    <string name="zen_alarm_warning" msgid="6236690803924413088">"तुमचा पुढील <xliff:g id="WHEN">%1$s</xliff:g> वाजता होणारा अलार्म, तुम्ही ऐकू शकणार नाही"</string>
+    <string name="alarm_template" msgid="4996153414057676512">"<xliff:g id="WHEN">%1$s</xliff:g> वाजता"</string>
+    <string name="alarm_template_far" msgid="3779172822607461675">"<xliff:g id="WHEN">%1$s</xliff:g> रोजी"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ms/arrays.xml b/packages/SettingsLib/res/values-ms/arrays.xml
index 915814f..a804ea2 100644
--- a/packages/SettingsLib/res/values-ms/arrays.xml
+++ b/packages/SettingsLib/res/values-ms/arrays.xml
@@ -234,10 +234,6 @@
     <item msgid="7688197031296835369">"Tunjukkan kawasan lebih lukis"</item>
     <item msgid="2290859360633824369">"Tunjukkan kawasan untuk Deuteranomaly"</item>
   </string-array>
-  <string-array name="debug_hw_renderer_entries">
-    <item msgid="2578620445459945681">"OpenGL (Lalai)"</item>
-    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
-  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"Had standard"</item>
     <item msgid="4071574792028999443">"Tiada proses latar belakang"</item>
diff --git a/packages/SettingsLib/res/values-ms/strings.xml b/packages/SettingsLib/res/values-ms/strings.xml
index 713dc82..e1aa376 100644
--- a/packages/SettingsLib/res/values-ms/strings.xml
+++ b/packages/SettingsLib/res/values-ms/strings.xml
@@ -53,16 +53,16 @@
     <string name="bluetooth_disconnected" msgid="6557104142667339895">"Diputuskan sambungan"</string>
     <string name="bluetooth_disconnecting" msgid="8913264760027764974">"Memutuskan sambungan..."</string>
     <string name="bluetooth_connecting" msgid="8555009514614320497">"Menyambung..."</string>
-    <string name="bluetooth_connected" msgid="6038755206916626419">"Bersambung"</string>
+    <string name="bluetooth_connected" msgid="5427152882755735944">"<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> disambungkan"</string>
     <string name="bluetooth_pairing" msgid="1426882272690346242">"Memasangkan..."</string>
-    <string name="bluetooth_connected_no_headset" msgid="2866994875046035609">"Disambungkan (tiada telefon)"</string>
-    <string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Disambungkan (tiada media)"</string>
-    <string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Disambungkan (tiada akses mesej)"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Disambungkan (tiada telefon atau media)"</string>
-    <string name="bluetooth_connected_battery_level" msgid="7049181126136692368">"Disambungkan, bateri <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_headset_battery_level" msgid="5504193961248406027">"Disambungkan (tiada telefon), bateri <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="4751724026365870779">"Disambungkan (tiada media), bateri <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1549265779323455261">"Disambungkan (tiada telefon atau media), bateri <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset" msgid="616068069034994802">"Disambungkan (tiada telefon)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp" msgid="3736431800395923868">"Disambungkan (tiada media)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_map" msgid="3200033913678466453">"Disambungkan (tiada akses mesej)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2047403011284187056">"Disambungkan (tiada telefon atau media)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_battery_level" msgid="5162924691231307748">"Disambungkan, bateri <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"Disambungkan (tiada telefon), bateri <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"Disambungkan (tiada media), bateri <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"Disambungkan (tiada telefon atau media), bateri <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Audio media"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"Panggilan telefon"</string>
     <string name="bluetooth_profile_opp" msgid="9168139293654233697">"Pemindahan fail"</string>
@@ -75,6 +75,10 @@
     <string name="bluetooth_profile_sap" msgid="5764222021851283125">"Akses SIM"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"Audio HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"Audio HD"</string>
+    <!-- no translation found for bluetooth_profile_hearing_aid (7999237886427812595) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (7188282786730266159) -->
+    <skip />
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Disambungkan ke audio media"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Disambungkan ke audio telefon"</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Bersambung ke pelayan pemindahan fail"</string>
@@ -91,6 +95,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Gunakan untuk audio telefon"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Gunakan untuk pemindahan fail"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Gunakan untuk input"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (908775281788309484) -->
+    <skip />
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Jadikan pasangan"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"JADIKAN PASANGAN"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Batal"</string>
@@ -275,7 +281,6 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"Tunjukkan kemas kini perkakasan"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Denyar hijau lapisan perkakasan yang dikemas kini"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"Nyahpepijat lebih lukis GPU"</string>
-    <string name="debug_hw_renderer" msgid="7568529019431785816">"Tetapkan Pemapar GPU"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"Lumpuhkan tindihan HW"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"Sentiasa gunakan GPU untuk komposit skrin"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"Tiru ruang warna"</string>
@@ -328,9 +333,10 @@
     <item msgid="8280754435979370728">"Warna semula jadi seperti yang dilihat oleh mata"</item>
     <item msgid="5363960654009010371">"Warna dioptimumkan untuk kandungan digital"</item>
   </string-array>
-    <string name="inactive_apps_title" msgid="1317817863508274533">"Apl yang tidak aktif"</string>
+    <string name="inactive_apps_title" msgid="9042996804461901648">"Apl tunggu sedia"</string>
     <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"Tidak aktif. Ketik untuk menogol."</string>
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"Aktif. Ketik untuk menogol."</string>
+    <string name="standby_bucket_summary" msgid="6567835350910684727">"Keadaan tunggu sedia apl:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="runningservices_settings_title" msgid="8097287939865165213">"Perkhidmatan dijalankan"</string>
     <string name="runningservices_settings_summary" msgid="854608995821032748">"Lihat dan kawal perkhidmatan yang sedang dijalankan"</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"Pelaksanaan WebView"</string>
@@ -352,16 +358,24 @@
     <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Pembetulan warna"</string>
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Ciri ini adalah percubaan dan boleh menjejaskan prestasi."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Diatasi oleh <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only" msgid="845431008899029842">"Kira-kira <xliff:g id="TIME">^1</xliff:g> lagi"</string>
-    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Tinggal kira-kira <xliff:g id="TIME">^1</xliff:g> berdasarkan penggunaan anda"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">^1</xliff:g> lagi sehingga dicas penuh"</string>
-    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">^1</xliff:g> lagi"</string>
-    <string name="power_remaining_duration_only_short_enhanced" msgid="7450425624026394823">"Tinggal <xliff:g id="TIME">^1</xliff:g> berdasarkan penggunaan anda"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">^1</xliff:g> - kira-kira <xliff:g id="TIME">^2</xliff:g> lagi"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">^1</xliff:g> - tinggal kira-kira <xliff:g id="TIME">^2</xliff:g> berdasarkan penggunaan anda"</string>
-    <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g> lagi"</string>
+    <string name="power_remaining_duration_only" msgid="845431008899029842">"Kira-kira <xliff:g id="TIME">%1$s</xliff:g> lagi"</string>
+    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Tinggal kira-kira <xliff:g id="TIME">%1$s</xliff:g> berdasarkan penggunaan anda"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> lagi sehingga dicas penuh"</string>
+    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">%1$s</xliff:g> lagi"</string>
+    <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Tinggal kurang daripada <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
+    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> - Tinggal kurang daripada <xliff:g id="THRESHOLD">%2$s</xliff:g>"</string>
+    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g>tinggal lebih daripada <xliff:g id="TIME_REMAINING">%2$s</xliff:g>"</string>
+    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"tinggal lebih daripada <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"telefon mungkin ditutup tidak lama lagi"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"tablet mungkin ditutup tidak lama lagi"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"peranti mungkin ditutup tidak lama lagi"</string>
+    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> - kira-kira <xliff:g id="TIME">%2$s</xliff:g> lagi"</string>
+    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> - tinggal kira-kira <xliff:g id="TIME">%2$s</xliff:g> berdasarkan penggunaan anda"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> - telefon mungkin ditutup tidak lama lagi"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> - tablet mungkin ditutup tidak lama lagi"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> - peranti mungkin ditutup tidak lama lagi"</string>
     <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> sehingga dicas penuh"</string>
+    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> sehingga dicas penuh"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Tidak diketahui"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Mengecas"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"mengecas"</string>
@@ -409,4 +423,14 @@
     </plurals>
     <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"Lagi masa."</string>
     <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"Kurang masa."</string>
+    <string name="zen_mode_enable_dialog_turn_on" msgid="8287824809739581837">"Hidupkan"</string>
+    <string name="cancel" msgid="6859253417269739139">"Batal"</string>
+    <string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"Hidupkan Jangan Ganggu"</string>
+    <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"Jangan sekali-kali"</string>
+    <string name="zen_interruption_level_priority" msgid="2078370238113347720">"Keutamaan sahaja"</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>
+    <string name="zen_alarm_warning_indef" msgid="3007988140196673193">"Anda tidak akan mendengar penggera yang seterusnya <xliff:g id="WHEN">%1$s</xliff:g> melainkan anda mematikan ini sebelum waktu itu"</string>
+    <string name="zen_alarm_warning" msgid="6236690803924413088">"Anda tidak akan mendengar penggera yang seterusnya <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template" msgid="4996153414057676512">"pada <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template_far" msgid="3779172822607461675">"pada <xliff:g id="WHEN">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml
index 22ac322..4eb4044 100644
--- a/packages/SettingsLib/res/values-my/strings.xml
+++ b/packages/SettingsLib/res/values-my/strings.xml
@@ -53,16 +53,16 @@
     <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>
+    <string name="bluetooth_connected" msgid="5427152882755735944">"<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> ချိတ်ဆက်ပြီးပြီ"</string>
     <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>
+    <string name="bluetooth_connected_no_headset" msgid="616068069034994802">"ချိတ်ဆက်ပြီးပြီ (ဖုန်းမရှိပါ)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp" msgid="3736431800395923868">"ချိတ်ဆက်ပြီးပြီ (မီဒီယာ မရှိပါ)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_map" msgid="3200033913678466453">"ချိတ်ဆက်ပြီးပြီ (မက်ဆေ့ဂျ် သုံး၍မရပါ)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2047403011284187056">"ချိတ်ပြီးပြီ (ဖုန်း (သို့) မီဒီယာ မရှိပါ)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_battery_level" msgid="5162924691231307748">"ချိတ်ဆက်ပြီးပြီ၊ ဘက်ထရီ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"ချိတ်ဆက်ပြီးပြီ (ဖုန်းမရှိပါ)၊ ဘက်ထရီ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"ချိတ်ဆက်ပြီးပြီ (မီဒီယာ မရှိပါ)၊ ဘက်ထရီ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"ချိတ်ဆက်ပြီးပြီ (ဖုန်း (သို့) မီဒီယာ မရှိပါ)၊ ဘက်ထရီ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"မီဒီယာ အသံ"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"ဖုန်းခေါ်ဆိုမှုများ"</string>
     <string name="bluetooth_profile_opp" msgid="9168139293654233697">"ဖိုင်လွဲပြောင်းခြင်း"</string>
@@ -75,6 +75,10 @@
     <string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM အသုံးပြုခြင်း"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD အသံ- <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD အသံ"</string>
+    <!-- no translation found for bluetooth_profile_hearing_aid (7999237886427812595) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (7188282786730266159) -->
+    <skip />
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"မီဒီယာအသံအား ချိတ်ဆက်ရန်"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"ဖုန်းအသံအား ချိတ်ဆက်ရန်"</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"ဖိုင်လွှဲပြောင်းမည့်ဆာဗာနှင့် ချိတ်ဆက်ထားပြီး"</string>
@@ -91,6 +95,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"ဖုန်းအသံအားအသုံးပြုရန်"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"ဖိုင်လွဲပြောင်းရန်အတွက်အသုံးပြုရန်"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"ထည့်သွင်းရန်အသုံးပြုသည်"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (908775281788309484) -->
+    <skip />
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"အတူတွဲပါ"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"ချိတ်တွဲရန်"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"မလုပ်တော့"</string>
@@ -327,9 +333,10 @@
     <item msgid="8280754435979370728">"မျက်လုံးမှတွေ့ရသည့် သဘာဝအရောင်"</item>
     <item msgid="5363960654009010371">"ဒီဂျစ်တယ်အကြောင်းအရာအတွက် ပြင်ဆင်ထားသည့် အရောင်များ"</item>
   </string-array>
-    <string name="inactive_apps_title" msgid="1317817863508274533">"အလုပ်မလုပ်သော အက်ပ်များ"</string>
+    <string name="inactive_apps_title" msgid="9042996804461901648">"အရန်သင့်ထားရှိသော အက်ပ်များ"</string>
     <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"ပွင့်မနေပါ။ ပြောင်းရန်တို့ပါ။"</string>
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"ပွင့်နေသည်။ ပြောင်းရန်တို့ပါ။"</string>
+    <string name="standby_bucket_summary" msgid="6567835350910684727">"အက်ပ်ကို အရန်သင့်ထားရှိခြင်း အခြေအနေ-<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <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 +358,24 @@
     <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>
+    <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"<xliff:g id="THRESHOLD">%1$s</xliff:g> ခန့်သာ ကျန်တော့သည်"</string>
+    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="THRESHOLD">%2$s</xliff:g> ခန့်သာ ကျန်တော့သည်"</string>
+    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g><xliff:g id="TIME_REMAINING">%2$s</xliff:g> ကျော် ကျန်သေးသည်"</string>
+    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> ကျော် ကျန်သေးသည်"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"မကြာမီ ဖုန်းပိတ်သွားနိုင်သည်"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"မကြာမီ တက်ဘလက်ပိတ်သွားနိုင်သည်"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"မကြာမီ စက်ပိတ်သွားနိုင်သည်"</string>
+    <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>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> - မကြာမီ ဖုန်းပိတ်သွားနိင်သည်"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> - မကြာမီ တက်ဘလက်ပိတ်သွားနိင်သည်"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> - မကြာမီ စက်ပိတ်သွားနိင်သည်"</string>
     <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 +429,8 @@
     <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>
+    <string name="zen_alarm_warning_indef" msgid="3007988140196673193">"သင်၏ နောက်ထပ်နှိုးစက် <xliff:g id="WHEN">%1$s</xliff:g> မတိုင်မီ ၎င်းကိုမပိတ်လျှင် ကြားမည်မဟုတ်ပါ"</string>
+    <string name="zen_alarm_warning" msgid="6236690803924413088">"သင်၏ နောက်ထပ်နှိုးစက် <xliff:g id="WHEN">%1$s</xliff:g> ကို ကြားမည်မဟုတ်ပါ"</string>
+    <string name="alarm_template" msgid="4996153414057676512">"<xliff:g id="WHEN">%1$s</xliff:g> တွင်"</string>
+    <string name="alarm_template_far" msgid="3779172822607461675">"<xliff:g id="WHEN">%1$s</xliff:g> တွင်"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index 77ebdc7..f962316 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -53,16 +53,16 @@
     <string name="bluetooth_disconnected" msgid="6557104142667339895">"Frakoblet"</string>
     <string name="bluetooth_disconnecting" msgid="8913264760027764974">"Kobler fra…"</string>
     <string name="bluetooth_connecting" msgid="8555009514614320497">"Kobler til…"</string>
-    <string name="bluetooth_connected" msgid="6038755206916626419">"Tilkoblet"</string>
+    <string name="bluetooth_connected" msgid="5427152882755735944">"Koblet til <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
     <string name="bluetooth_pairing" msgid="1426882272690346242">"Sammenkobles …"</string>
-    <string name="bluetooth_connected_no_headset" msgid="2866994875046035609">"Tilkobling (ingen telefon)"</string>
-    <string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Tilkoblet (ingen medier)"</string>
-    <string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Tilkoblet (ingen meldingstilgang)"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Tilkoblet (ingen telefon eller media)"</string>
-    <string name="bluetooth_connected_battery_level" msgid="7049181126136692368">"Tilkoblet, batterinivå <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_headset_battery_level" msgid="5504193961248406027">"Tilkoblet (ingen telefon), batterinivå <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="4751724026365870779">"Tilkoblet (ingen medier), batterinivå <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1549265779323455261">"Tilkoblet (ingen telefon eller medier), batterinivå <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset" msgid="616068069034994802">"Koblet til (ingen telefon) <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp" msgid="3736431800395923868">"Koblet til (ingen medier) <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_map" msgid="3200033913678466453">"Koblet til (ingen meldingstilgang) <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2047403011284187056">"Koblet til (ingen telefon eller medier) <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_battery_level" msgid="5162924691231307748">"Koblet til, batteri <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"Koblet til (ingen telefon), batteri <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"Koblet til (ingen medier), batteri <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"Koblet til (ingen telefon eller medier), batteri <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Medielyd"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"Telefonsamtaler"</string>
     <string name="bluetooth_profile_opp" msgid="9168139293654233697">"Filoverføring"</string>
@@ -75,6 +75,10 @@
     <string name="bluetooth_profile_sap" msgid="5764222021851283125">"Tilgang til SIM-kortet"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD-lyd: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD-lyd"</string>
+    <!-- no translation found for bluetooth_profile_hearing_aid (7999237886427812595) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (7188282786730266159) -->
+    <skip />
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Koblet til medielyd"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Koblet til telefonlyd"</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Koblet til tjener for filoverføring"</string>
@@ -91,6 +95,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Bruk for telefonlyd"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Bruk til filoverføring"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Bruk for inndata"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (908775281788309484) -->
+    <skip />
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Sammenkoble"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"KOBLE TIL"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Avbryt"</string>
@@ -327,9 +333,10 @@
     <item msgid="8280754435979370728">"Naturlige farger – som øyet ser dem"</item>
     <item msgid="5363960654009010371">"Farger som er optimalisert for digitalt innhold"</item>
   </string-array>
-    <string name="inactive_apps_title" msgid="1317817863508274533">"Inaktive apper"</string>
+    <string name="inactive_apps_title" msgid="9042996804461901648">"Apper i ventemodus"</string>
     <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"Ikke aktiv. Trykk for å slå av/på."</string>
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"Aktiv. Trykk for å slå av/på."</string>
+    <string name="standby_bucket_summary" msgid="6567835350910684727">"Hvilemodus:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="runningservices_settings_title" msgid="8097287939865165213">"Aktive tjenester"</string>
     <string name="runningservices_settings_summary" msgid="854608995821032748">"Se og kontrollér tjenester som kjører for øyeblikket"</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView-implementering"</string>
@@ -351,16 +358,24 @@
     <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Fargekorrigering"</string>
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Dette er en eksperimentell funksjon som kan gjøre at telefonen ikke fungerer optimalt."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Overstyres av <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only" msgid="845431008899029842">"Omtrent <xliff:g id="TIME">^1</xliff:g> gjenstår"</string>
-    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Omtrent <xliff:g id="TIME">^1</xliff:g> igjen basert på bruken din"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">^1</xliff:g> til det er fulladet"</string>
-    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">^1</xliff:g> gjenstår"</string>
-    <string name="power_remaining_duration_only_short_enhanced" msgid="7450425624026394823">"<xliff:g id="TIME">^1</xliff:g> igjen basert på bruken din"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">^1</xliff:g> – omtrent <xliff:g id="TIME">^2</xliff:g> gjenstår"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">^1</xliff:g> – omtrent <xliff:g id="TIME">^2</xliff:g> igjen basert på bruken din"</string>
-    <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> – <xliff:g id="TIME">^2</xliff:g> gjenstår"</string>
+    <string name="power_remaining_duration_only" msgid="845431008899029842">"Omtrent <xliff:g id="TIME">%1$s</xliff:g> gjenstår"</string>
+    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Omtrent <xliff:g id="TIME">%1$s</xliff:g> igjen basert på bruken din"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> til det er fulladet"</string>
+    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">%1$s</xliff:g> gjenstår"</string>
+    <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Mindre enn <xliff:g id="THRESHOLD">%1$s</xliff:g> gjenstår"</string>
+    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> – mindre enn <xliff:g id="THRESHOLD">%2$s</xliff:g> gjenstår"</string>
+    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g> mindre enn <xliff:g id="TIME_REMAINING">%2$s</xliff:g> gjenstår"</string>
+    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"mer enn <xliff:g id="TIME_REMAINING">%1$s</xliff:g> gjenstår"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"telefonen slås kanskje av snart"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"nettbrettet slås kanskje av snart"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"enheten slås kanskje av snart"</string>
+    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> – omtrent <xliff:g id="TIME">%2$s</xliff:g> gjenstår"</string>
+    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> – omtrent <xliff:g id="TIME">%2$s</xliff:g> igjen basert på bruken din"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> – telefonen slås kanskje av snart"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> – nettbrettet slås kanskje av snart"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> – enheten slås kanskje av snart"</string>
     <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> til det er fulladet"</string>
+    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> til det er fulladet"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Ukjent"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Lader"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"lader"</string>
@@ -414,4 +429,8 @@
     <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"Aldri"</string>
     <string name="zen_interruption_level_priority" msgid="2078370238113347720">"Bare prioritet"</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>
+    <string name="zen_alarm_warning_indef" msgid="3007988140196673193">"Du hører ikke neste innstilte alarm <xliff:g id="WHEN">%1$s</xliff:g>, med mindre du slår av dette først"</string>
+    <string name="zen_alarm_warning" msgid="6236690803924413088">"Du hører ikke neste innstilte alarm <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template" msgid="4996153414057676512">"kl. <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template_far" msgid="3779172822607461675">"<xliff:g id="WHEN">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml
index 9aeb083..0cac05e 100644
--- a/packages/SettingsLib/res/values-ne/strings.xml
+++ b/packages/SettingsLib/res/values-ne/strings.xml
@@ -53,16 +53,16 @@
     <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>
+    <string name="bluetooth_connected" msgid="5427152882755735944">"<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> सँग जडान गरियो"</string>
     <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>
+    <string name="bluetooth_connected_no_headset" msgid="616068069034994802">"जडान गरियो (फोनबाहेेक) <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp" msgid="3736431800395923868">"जडान गरियो (मिडियाबाहेक) <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_map" msgid="3200033913678466453">"जडान गरियो (सन्देशमाथि पहुँच छैन) <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2047403011284187056">"जडान गरियो (फोन वा मिडियाबाहेक) <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_battery_level" msgid="5162924691231307748">"जडान गरियो, ब्याट्री <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"जडान गरियो (फोनबाहेेक), ब्याट्री <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"जडान गरियो (मिडियाबाहेक), ब्याट्री <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"जडान गरियो (फोन वा मिडियाबाहेक), ब्याट्री <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"मिडिया अडियो"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"फोन कलहरू"</string>
     <string name="bluetooth_profile_opp" msgid="9168139293654233697">"फाइल स्थानान्तरण"</string>
@@ -75,6 +75,10 @@
     <string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM पहुँच"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD अडियो: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD अडियो"</string>
+    <!-- no translation found for bluetooth_profile_hearing_aid (7999237886427812595) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (7188282786730266159) -->
+    <skip />
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"मिडिया अडियोसँग जडित"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"फोन अडियोमा जडान गरियो"</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"फाइल ट्रान्सफर सर्भरमा जडान गरियो"</string>
@@ -91,6 +95,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"फोन अडियोको लागि प्रयोग गर्नुहोस्"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"फाइल ट्रान्सफरका लागि प्रयोग गर्नुहोस्"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"इनपुटको लागि प्रयोग गर्नुहोस्"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (908775281788309484) -->
+    <skip />
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"जोडी"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"जोडी"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"रद्द गर्नुहोस्"</string>
@@ -327,9 +333,10 @@
     <item msgid="8280754435979370728">"आँखाले देख्ने प्राकृतिक रङ्गहरू"</item>
     <item msgid="5363960654009010371">"डिजिटल सामग्रीको लागि अनुकूलित रङ्गहरु"</item>
   </string-array>
-    <string name="inactive_apps_title" msgid="1317817863508274533">"निष्क्रिय अनुप्रयोगहरू"</string>
+    <string name="inactive_apps_title" msgid="9042996804461901648">"स्ट्यान्डबाई अनुप्रयोगहरू"</string>
     <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"निष्क्रिय। टगल गर्न ट्याप गर्नुहोस्।"</string>
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"सक्रिय। टगल गर्न ट्याप गर्नुहोस्।"</string>
+    <string name="standby_bucket_summary" msgid="6567835350910684727">"अनुप्रयोगको स्ट्यान्डबाई अवस्था:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <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 +358,24 @@
     <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>
+    <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"<xliff:g id="THRESHOLD">%1$s</xliff:g> भन्दा कम समय बाँकी छ"</string>
+    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="THRESHOLD">%2$s</xliff:g> भन्दा कम समय बाँकी छ"</string>
+    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g> <xliff:g id="TIME_REMAINING">%2$s</xliff:g> भन्दा बढी समय बाँकी छ"</string>
+    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> भन्दा बढी समय बाँकी छ"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"फोन चाँडै बन्द हुन सक्छ"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"ट्याब्लेट चाँडै बन्द हुन सक्छ"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"यन्त्र चाँडै बन्द हुन सक्छ"</string>
+    <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>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> - फोन चाँडै बन्द हुन सक्छ"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> - ट्याब्लेट चाँडै बन्द हुन सक्छ"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> - यन्त्र चाँडै बन्द हुन सक्छ"</string>
     <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 +429,8 @@
     <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>
+    <string name="zen_alarm_warning_indef" msgid="3007988140196673193">"तपाईंले <xliff:g id="WHEN">%1$s</xliff:g> मा बज्ने अर्को अलार्मको समयअघि नै यसलाई निष्क्रिय पार्नुभएन भने तपाईं उक्त अलार्म सुन्नु हुने छैन"</string>
+    <string name="zen_alarm_warning" msgid="6236690803924413088">"तपाईं <xliff:g id="WHEN">%1$s</xliff:g> मा बज्ने आफ्नो अर्को अलार्म सुन्नु हुने छैन"</string>
+    <string name="alarm_template" msgid="4996153414057676512">"<xliff:g id="WHEN">%1$s</xliff:g> मा"</string>
+    <string name="alarm_template_far" msgid="3779172822607461675">"<xliff:g id="WHEN">%1$s</xliff:g> मा"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml
index c1ea14e..7a92f02 100644
--- a/packages/SettingsLib/res/values-nl/strings.xml
+++ b/packages/SettingsLib/res/values-nl/strings.xml
@@ -53,16 +53,16 @@
     <string name="bluetooth_disconnected" msgid="6557104142667339895">"Verbinding verbroken"</string>
     <string name="bluetooth_disconnecting" msgid="8913264760027764974">"Verbinding verbreken..."</string>
     <string name="bluetooth_connecting" msgid="8555009514614320497">"Verbinding maken..."</string>
-    <string name="bluetooth_connected" msgid="6038755206916626419">"Verbonden"</string>
+    <string name="bluetooth_connected" msgid="5427152882755735944">"Verbonden: <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
     <string name="bluetooth_pairing" msgid="1426882272690346242">"Koppelen..."</string>
-    <string name="bluetooth_connected_no_headset" msgid="2866994875046035609">"Gekoppeld (geen telefoon)"</string>
-    <string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Gekoppeld (geen media)"</string>
-    <string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Verbonden (geen toegang tot berichten)"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Gekoppeld (geen telefoon of media)"</string>
-    <string name="bluetooth_connected_battery_level" msgid="7049181126136692368">"Verbonden, batterij <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_headset_battery_level" msgid="5504193961248406027">"Verbonden (geen telefoon), batterij <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="4751724026365870779">"Verbonden (geen media), batterij <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1549265779323455261">"Verbonden (geen telefoon of media), batterij <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset" msgid="616068069034994802">"Verbonden: <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> (geen telefoon)"</string>
+    <string name="bluetooth_connected_no_a2dp" msgid="3736431800395923868">"Verbonden: <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> (geen media)"</string>
+    <string name="bluetooth_connected_no_map" msgid="3200033913678466453">"Verbonden: <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> (geen berichtentoegang)"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2047403011284187056">"Verbonden: <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> (geen telefoon of media)"</string>
+    <string name="bluetooth_connected_battery_level" msgid="5162924691231307748">"Verbonden: <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>, batterij: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"Verbonden: <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (geen telefoon), batterij: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"Verbonden: <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (geen media), batterij: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"Verbonden: <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (geen telefoon of media), batterij: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Media-audio"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"Telefoongesprekken"</string>
     <string name="bluetooth_profile_opp" msgid="9168139293654233697">"Bestandsoverdracht"</string>
@@ -75,6 +75,10 @@
     <string name="bluetooth_profile_sap" msgid="5764222021851283125">"Sim-toegang"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD-audio: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD-audio"</string>
+    <!-- no translation found for bluetooth_profile_hearing_aid (7999237886427812595) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (7188282786730266159) -->
+    <skip />
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Verbonden met audio van medium"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Verbonden met audio van telefoon"</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Verbonden met server voor bestandsoverdracht"</string>
@@ -91,6 +95,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Gebruiken voor audio van telefoon"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Gebruiken voor bestandsoverdracht"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Gebruiken voor invoer"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (908775281788309484) -->
+    <skip />
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Koppelen"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"KOPPELEN"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Annuleren"</string>
@@ -327,9 +333,10 @@
     <item msgid="8280754435979370728">"Natuurlijke kleuren zoals gezien door het menselijk oog"</item>
     <item msgid="5363960654009010371">"Kleuren geoptimaliseerd voor digitale content"</item>
   </string-array>
-    <string name="inactive_apps_title" msgid="1317817863508274533">"Inactieve apps"</string>
+    <string name="inactive_apps_title" msgid="9042996804461901648">"Stand-by-apps"</string>
     <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"Inactief. Tik om te schakelen."</string>
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"Actief. Tik om te schakelen."</string>
+    <string name="standby_bucket_summary" msgid="6567835350910684727">"Stand-bystatus app: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="runningservices_settings_title" msgid="8097287939865165213">"Actieve services"</string>
     <string name="runningservices_settings_summary" msgid="854608995821032748">"Services die momenteel actief zijn, weergeven en beheren"</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView-implementatie"</string>
@@ -351,16 +358,24 @@
     <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Kleurcorrectie"</string>
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Deze functie is experimenteel en kan invloed hebben op de prestaties."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Overschreven door <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only" msgid="845431008899029842">"Nog ongeveer <xliff:g id="TIME">^1</xliff:g>"</string>
-    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Nog ongeveer <xliff:g id="TIME">^1</xliff:g> over op basis van je gebruik"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Nog <xliff:g id="TIME">^1</xliff:g> tot volledig opgeladen"</string>
-    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">^1</xliff:g> resterend"</string>
-    <string name="power_remaining_duration_only_short_enhanced" msgid="7450425624026394823">"Nog <xliff:g id="TIME">^1</xliff:g> over op basis van je gebruik"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">^1</xliff:g> - ongeveer <xliff:g id="TIME">^2</xliff:g> resterend"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">^1</xliff:g>: nog ongeveer <xliff:g id="TIME">^2</xliff:g> over op basis van je gebruik"</string>
-    <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g> resterend"</string>
+    <string name="power_remaining_duration_only" msgid="845431008899029842">"Nog ongeveer <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Nog ongeveer <xliff:g id="TIME">%1$s</xliff:g> over op basis van je gebruik"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Nog <xliff:g id="TIME">%1$s</xliff:g> tot volledig opgeladen"</string>
+    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">%1$s</xliff:g> resterend"</string>
+    <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Minder dan <xliff:g id="THRESHOLD">%1$s</xliff:g> resterend"</string>
+    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> - Minder dan <xliff:g id="THRESHOLD">%2$s</xliff:g> resterend"</string>
+    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g> - meer dan <xliff:g id="TIME_REMAINING">%2$s</xliff:g> resterend"</string>
+    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"meer dan <xliff:g id="TIME_REMAINING">%1$s</xliff:g> resterend"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"telefoon wordt binnenkort mogelijk uitgeschakeld"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"tablet wordt binnenkort mogelijk uitgeschakeld"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"apparaat wordt binnenkort mogelijk uitgeschakeld"</string>
+    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> - ongeveer <xliff:g id="TIME">%2$s</xliff:g> resterend"</string>
+    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g>: nog ongeveer <xliff:g id="TIME">%2$s</xliff:g> over op basis van je gebruik"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> - telefoon wordt binnenkort mogelijk uitgeschakeld"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> - tablet wordt binnenkort mogelijk uitgeschakeld"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> - apparaat wordt binnenkort mogelijk uitgeschakeld"</string>
     <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> tot volledig opgeladen"</string>
+    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> tot volledig opgeladen"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Onbekend"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Opladen"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"opladen"</string>
@@ -414,4 +429,8 @@
     <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"Nooit"</string>
     <string name="zen_interruption_level_priority" msgid="2078370238113347720">"Alleen prioriteit"</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>
+    <string name="zen_alarm_warning_indef" msgid="3007988140196673193">"Je hoort je volgende wekker niet <xliff:g id="WHEN">%1$s</xliff:g> tenzij je dit vóór die tijd uitschakelt"</string>
+    <string name="zen_alarm_warning" msgid="6236690803924413088">"Je hoort je volgende wekker niet <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template" msgid="4996153414057676512">"om <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template_far" msgid="3779172822607461675">"op <xliff:g id="WHEN">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml
index 863b17c..bfea9a8 100644
--- a/packages/SettingsLib/res/values-pa/strings.xml
+++ b/packages/SettingsLib/res/values-pa/strings.xml
@@ -53,16 +53,16 @@
     <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>
+    <string name="bluetooth_connected" msgid="5427152882755735944">"ਕਨੈਕਟ ਕੀਤਾ ਹੋਇਆ<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
     <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>
+    <string name="bluetooth_connected_no_headset" msgid="616068069034994802">"ਕਨੈਕਟ ਕੀਤਾ ਹੋਇਆ (ਕੋਈ ਫ਼ੋਨ ਨਹੀਂ)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp" msgid="3736431800395923868">"ਕਨੈਕਟ ਕੀਤਾ ਹੋਇਆ (ਕੋਈ ਮੀਡੀਆ ਨਹੀਂ)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_map" msgid="3200033913678466453">"ਕਨੈਕਟ ਕੀਤਾ ਹੋਇਆ (ਸੁਨੇਹੇ \'ਤੇ ਪਹੁੰਚ ਨਹੀਂ)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2047403011284187056">"ਕਨੈਕਟ ਕੀਤਾ ਹੋਇਆ (ਕੋਈ ਫ਼ੋਨ ਜਾਂ ਮੀਡੀਆ ਨਹੀਂ)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_battery_level" msgid="5162924691231307748">"ਕਨੈਕਟ ਕੀਤਾ ਹੋਇਆ, ਬੈਟਰੀ ਦਾ ਪੱਧਰ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"ਕਨੈਕਟ ਕੀਤਾ ਹੋਇਆ (ਕੋਈ ਫ਼ੋਨ ਨਹੀਂ), ਬੈਟਰੀ ਦਾ ਪੱਧਰ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"ਕਨੈਕਟ ਕੀਤਾ ਹੋਇਆ (ਕੋਈ ਮੀਡੀਆ ਨਹੀਂ), ਬੈਟਰੀ ਦਾ ਪੱਧਰ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"ਕਨੈਕਟ ਕੀਤਾ ਹੋਇਆ (ਕੋਈ ਫ਼ੋਨ ਜਾਂ ਮੀਡੀਆ ਨਹੀਂ), ਬੈਟਰੀ ਦਾ ਪੱਧਰ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"ਮੀਡੀਆ  ਆਡੀਓ"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"ਫ਼ੋਨ ਕਾਲਾਂ"</string>
     <string name="bluetooth_profile_opp" msgid="9168139293654233697">"ਫਾਈਲ ਟ੍ਰਾਂਸਫਰ"</string>
@@ -75,6 +75,10 @@
     <string name="bluetooth_profile_sap" msgid="5764222021851283125">"ਸਿਮ ਪਹੁੰਚ"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD ਆਡੀਓ: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD ਆਡੀਓ"</string>
+    <!-- no translation found for bluetooth_profile_hearing_aid (7999237886427812595) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (7188282786730266159) -->
+    <skip />
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"ਮੀਡੀਆ  ਆਡੀਓ  ਨਾਲ ਕਨੈਕਟ ਕੀਤਾ"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"ਫ਼ੋਨ ਔਡੀਓ ਨਾਲ ਕਨੈਕਟ ਕੀਤਾ"</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"ਫਾਈਲ ਟ੍ਰਾਂਸਫ਼ਰ ਸਰਵਰ ਨਾਲ ਕਨੈਕਟ ਕੀਤਾ"</string>
@@ -91,6 +95,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"ਫ਼ੋਨ ਔਡੀਓ ਲਈ ਵਰਤੋ"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"ਫਾਈਲ ਟ੍ਰਾਂਸਫਰ ਲਈ ਵਰਤੋ"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"ਇਨਪੁਟ ਲਈ ਵਰਤੋ"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (908775281788309484) -->
+    <skip />
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"ਪੇਅਰ ਕਰੋ"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"ਪੇਅਰ ਕਰੋ"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"ਰੱਦ ਕਰੋ"</string>
@@ -327,9 +333,10 @@
     <item msgid="8280754435979370728">"ਕੁਦਰਤੀ ਰੰਗ ਜਿਵੇਂ ਅੱਖ ਰਾਹੀਂ ਦੇਖੇ ਜਾਂਦੇ ਹਨ"</item>
     <item msgid="5363960654009010371">"ਡਿਜੀਟਲ ਸਮੱਗਰੀ ਲਈ ਰੰਗ ਅਨੁਕੂਲ ਕੀਤੇ"</item>
   </string-array>
-    <string name="inactive_apps_title" msgid="1317817863508274533">"ਕਿਰਿਆਸ਼ੀਲ ਐਪਸ"</string>
+    <string name="inactive_apps_title" msgid="9042996804461901648">"ਸਟੈਂਡਬਾਏ ਐਪਾਂ"</string>
     <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"ਅਕਿਰਿਆਸ਼ੀਲ। ਟੌਗਲ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ।"</string>
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"ਕਿਰਿਆਸ਼ੀਲ। ਟੌਗਲ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ।"</string>
+    <string name="standby_bucket_summary" msgid="6567835350910684727">"ਐਪ ਸਟੈਂਡਬਾਈ ਸਥਿਤੀ:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <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 +358,24 @@
     <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>
+    <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"<xliff:g id="THRESHOLD">%1$s</xliff:g> ਤੋਂ ਘੱਟ ਸਮਾਂ ਬਾਕੀ"</string>
+    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="THRESHOLD">%2$s</xliff:g> ਤੋਂ ਘੱਟ ਸਮਾਂ ਬਾਕੀ"</string>
+    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g><xliff:g id="TIME_REMAINING">%2$s</xliff:g> ਤੋਂ ਵੱਧ ਸਮਾਂ ਬਾਕੀ"</string>
+    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> ਤੋਂ ਵੱਧ ਸਮਾਂ ਬਾਕੀ"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"ਫ਼ੋਨ ਛੇਤੀ ਹੀ ਬੰਦ ਹੋ ਸਕਦਾ ਹੈ"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"ਟੈਬਲੈੱਟ ਛੇਤੀ ਹੀ ਬੰਦ ਹੋ ਸਕਦਾ ਹੈ"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"ਡੀਵਾਈਸ ਛੇਤੀ ਹੀ ਬੰਦ ਹੋ ਸਕਦਾ ਹੈ"</string>
+    <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>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> - ਫ਼ੋਨ ਛੇਤੀ ਹੀ ਬੰਦ ਹੋ ਸਕਦਾ ਹੈ"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> - ਟੈਬਲੈੱਟ ਛੇਤੀ ਹੀ ਬੰਦ ਹੋ ਸਕਦਾ ਹੈ"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> - ਡੀਵਾਈਸ ਛੇਤੀ ਹੀ ਬੰਦ ਹੋ ਸਕਦਾ ਹੈ"</string>
     <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 +429,8 @@
     <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>
+    <string name="zen_alarm_warning_indef" msgid="3007988140196673193">"ਤੁਸੀਂ <xliff:g id="WHEN">%1$s</xliff:g> ਵਜੇ ਆਪਣਾ ਅਗਲਾ ਅਲਾਰਮ ਨਹੀਂ ਸੁਣੋਗੇ ਜੇਕਰ ਤੁਸੀਂ ਉਸ ਤੋਂ ਪਹਿਲਾਂ ਤੁਸੀਂ ਇਸ ਮੋਡ ਨੂੰ ਬੰਦ ਨਹੀਂ ਕਰਦੇ"</string>
+    <string name="zen_alarm_warning" msgid="6236690803924413088">"ਤੁਸੀਂ <xliff:g id="WHEN">%1$s</xliff:g> ਵਜੇ ਆਪਣਾ ਅਗਲਾ ਅਲਾਰਮ ਨਹੀਂ ਸੁਣੋਗੇ"</string>
+    <string name="alarm_template" msgid="4996153414057676512">"<xliff:g id="WHEN">%1$s</xliff:g> ਵਜੇ"</string>
+    <string name="alarm_template_far" msgid="3779172822607461675">"<xliff:g id="WHEN">%1$s</xliff:g> ਵਜੇ"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index a363ee2..75c336a 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -53,16 +53,16 @@
     <string name="bluetooth_disconnected" msgid="6557104142667339895">"Rozłączona"</string>
     <string name="bluetooth_disconnecting" msgid="8913264760027764974">"Rozłączanie..."</string>
     <string name="bluetooth_connecting" msgid="8555009514614320497">"Łączenie..."</string>
-    <string name="bluetooth_connected" msgid="6038755206916626419">"Połączony"</string>
+    <string name="bluetooth_connected" msgid="5427152882755735944">"Połączono – <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
     <string name="bluetooth_pairing" msgid="1426882272690346242">"Parowanie..."</string>
-    <string name="bluetooth_connected_no_headset" msgid="2866994875046035609">"Połączono (bez telefonu)"</string>
-    <string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Połączono (bez multimediów)"</string>
-    <string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Połączono (brak dostępu do wiadomości)"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Połączono (bez telefonu ani multimediów)"</string>
-    <string name="bluetooth_connected_battery_level" msgid="7049181126136692368">"Połączono, bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_headset_battery_level" msgid="5504193961248406027">"Połączono (bez telefonu), bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="4751724026365870779">"Połączono (bez multimediów), bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1549265779323455261">"Połączono (bez telefonu i multimediów), bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset" msgid="616068069034994802">"Połączono (bez telefonu) – <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp" msgid="3736431800395923868">"Połączono (bez multimediów) – <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_map" msgid="3200033913678466453">"Połączono (bez dostępu do wiadomości) – <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2047403011284187056">"Połączono (bez telefonu i multimediów) – <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_battery_level" msgid="5162924691231307748">"Połączono, bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> – <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"Połączono (bez telefonu), bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> – <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"Połączono (bez multimediów), bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> – <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"Połączono (bez telefonu i multimediów), bateria <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> – <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Dźwięk multimediów"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"Połączenia telefoniczne"</string>
     <string name="bluetooth_profile_opp" msgid="9168139293654233697">"Przesyłanie pliku"</string>
@@ -75,6 +75,10 @@
     <string name="bluetooth_profile_sap" msgid="5764222021851283125">"Dostęp do karty SIM"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"Dźwięk HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"Dźwięk HD"</string>
+    <!-- no translation found for bluetooth_profile_hearing_aid (7999237886427812595) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (7188282786730266159) -->
+    <skip />
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Połączono z funkcją audio multimediów"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Połączono z funkcją audio telefonu"</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Połączono z serwerem transferu plików"</string>
@@ -91,6 +95,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Użyj dla funkcji audio telefonu"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Użyj do transferu plików"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Użyj do wprowadzania"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (908775281788309484) -->
+    <skip />
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Sparuj"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"SPARUJ"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Anuluj"</string>
@@ -327,9 +333,10 @@
     <item msgid="8280754435979370728">"Naturalne kolory widziane przez ludzkie oko"</item>
     <item msgid="5363960654009010371">"Kolory dostosowane do wyświetlania treści cyfrowych"</item>
   </string-array>
-    <string name="inactive_apps_title" msgid="1317817863508274533">"Nieaktywne aplikacje"</string>
+    <string name="inactive_apps_title" msgid="9042996804461901648">"Aplikacje w trybie czuwania"</string>
     <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"Nieaktywna. Dotknij, by zmienić."</string>
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"Aktywna. Dotknij, by zmienić."</string>
+    <string name="standby_bucket_summary" msgid="6567835350910684727">"Stan aplikacji w trybie czuwania: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="runningservices_settings_title" msgid="8097287939865165213">"Uruchomione usługi"</string>
     <string name="runningservices_settings_summary" msgid="854608995821032748">"Wyświetl obecnie uruchomione usługi i zarządzaj nimi"</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"Implementacja WebView"</string>
@@ -351,16 +358,24 @@
     <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Korekcja kolorów"</string>
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"To jest funkcja eksperymentalna i może wpływać na działanie urządzenia."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Nadpisana przez <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only" msgid="845431008899029842">"Pozostało: <xliff:g id="TIME">^1</xliff:g>"</string>
-    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Jeszcze około <xliff:g id="TIME">^1</xliff:g> (na podstawie Twojego sposobu korzystania)"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">^1</xliff:g> do pełnego naładowania"</string>
-    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Zostało <xliff:g id="TIME">^1</xliff:g>"</string>
-    <string name="power_remaining_duration_only_short_enhanced" msgid="7450425624026394823">"Jeszcze <xliff:g id="TIME">^1</xliff:g> (na podstawie Twojego sposobu korzystania)"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">^1</xliff:g> – pozostało około <xliff:g id="TIME">^2</xliff:g>"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">^1</xliff:g> – jeszcze około <xliff:g id="TIME">^2</xliff:g> (na podstawie Twojego sposobu korzystania)"</string>
-    <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> – zostało <xliff:g id="TIME">^2</xliff:g>"</string>
+    <string name="power_remaining_duration_only" msgid="845431008899029842">"Pozostało: <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Jeszcze około <xliff:g id="TIME">%1$s</xliff:g> (na podstawie Twojego sposobu korzystania)"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> do pełnego naładowania"</string>
+    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Zostało <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Pozostało mniej niż <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
+    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> – pozostało mniej niż <xliff:g id="THRESHOLD">%2$s</xliff:g>"</string>
+    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g> – pozostało ponad <xliff:g id="TIME_REMAINING">%2$s</xliff:g>"</string>
+    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"pozostało ponad <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"telefon może się wkrótce wyłączyć"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"tablet może się wkrótce wyłączyć"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"urządzenie może się wkrótce wyłączyć"</string>
+    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> – pozostało około <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> – jeszcze około <xliff:g id="TIME">%2$s</xliff:g> (na podstawie Twojego sposobu korzystania)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> – telefon może się wkrótce wyłączyć"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> – tablet może się wkrótce wyłączyć"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> – urządzenie może się wkrótce wyłączyć"</string>
     <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> do pełnego naładowania"</string>
+    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do pełnego naładowania"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Nieznane"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Ładowanie"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"ładowanie"</string>
@@ -416,4 +431,8 @@
     <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"Nigdy"</string>
     <string name="zen_interruption_level_priority" msgid="2078370238113347720">"Tylko priorytet"</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>
+    <string name="zen_alarm_warning_indef" msgid="3007988140196673193">"Nie usłyszysz następnego alarmu o <xliff:g id="WHEN">%1$s</xliff:g>, chyba że wcześniej to wyłączysz"</string>
+    <string name="zen_alarm_warning" msgid="6236690803924413088">"Nie usłyszysz następnego alarmu o <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template" msgid="4996153414057676512">"o <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template_far" msgid="3779172822607461675">"w: <xliff:g id="WHEN">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index b13a9c0..39ac124 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -53,16 +53,16 @@
     <string name="bluetooth_disconnected" msgid="6557104142667339895">"Desconectado"</string>
     <string name="bluetooth_disconnecting" msgid="8913264760027764974">"Desconectando…"</string>
     <string name="bluetooth_connecting" msgid="8555009514614320497">"Conectando..."</string>
-    <string name="bluetooth_connected" msgid="6038755206916626419">"Conectado"</string>
+    <string name="bluetooth_connected" msgid="5427152882755735944">"Conectado a <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
     <string name="bluetooth_pairing" msgid="1426882272690346242">"Pareando…"</string>
-    <string name="bluetooth_connected_no_headset" msgid="2866994875046035609">"Conectado (sem telefone)"</string>
-    <string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Conectado (sem mídia)"</string>
-    <string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Conectado (sem acesso a mensagens)"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Conectado (sem telefone ou mídia)"</string>
-    <string name="bluetooth_connected_battery_level" msgid="7049181126136692368">"Conectado, nível da bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_headset_battery_level" msgid="5504193961248406027">"Conectado (sem smartphone), nível da bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="4751724026365870779">"Conectado (sem mídia), nível da bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1549265779323455261">"Conectado (sem smartphone ou mídia), nível da bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset" msgid="616068069034994802">"Conectado (sem telefone) a <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp" msgid="3736431800395923868">"Conectado (sem mídia) a <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_map" msgid="3200033913678466453">"Conectado (sem acesso a mensagens) a <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2047403011284187056">"Conectado (sem telefone ou mídia) a <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_battery_level" msgid="5162924691231307748">"Conectado, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> de bateria"</string>
+    <string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"Conectado (sem telefone), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> de bateria"</string>
+    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"Conectado (sem mídia), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> de bateria"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"Conectado (sem telefone ou mídia), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> de bateria"</string>
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Áudio da mídia"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"Chamadas telefônicas"</string>
     <string name="bluetooth_profile_opp" msgid="9168139293654233697">"Transferência de arquivo"</string>
@@ -75,6 +75,10 @@
     <string name="bluetooth_profile_sap" msgid="5764222021851283125">"Acesso SIM"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"Áudio HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"Áudio HD"</string>
+    <!-- no translation found for bluetooth_profile_hearing_aid (7999237886427812595) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (7188282786730266159) -->
+    <skip />
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Conectado ao áudio da mídia"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Conectado ao áudio do smartphone"</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Conectado ao servidor de transferência de arquivo"</string>
@@ -91,6 +95,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Usar para áudio do smartphone"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Usado para transferência de arquivo"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Usar para entrada"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (908775281788309484) -->
+    <skip />
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Parear"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"PAREAR"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Cancelar"</string>
@@ -327,9 +333,10 @@
     <item msgid="8280754435979370728">"Cores naturais, como vistas pelos olhos"</item>
     <item msgid="5363960654009010371">"Cores otimizadas para conteúdo digital"</item>
   </string-array>
-    <string name="inactive_apps_title" msgid="1317817863508274533">"Apps inativos"</string>
+    <string name="inactive_apps_title" msgid="9042996804461901648">"Apps em espera"</string>
     <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"Inativo. Tocar para alternar."</string>
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"Ativo. Tocar para alternar."</string>
+    <string name="standby_bucket_summary" msgid="6567835350910684727">"Estado em espera do app:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="runningservices_settings_title" msgid="8097287939865165213">"Serviços em execução"</string>
     <string name="runningservices_settings_summary" msgid="854608995821032748">"Visualizar e controlar os serviços em execução no momento"</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"Implementação do WebView"</string>
@@ -351,16 +358,24 @@
     <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Correção de cor"</string>
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Este recurso é experimental e pode afetar o desempenho."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Substituído por <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only" msgid="845431008899029842">"Cerca de <xliff:g id="TIME">^1</xliff:g> restante(s)"</string>
-    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Cerca de <xliff:g id="TIME">^1</xliff:g> restante(s) com base no seu uso"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">^1</xliff:g> restante(s) até a carga completa"</string>
-    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">^1</xliff:g> restante(s)"</string>
-    <string name="power_remaining_duration_only_short_enhanced" msgid="7450425624026394823">"<xliff:g id="TIME">^1</xliff:g> restante(s) com base no seu uso"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">^1</xliff:g> - cerca de <xliff:g id="TIME">^2</xliff:g> restante(s)"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">^1</xliff:g>: cerca de <xliff:g id="TIME">^2</xliff:g> restante(s) com base no seu uso"</string>
-    <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g> restante(s)"</string>
+    <string name="power_remaining_duration_only" msgid="845431008899029842">"Cerca de <xliff:g id="TIME">%1$s</xliff:g> restante(s)"</string>
+    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Cerca de <xliff:g id="TIME">%1$s</xliff:g> restante(s) com base no seu uso"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> restante(s) até a carga completa"</string>
+    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">%1$s</xliff:g> restante(s)"</string>
+    <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Menos de <xliff:g id="THRESHOLD">%1$s</xliff:g> restante(s)"</string>
+    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g>: menos de <xliff:g id="THRESHOLD">%2$s</xliff:g> restante(s)"</string>
+    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g>mais de <xliff:g id="TIME_REMAINING">%2$s</xliff:g> restante(s)"</string>
+    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"mais de <xliff:g id="TIME_REMAINING">%1$s</xliff:g> restante(s)"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"o smartphone pode ser desligado em breve"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"o tablet pode ser desligado em breve"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"o dispositivo pode ser desligado em breve"</string>
+    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> - cerca de <xliff:g id="TIME">%2$s</xliff:g> restante(s)"</string>
+    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g>: cerca de <xliff:g id="TIME">%2$s</xliff:g> restante(s) com base no seu uso"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g>: o smartphone pode ser desligado em breve"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g>: o tablet pode ser desligado em breve"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g>: o dispositivo pode ser desligado em breve"</string>
     <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> até a carga completa"</string>
+    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> até a carga completa"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Desconhecido"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Carregando"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"carregando"</string>
@@ -414,4 +429,8 @@
     <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"Nunca"</string>
     <string name="zen_interruption_level_priority" msgid="2078370238113347720">"Somente prioridade"</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>
+    <string name="zen_alarm_warning_indef" msgid="3007988140196673193">"Você não ouvirá o próximo alarme <xliff:g id="WHEN">%1$s</xliff:g>, a menos que desative essa opção antes desse horário"</string>
+    <string name="zen_alarm_warning" msgid="6236690803924413088">"Você não ouvirá o próximo alarme <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template" msgid="4996153414057676512">"às <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template_far" msgid="3779172822607461675">"<xliff:g id="WHEN">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index 2965ca7..ec9de7c 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -53,16 +53,16 @@
     <string name="bluetooth_disconnected" msgid="6557104142667339895">"Desligado"</string>
     <string name="bluetooth_disconnecting" msgid="8913264760027764974">"A desligar..."</string>
     <string name="bluetooth_connecting" msgid="8555009514614320497">"A ligar..."</string>
-    <string name="bluetooth_connected" msgid="6038755206916626419">"Ligado"</string>
+    <string name="bluetooth_connected" msgid="5427152882755735944">"Ligado<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
     <string name="bluetooth_pairing" msgid="1426882272690346242">"A emparelhar..."</string>
-    <string name="bluetooth_connected_no_headset" msgid="2866994875046035609">"Ligado (sem telefone)"</string>
-    <string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Ligado (sem multimédia)"</string>
-    <string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Ligado (sem acesso a mensagens)"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Ligado (sem telefone ou multimédia)"</string>
-    <string name="bluetooth_connected_battery_level" msgid="7049181126136692368">"Ligado com <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria"</string>
-    <string name="bluetooth_connected_no_headset_battery_level" msgid="5504193961248406027">"Ligado (sem telemóvel) com <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria"</string>
-    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="4751724026365870779">"Ligado (sem multimédia) com <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1549265779323455261">"Ligado (sem telemóvel nem multimédia) com <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria"</string>
+    <string name="bluetooth_connected_no_headset" msgid="616068069034994802">"Ligado (sem telemóvel)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp" msgid="3736431800395923868">"Ligado (sem multimédia)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_map" msgid="3200033913678466453">"Ligado (sem acesso a mensagens)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2047403011284187056">"Ligado (sem telemóvel nem multimédia)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_battery_level" msgid="5162924691231307748">"Ligado, bateria a <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"Ligado (sem telemóvel), bateria a <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"Ligado (sem multimédia), bateria a <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"Ligado (sem telemóvel nem multimédia), bateria a <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Áudio de multimédia"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"Chamadas telefónicas"</string>
     <string name="bluetooth_profile_opp" msgid="9168139293654233697">"Transferência do ficheiro"</string>
@@ -75,6 +75,10 @@
     <string name="bluetooth_profile_sap" msgid="5764222021851283125">"Acesso ao SIM"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"Áudio HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"Áudio HD"</string>
+    <!-- no translation found for bluetooth_profile_hearing_aid (7999237886427812595) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (7188282786730266159) -->
+    <skip />
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Ligado ao áudio de multimédia"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Ligado ao áudio do telefone"</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Ligado ao servidor de transferência de ficheiros"</string>
@@ -91,6 +95,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Utilizar para áudio do telefone"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Utilizar para transferência de ficheiros"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Utilizar para entrada"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (908775281788309484) -->
+    <skip />
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Par"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"SINCRONIZAR"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Cancelar"</string>
@@ -327,9 +333,10 @@
     <item msgid="8280754435979370728">"Cores naturais e realistas"</item>
     <item msgid="5363960654009010371">"Cores otimizadas para conteúdos digitais"</item>
   </string-array>
-    <string name="inactive_apps_title" msgid="1317817863508274533">"Aplicações inativas"</string>
+    <string name="inactive_apps_title" msgid="9042996804461901648">"Aplicações em espera"</string>
     <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"Inativo. Toque para ativar/desativar."</string>
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"Ativo. Toque para ativar/desativar."</string>
+    <string name="standby_bucket_summary" msgid="6567835350910684727">"Estado do Modo de espera das aplicações:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="runningservices_settings_title" msgid="8097287939865165213">"Serviços em execução"</string>
     <string name="runningservices_settings_summary" msgid="854608995821032748">"Ver e controlar os serviços actualmente em execução"</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"Implementação WebView"</string>
@@ -351,16 +358,24 @@
     <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Correção da cor"</string>
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Esta funcionalidade é experimental e pode afetar o desempenho."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Substituído por <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only" msgid="845431008899029842">"Falta(m) cerca de <xliff:g id="TIME">^1</xliff:g>"</string>
-    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Resta(m) cerca de <xliff:g id="TIME">^1</xliff:g> com base na sua utilização"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Falta(m) <xliff:g id="TIME">^1</xliff:g> para concluir o carregamento"</string>
-    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Resta(m) <xliff:g id="TIME">^1</xliff:g>"</string>
-    <string name="power_remaining_duration_only_short_enhanced" msgid="7450425624026394823">"Resta(m) <xliff:g id="TIME">^1</xliff:g> com base na sua utilização"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">^1</xliff:g> – falta(m) cerca de <xliff:g id="TIME">^2</xliff:g>"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">^1</xliff:g> – resta(m) cerca de <xliff:g id="TIME">^2</xliff:g> com base na sua utilização"</string>
-    <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> – resta(m) <xliff:g id="TIME">^2</xliff:g>"</string>
+    <string name="power_remaining_duration_only" msgid="845431008899029842">"Falta(m) cerca de <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Resta(m) cerca de <xliff:g id="TIME">%1$s</xliff:g> com base na sua utilização"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Falta(m) <xliff:g id="TIME">%1$s</xliff:g> para concluir o carregamento"</string>
+    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Resta(m) <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Resta(m) menos de <xliff:g id="THRESHOLD">%1$s</xliff:g>."</string>
+    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> – Resta(m) menos de <xliff:g id="THRESHOLD">%2$s</xliff:g>."</string>
+    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g> – Resta(m) mais de <xliff:g id="TIME_REMAINING">%2$s</xliff:g>."</string>
+    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"Resta(m) mais de <xliff:g id="TIME_REMAINING">%1$s</xliff:g>."</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"O telemóvel poderá ser encerrado em breve."</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"O tablet poderá ser encerrado em breve."</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"O dispositivo poderá ser encerrado em breve."</string>
+    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> – falta(m) cerca de <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> – resta(m) cerca de <xliff:g id="TIME">%2$s</xliff:g> com base na sua utilização"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> – O telemóvel poderá ser encerrado em breve."</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> – O tablet poderá ser encerrado em breve."</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> – O dispositivo poderá ser encerrado em breve."</string>
     <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> até ficar totalmente carregada"</string>
+    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> até ficar totalmente carregada"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Desconhecido"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"A carregar"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"a carregar…"</string>
@@ -414,4 +429,8 @@
     <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"Nunca"</string>
     <string name="zen_interruption_level_priority" msgid="2078370238113347720">"Apenas prioridade"</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>
+    <string name="zen_alarm_warning_indef" msgid="3007988140196673193">"Só vai ouvir o próximo alarme à(s) <xliff:g id="WHEN">%1$s</xliff:g> se desativar esta funcionalidade antes dessa hora."</string>
+    <string name="zen_alarm_warning" msgid="6236690803924413088">"Não vai ouvir o próximo alarme à(s) <xliff:g id="WHEN">%1$s</xliff:g>."</string>
+    <string name="alarm_template" msgid="4996153414057676512">"à(s) <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template_far" msgid="3779172822607461675">"no(a) <xliff:g id="WHEN">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index b13a9c0..39ac124 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -53,16 +53,16 @@
     <string name="bluetooth_disconnected" msgid="6557104142667339895">"Desconectado"</string>
     <string name="bluetooth_disconnecting" msgid="8913264760027764974">"Desconectando…"</string>
     <string name="bluetooth_connecting" msgid="8555009514614320497">"Conectando..."</string>
-    <string name="bluetooth_connected" msgid="6038755206916626419">"Conectado"</string>
+    <string name="bluetooth_connected" msgid="5427152882755735944">"Conectado a <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
     <string name="bluetooth_pairing" msgid="1426882272690346242">"Pareando…"</string>
-    <string name="bluetooth_connected_no_headset" msgid="2866994875046035609">"Conectado (sem telefone)"</string>
-    <string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Conectado (sem mídia)"</string>
-    <string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Conectado (sem acesso a mensagens)"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Conectado (sem telefone ou mídia)"</string>
-    <string name="bluetooth_connected_battery_level" msgid="7049181126136692368">"Conectado, nível da bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_headset_battery_level" msgid="5504193961248406027">"Conectado (sem smartphone), nível da bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="4751724026365870779">"Conectado (sem mídia), nível da bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1549265779323455261">"Conectado (sem smartphone ou mídia), nível da bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset" msgid="616068069034994802">"Conectado (sem telefone) a <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp" msgid="3736431800395923868">"Conectado (sem mídia) a <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_map" msgid="3200033913678466453">"Conectado (sem acesso a mensagens) a <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2047403011284187056">"Conectado (sem telefone ou mídia) a <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_battery_level" msgid="5162924691231307748">"Conectado, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> de bateria"</string>
+    <string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"Conectado (sem telefone), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> de bateria"</string>
+    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"Conectado (sem mídia), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> de bateria"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"Conectado (sem telefone ou mídia), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> de bateria"</string>
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Áudio da mídia"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"Chamadas telefônicas"</string>
     <string name="bluetooth_profile_opp" msgid="9168139293654233697">"Transferência de arquivo"</string>
@@ -75,6 +75,10 @@
     <string name="bluetooth_profile_sap" msgid="5764222021851283125">"Acesso SIM"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"Áudio HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"Áudio HD"</string>
+    <!-- no translation found for bluetooth_profile_hearing_aid (7999237886427812595) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (7188282786730266159) -->
+    <skip />
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Conectado ao áudio da mídia"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Conectado ao áudio do smartphone"</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Conectado ao servidor de transferência de arquivo"</string>
@@ -91,6 +95,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Usar para áudio do smartphone"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Usado para transferência de arquivo"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Usar para entrada"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (908775281788309484) -->
+    <skip />
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Parear"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"PAREAR"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Cancelar"</string>
@@ -327,9 +333,10 @@
     <item msgid="8280754435979370728">"Cores naturais, como vistas pelos olhos"</item>
     <item msgid="5363960654009010371">"Cores otimizadas para conteúdo digital"</item>
   </string-array>
-    <string name="inactive_apps_title" msgid="1317817863508274533">"Apps inativos"</string>
+    <string name="inactive_apps_title" msgid="9042996804461901648">"Apps em espera"</string>
     <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"Inativo. Tocar para alternar."</string>
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"Ativo. Tocar para alternar."</string>
+    <string name="standby_bucket_summary" msgid="6567835350910684727">"Estado em espera do app:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="runningservices_settings_title" msgid="8097287939865165213">"Serviços em execução"</string>
     <string name="runningservices_settings_summary" msgid="854608995821032748">"Visualizar e controlar os serviços em execução no momento"</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"Implementação do WebView"</string>
@@ -351,16 +358,24 @@
     <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Correção de cor"</string>
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Este recurso é experimental e pode afetar o desempenho."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Substituído por <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only" msgid="845431008899029842">"Cerca de <xliff:g id="TIME">^1</xliff:g> restante(s)"</string>
-    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Cerca de <xliff:g id="TIME">^1</xliff:g> restante(s) com base no seu uso"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">^1</xliff:g> restante(s) até a carga completa"</string>
-    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">^1</xliff:g> restante(s)"</string>
-    <string name="power_remaining_duration_only_short_enhanced" msgid="7450425624026394823">"<xliff:g id="TIME">^1</xliff:g> restante(s) com base no seu uso"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">^1</xliff:g> - cerca de <xliff:g id="TIME">^2</xliff:g> restante(s)"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">^1</xliff:g>: cerca de <xliff:g id="TIME">^2</xliff:g> restante(s) com base no seu uso"</string>
-    <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g> restante(s)"</string>
+    <string name="power_remaining_duration_only" msgid="845431008899029842">"Cerca de <xliff:g id="TIME">%1$s</xliff:g> restante(s)"</string>
+    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Cerca de <xliff:g id="TIME">%1$s</xliff:g> restante(s) com base no seu uso"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> restante(s) até a carga completa"</string>
+    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">%1$s</xliff:g> restante(s)"</string>
+    <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Menos de <xliff:g id="THRESHOLD">%1$s</xliff:g> restante(s)"</string>
+    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g>: menos de <xliff:g id="THRESHOLD">%2$s</xliff:g> restante(s)"</string>
+    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g>mais de <xliff:g id="TIME_REMAINING">%2$s</xliff:g> restante(s)"</string>
+    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"mais de <xliff:g id="TIME_REMAINING">%1$s</xliff:g> restante(s)"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"o smartphone pode ser desligado em breve"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"o tablet pode ser desligado em breve"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"o dispositivo pode ser desligado em breve"</string>
+    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> - cerca de <xliff:g id="TIME">%2$s</xliff:g> restante(s)"</string>
+    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g>: cerca de <xliff:g id="TIME">%2$s</xliff:g> restante(s) com base no seu uso"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g>: o smartphone pode ser desligado em breve"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g>: o tablet pode ser desligado em breve"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g>: o dispositivo pode ser desligado em breve"</string>
     <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> até a carga completa"</string>
+    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> até a carga completa"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Desconhecido"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Carregando"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"carregando"</string>
@@ -414,4 +429,8 @@
     <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"Nunca"</string>
     <string name="zen_interruption_level_priority" msgid="2078370238113347720">"Somente prioridade"</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>
+    <string name="zen_alarm_warning_indef" msgid="3007988140196673193">"Você não ouvirá o próximo alarme <xliff:g id="WHEN">%1$s</xliff:g>, a menos que desative essa opção antes desse horário"</string>
+    <string name="zen_alarm_warning" msgid="6236690803924413088">"Você não ouvirá o próximo alarme <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template" msgid="4996153414057676512">"às <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template_far" msgid="3779172822607461675">"<xliff:g id="WHEN">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index 9c3f0902..61a88e3 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -53,16 +53,16 @@
     <string name="bluetooth_disconnected" msgid="6557104142667339895">"Deconectat"</string>
     <string name="bluetooth_disconnecting" msgid="8913264760027764974">"În curs de deconectare..."</string>
     <string name="bluetooth_connecting" msgid="8555009514614320497">"Se conectează..."</string>
-    <string name="bluetooth_connected" msgid="6038755206916626419">"Conectat"</string>
+    <string name="bluetooth_connected" msgid="5427152882755735944">"V-ați conectat la <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
     <string name="bluetooth_pairing" msgid="1426882272690346242">"Se conectează…"</string>
-    <string name="bluetooth_connected_no_headset" msgid="2866994875046035609">"Conectat (fără telefon)"</string>
-    <string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Conectat (fără conținut media)"</string>
-    <string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Conectat (fără acces la mesaje)"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Conectat (fără telefon sau conț. media)"</string>
-    <string name="bluetooth_connected_battery_level" msgid="7049181126136692368">"Conectat, bateria la <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_headset_battery_level" msgid="5504193961248406027">"Conectat (fără telefon), bateria la <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="4751724026365870779">"Conectat (fără conținut media), bateria la <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1549265779323455261">"Conectat (fără telefon sau conținut media), bateria la <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset" msgid="616068069034994802">"Conectat (fără telefon) la <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp" msgid="3736431800395923868">"Conectat (fără conținut media) la <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_map" msgid="3200033913678466453">"Conectat (fără acces la mesaje) la <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2047403011284187056">"Conectat (fără telefon sau media) la <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_battery_level" msgid="5162924691231307748">"Conectat, baterie <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"Conectat (fără telefon), baterie <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"Conectat (fără conținut media), baterie <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"Conectat (fără telefon sau conținut media), baterie <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Conținut media audio"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"Apeluri telefonice"</string>
     <string name="bluetooth_profile_opp" msgid="9168139293654233697">"Transfer de fișiere"</string>
@@ -75,6 +75,10 @@
     <string name="bluetooth_profile_sap" msgid="5764222021851283125">"Acces la SIM"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"Audio HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"Audio HD"</string>
+    <!-- no translation found for bluetooth_profile_hearing_aid (7999237886427812595) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (7188282786730266159) -->
+    <skip />
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Conectat la profilul pentru conținut media audio"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Conectat la componenta audio a telefonului"</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Conectat la serverul de transfer de fișiere"</string>
@@ -91,6 +95,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Utilizați pentru componenta audio a telefonului"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Utilizați pentru transferul de fișiere"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Utilizați pentru introducere date"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (908775281788309484) -->
+    <skip />
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Asociați"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"CONECTAȚI"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Anulați"</string>
@@ -327,9 +333,10 @@
     <item msgid="8280754435979370728">"Culori naturale, așa cum le percepe ochiul"</item>
     <item msgid="5363960654009010371">"Culori optimizate pentru conținutul digital"</item>
   </string-array>
-    <string name="inactive_apps_title" msgid="1317817863508274533">"Aplicații inactive"</string>
+    <string name="inactive_apps_title" msgid="9042996804461901648">"Aplicații în standby"</string>
     <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"Inactivă. Atingeți pentru a comuta."</string>
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"Activă. Atingeți pentru a comuta."</string>
+    <string name="standby_bucket_summary" msgid="6567835350910684727">"Stare Standby aplicații: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="runningservices_settings_title" msgid="8097287939865165213">"Servicii în curs de funcționare"</string>
     <string name="runningservices_settings_summary" msgid="854608995821032748">"Vedeți și controlați serviciile care funcționează în prezent"</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"Implementare WebView"</string>
@@ -351,16 +358,24 @@
     <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Corecția culorii"</string>
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Această funcție este experimentală și poate afecta performanțele."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Valoare înlocuită de <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only" msgid="845431008899029842">"Timp rămas: aproximativ <xliff:g id="TIME">^1</xliff:g>"</string>
-    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"În baza utilizării, timpul aproximativ rămas este: <xliff:g id="TIME">^1</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Timp rămas până la încărcarea completă: <xliff:g id="TIME">^1</xliff:g>"</string>
-    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Timp rămas: <xliff:g id="TIME">^1</xliff:g>"</string>
-    <string name="power_remaining_duration_only_short_enhanced" msgid="7450425624026394823">"În baza utilizării, timpul rămas este: <xliff:g id="TIME">^1</xliff:g>"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">^1</xliff:g> - încă aproximativ <xliff:g id="TIME">^2</xliff:g>"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">^1</xliff:g> – în baza utilizării, timpul aproximativ rămas este: <xliff:g id="TIME">^2</xliff:g>"</string>
-    <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> – timp rămas: <xliff:g id="TIME">^2</xliff:g>"</string>
+    <string name="power_remaining_duration_only" msgid="845431008899029842">"Timp rămas: aproximativ <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"În baza utilizării, timpul aproximativ rămas este: <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Timp rămas până la încărcarea completă: <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Timp rămas: <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"a mai rămas mai puțin de <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
+    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> - a mai rămas mai puțin de <xliff:g id="THRESHOLD">%2$s</xliff:g>"</string>
+    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g> - a mai rămas mai mult de <xliff:g id="TIME_REMAINING">%2$s</xliff:g>"</string>
+    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"a mai rămas mai mult de <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"telefonul să poate închide în curând"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"tableta se poate închide în curând"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"dispozitivul se poate închide în curând"</string>
+    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> - încă aproximativ <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> – în baza utilizării, timpul aproximativ rămas este: <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> - telefonul se poate închide în curând"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> - tableta se poate închide în curând"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> - dispozitivul se poate închide în curând"</string>
     <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> până la încărcarea completă"</string>
+    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> până la încărcarea completă"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Necunoscut"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Se încarcă"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"se încarcă"</string>
@@ -415,4 +430,8 @@
     <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"Niciodată"</string>
     <string name="zen_interruption_level_priority" msgid="2078370238113347720">"Numai cu prioritate"</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>
+    <string name="zen_alarm_warning_indef" msgid="3007988140196673193">"Dacă nu dezactivați această opțiune înainte, nu veți auzi următoarea alarmă <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="zen_alarm_warning" msgid="6236690803924413088">"Nu veți auzi următoarea alarmă <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template" msgid="4996153414057676512">"la <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template_far" msgid="3779172822607461675">"<xliff:g id="WHEN">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index a4732eb..8456cc3 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -53,16 +53,16 @@
     <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>
+    <string name="bluetooth_connected" msgid="5427152882755735944">"Подключено<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
     <string name="bluetooth_pairing" msgid="1426882272690346242">"Сопряжение..."</string>
-    <string name="bluetooth_connected_no_headset" msgid="2866994875046035609">"Подключено (кроме HSP/HFP)"</string>
-    <string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Подключено (кроме A2DP)"</string>
-    <string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Подключено (нет доступа к сообщениям)"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Подключено (кроме HSP/HFP/A2DP)"</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>
+    <string name="bluetooth_connected_no_headset" msgid="616068069034994802">"Подключено (кроме звонков)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp" msgid="3736431800395923868">"Подключено (кроме аудио)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_map" msgid="3200033913678466453">"Подключено (кроме сообщений)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2047403011284187056">"Подключено (кроме звонков и аудио)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_battery_level" msgid="5162924691231307748">"Подключено, уровень заряда батареи: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"Подключено (кроме звонков), уровень заряда батареи: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"Подключено (кроме аудио), уровень заряда батареи: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"Подключено (кроме звонков и аудио), уровень заряда батареи: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Профиль A2DP"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"Звонки"</string>
     <string name="bluetooth_profile_opp" msgid="9168139293654233697">"Профиль OPP"</string>
@@ -75,6 +75,10 @@
     <string name="bluetooth_profile_sap" msgid="5764222021851283125">"Доступ к SIM-карте"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD Audio: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD Audio"</string>
+    <!-- no translation found for bluetooth_profile_hearing_aid (7999237886427812595) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (7188282786730266159) -->
+    <skip />
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Подключено к мультимедийному аудиоустройству"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Подключено к аудиоустройству телефона"</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Установлено подключение к серверу передачи файлов"</string>
@@ -91,6 +95,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Использовать для аудиоустройства телефона"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Используется для передачи файлов"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Использовать для ввода"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (908775281788309484) -->
+    <skip />
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Добавить"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"ДОБАВИТЬ"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Отмена"</string>
@@ -327,9 +333,10 @@
     <item msgid="8280754435979370728">"Натуральные цвета, привычные глазу"</item>
     <item msgid="5363960654009010371">"Цвета, оптимизированные для цифрового контента"</item>
   </string-array>
-    <string name="inactive_apps_title" msgid="1317817863508274533">"Неактивные приложения"</string>
+    <string name="inactive_apps_title" msgid="9042996804461901648">"Приложения в режиме ожидания"</string>
     <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"Выключено. Нажмите, чтобы включить."</string>
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"Включено. Нажмите, чтобы отключить."</string>
+    <string name="standby_bucket_summary" msgid="6567835350910684727">"Статус приложения в режиме ожидания:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <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 +358,24 @@
     <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>
+    <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Осталось менее <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
+    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"Уровень заряда батареи <xliff:g id="LEVEL">%1$s</xliff:g>. Осталось менее <xliff:g id="THRESHOLD">%2$s</xliff:g>."</string>
+    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"Уровень заряда батареи <xliff:g id="LEVEL">%1$s</xliff:g>. Осталось более <xliff:g id="TIME_REMAINING">%2$s</xliff:g>."</string>
+    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"Осталось более <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"телефон скоро завершит работу"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"планшет скоро завершит работу"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"устройство скоро завершит работу"</string>
+    <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>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"Уровень заряда батареи <xliff:g id="LEVEL">%1$s</xliff:g>. Телефон скоро завершит работу."</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"Уровень заряда батареи <xliff:g id="LEVEL">%1$s</xliff:g>. Планшет скоро завершит работу."</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"Уровень заряда батареи <xliff:g id="LEVEL">%1$s</xliff:g>. Устройство скоро завершит работу."</string>
     <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>
@@ -416,4 +431,8 @@
     <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>
+    <string name="zen_alarm_warning_indef" msgid="3007988140196673193">"Следующий будильник: <xliff:g id="WHEN">%1$s</xliff:g>. Чтобы услышать сигнал, включите звук."</string>
+    <string name="zen_alarm_warning" msgid="6236690803924413088">"Следующий будильник: <xliff:g id="WHEN">%1$s</xliff:g>. Звук отключен."</string>
+    <string name="alarm_template" msgid="4996153414057676512">"<xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template_far" msgid="3779172822607461675">"<xliff:g id="WHEN">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-si/strings.xml b/packages/SettingsLib/res/values-si/strings.xml
index 38dbe0a..b7557a0 100644
--- a/packages/SettingsLib/res/values-si/strings.xml
+++ b/packages/SettingsLib/res/values-si/strings.xml
@@ -53,16 +53,16 @@
     <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>
+    <string name="bluetooth_connected" msgid="5427152882755735944">"සම්බන්ධිත<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
     <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>
+    <string name="bluetooth_connected_no_headset" msgid="616068069034994802">"සම්බන්ධිතයි (දුරකථනය නැත) <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp" msgid="3736431800395923868">"සම්බන්ධිතයි (මාධ්‍ය නැත)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_map" msgid="3200033913678466453">"සම්බන්ධිතයි (පණිවිඩ ප්‍රවේශය නැත)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2047403011284187056">"සම්බන්ධිතයි (දුරකථනය හෝ මාධ්‍ය නැත) <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_battery_level" msgid="5162924691231307748">"සම්බන්ධිතයි, බැටරිය <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"සම්බන්ධිතයි (දුරකථනය නැත), බැටරිය <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"සම්බන්ධිතයි (මාධ්‍ය නැත), බැටරිය <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"සම්බන්ධිතයි (දුරකථනය හෝ මාධ්‍ය නැත), බැටරිය <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"මාධ්‍ය ශ්‍රව්‍ය"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"දුරකථන ඇමතුම්"</string>
     <string name="bluetooth_profile_opp" msgid="9168139293654233697">"ගොනු හුවමාරුව"</string>
@@ -75,6 +75,10 @@
     <string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM ප්‍රවේශය"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD ශ්‍රව්‍යය: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD ශ්‍රව්‍යය"</string>
+    <!-- no translation found for bluetooth_profile_hearing_aid (7999237886427812595) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (7188282786730266159) -->
+    <skip />
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"මාධ්‍ය ශ්‍රව්‍යට සම්බන්ධ විය"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"දුරකතනයේ ශ්‍රව්‍යට සම්බන්ධ විය"</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"ගොනු හුවමාරු සේවාදායකය සමග සම්බන්ධ විය"</string>
@@ -91,6 +95,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"දුරකථන ශ්‍රව්‍ය සඳහා භාවිතා කෙරේ"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"ගොනු හුවමාරුව සඳහා භාවිතා කරන්න"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"ආදානය සඳහා භාවිතා කරන්න"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (908775281788309484) -->
+    <skip />
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"යුගල කරන්න"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"යුගල කරන්න"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"අවලංගු කරන්න"</string>
@@ -327,9 +333,10 @@
     <item msgid="8280754435979370728">"ඇස දකින ස්වභාවික වර්ණ"</item>
     <item msgid="5363960654009010371">"ඩිජිටල් අන්තර්ගතය සඳහා වර්ණ ප්‍රශස්ත කරන ලද"</item>
   </string-array>
-    <string name="inactive_apps_title" msgid="1317817863508274533">"අක්‍රිය යෙදුම්"</string>
+    <string name="inactive_apps_title" msgid="9042996804461901648">"පොරොත්තු යෙදුම්"</string>
     <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"අක්‍රියයි. ටොගල කිරීමට තට්ටු කරන්න."</string>
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"සක්‍රියයි. ටොගල කිරීමට තට්ටු කරන්න."</string>
+    <string name="standby_bucket_summary" msgid="6567835350910684727">"යෙදුම් පොරොත්තු තත්ත්වය:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <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 +358,24 @@
     <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>
+    <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"<xliff:g id="THRESHOLD">%1$s</xliff:g>ට වඩා අඩුවෙන් ඉතිරිව ඇත"</string>
+    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="THRESHOLD">%2$s</xliff:g>ට වඩා අඩුවෙන් ඉතිරිව ඇත"</string>
+    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g><xliff:g id="TIME_REMAINING">%2$s</xliff:g>ට වඩා වැඩියෙන් ඉතිරිව ඇත"</string>
+    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g>ට වඩා වැඩියෙන් ඉතිරිව ඇත"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"දුරකථනය ඉක්මනින් වැසිය හැකිය"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"ටැබ්ලට් උපාංගය ඉක්මනින් වැසිය හැකිය"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"උපාංගය ඉක්මනින් වැසිය හැකිය"</string>
+    <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>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> - දුරකථනය ඉක්මනින් වැසිය හැකිය"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> - ටැබ්ලට් පරිගණකය ඉක්මනින් වැසිය හැකිය"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> - උපාංගය ඉක්මනින් වැසිය හැකිය"</string>
     <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 +429,8 @@
     <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>
+    <string name="zen_alarm_warning_indef" msgid="3007988140196673193">"ඔබට ඔබේ ඊළඟ එලාමය <xliff:g id="WHEN">%1$s</xliff:g> ඔබ එයට පෙර මෙය ක්‍රියාවිරහිත නොකළේ නම් නොඇසෙනු ඇත"</string>
+    <string name="zen_alarm_warning" msgid="6236690803924413088">"ඔබට ඔබේ ඊළඟ එලාමය <xliff:g id="WHEN">%1$s</xliff:g> තෙක් නොඇසෙනු ඇත"</string>
+    <string name="alarm_template" msgid="4996153414057676512">"<xliff:g id="WHEN">%1$s</xliff:g>ට"</string>
+    <string name="alarm_template_far" msgid="3779172822607461675">"<xliff:g id="WHEN">%1$s</xliff:g>හිදී"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-sk/arrays.xml b/packages/SettingsLib/res/values-sk/arrays.xml
index f3c25b4..20d7e24 100644
--- a/packages/SettingsLib/res/values-sk/arrays.xml
+++ b/packages/SettingsLib/res/values-sk/arrays.xml
@@ -234,10 +234,6 @@
     <item msgid="7688197031296835369">"Zobraziť oblasti prekreslení"</item>
     <item msgid="2290859360633824369">"Zobraziť oblasti pre deuteranomáliu"</item>
   </string-array>
-  <string-array name="debug_hw_renderer_entries">
-    <item msgid="2578620445459945681">"OpenGL (predvolené)"</item>
-    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
-  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"Štandardný limit"</item>
     <item msgid="4071574792028999443">"Žiadne procesy na pozadí"</item>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index 3d7cf28..65f6126 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -53,16 +53,16 @@
     <string name="bluetooth_disconnected" msgid="6557104142667339895">"Odpojený"</string>
     <string name="bluetooth_disconnecting" msgid="8913264760027764974">"Prebieha odpájanie..."</string>
     <string name="bluetooth_connecting" msgid="8555009514614320497">"Prebieha pripájanie…"</string>
-    <string name="bluetooth_connected" msgid="6038755206916626419">"Pripojené"</string>
+    <string name="bluetooth_connected" msgid="5427152882755735944">"Pripojené k zariadeniu <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
     <string name="bluetooth_pairing" msgid="1426882272690346242">"Párovanie..."</string>
-    <string name="bluetooth_connected_no_headset" msgid="2866994875046035609">"Pripojené (bez telefónu)"</string>
-    <string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Pripojené (bez média)"</string>
-    <string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Pripojené (bez prístupu ku správam)"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Pripojené (bez telefónu alebo média)"</string>
-    <string name="bluetooth_connected_battery_level" msgid="7049181126136692368">"Pripojené, stav batérie: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_headset_battery_level" msgid="5504193961248406027">"Pripojené (žiadny telefón), stav batérie: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="4751724026365870779">"Pripojené (žiadne médiá), stav batérie: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1549265779323455261">"Pripojené (žiadny telefón ani médiá), stav batérie: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset" msgid="616068069034994802">"Pripojené k zariadeniu <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> (bez telefónu)"</string>
+    <string name="bluetooth_connected_no_a2dp" msgid="3736431800395923868">"Pripojené k zariadeniu <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> (bez médií)"</string>
+    <string name="bluetooth_connected_no_map" msgid="3200033913678466453">"Pripojené k <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> (bez prístupu k správam)"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2047403011284187056">"Pripojené k <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> (bez telefónu a médií)"</string>
+    <string name="bluetooth_connected_battery_level" msgid="5162924691231307748">"Pripojené k zariadeniu <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>, úroveň batérie <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"Pripojené k zariadeniu <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (bez telefónu), úroveň batérie: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"Pripojené k zariadeniu <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (bez médií), úroveň batérie <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"Pripojené k zariadeniu <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (bez telefónu a médií), úroveň batérie <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Zvuk medií"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"Telefonické hovory"</string>
     <string name="bluetooth_profile_opp" msgid="9168139293654233697">"Prenos súborov"</string>
@@ -75,6 +75,10 @@
     <string name="bluetooth_profile_sap" msgid="5764222021851283125">"Prístup k SIM karte"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD zvuk: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD zvuk"</string>
+    <!-- no translation found for bluetooth_profile_hearing_aid (7999237886427812595) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (7188282786730266159) -->
+    <skip />
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Pripojené ku zvukovému médiu"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Pripojené ku zvuku telefónu"</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Pripojené na server pre prenos údajov"</string>
@@ -91,6 +95,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Použiť pre zvuk telefónu"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Použiť na prenos súborov"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Použiť pre vstup"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (908775281788309484) -->
+    <skip />
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Párovať"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"PÁROVAŤ"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Zrušiť"</string>
@@ -275,7 +281,6 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"Obnovenie hardvér. vrstiev"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Rozblikať zelene hardvérové vrstvy pri obnovení"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"Ladenie prekresľovania GPU"</string>
-    <string name="debug_hw_renderer" msgid="7568529019431785816">"Nastaviť vykr. modul GPU"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"Zakázať hardvérové prekrytia"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"Vždy používať GPU na skladanie obrazovky"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"Simulácia far. priestoru"</string>
@@ -328,9 +333,10 @@
     <item msgid="8280754435979370728">"Prirodzené farby, ako ich vidí ľudské oko"</item>
     <item msgid="5363960654009010371">"Farby optimalizované pre digitálny obsah"</item>
   </string-array>
-    <string name="inactive_apps_title" msgid="1317817863508274533">"Neaktívne aplikácie"</string>
+    <string name="inactive_apps_title" msgid="9042996804461901648">"Aplikácie v pohotovostnom režime"</string>
     <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"Neaktívne. Prepnite klepnutím."</string>
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"Aktívne. Prepnite klepnutím."</string>
+    <string name="standby_bucket_summary" msgid="6567835350910684727">"Stav pohotovostného režimu aplikácie: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="runningservices_settings_title" msgid="8097287939865165213">"Spustené služby"</string>
     <string name="runningservices_settings_summary" msgid="854608995821032748">"Zobrazenie a ovládanie aktuálne spustených služieb"</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"Implementácia WebView"</string>
@@ -352,16 +358,24 @@
     <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Úprava farieb"</string>
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Funkcia je experimentálna a môže mať vplyv na výkonnosť."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Prekonané predvoľbou <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only" msgid="845431008899029842">"Približný zostávajúci čas: <xliff:g id="TIME">^1</xliff:g>"</string>
-    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Zostáva približne <xliff:g id="TIME">^1</xliff:g> v závislosti od intenzity využitia"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Zostávajúci čas do úplného nabitia: <xliff:g id="TIME">^1</xliff:g>"</string>
-    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Zostávajúci čas: <xliff:g id="TIME">^1</xliff:g>"</string>
-    <string name="power_remaining_duration_only_short_enhanced" msgid="7450425624026394823">"Zostáva <xliff:g id="TIME">^1</xliff:g> v závislosti od intenzity využitia"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">^1</xliff:g> – približný zostávajúci čas: <xliff:g id="TIME">^2</xliff:g>"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">^1</xliff:g> – zostáva približne <xliff:g id="TIME">^2</xliff:g> v závislosti od intenzity využitia"</string>
-    <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> – zostávajúci čas: <xliff:g id="TIME">^2</xliff:g>"</string>
+    <string name="power_remaining_duration_only" msgid="845431008899029842">"Približný zostávajúci čas: <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Zostáva približne <xliff:g id="TIME">%1$s</xliff:g> v závislosti od intenzity využitia"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Zostávajúci čas do úplného nabitia: <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Zostávajúci čas: <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Zostáva menej ako <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
+    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> – zostáva menej ako <xliff:g id="THRESHOLD">%2$s</xliff:g>"</string>
+    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g> – zostáva viac ako <xliff:g id="TIME_REMAINING">%2$s</xliff:g>"</string>
+    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"zostáva viac ako <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"telefón sa môže čoskoro vypnúť"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"tablet sa môže čoskoro vypnúť"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"zariadenie sa môže čoskoro vypnúť"</string>
+    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> – približný zostávajúci čas: <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> – zostáva približne <xliff:g id="TIME">%2$s</xliff:g> v závislosti od intenzity využitia"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> – telefón sa môže čoskoro vypnúť"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> – tablet sa môže čoskoro vypnúť"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> – zariadenie sa môže čoskoro vypnúť"</string>
     <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> do úplného nabitia"</string>
+    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do úplného nabitia"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Neznáme"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Nabíja sa"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"nabíja sa"</string>
@@ -411,4 +425,14 @@
     </plurals>
     <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"Dlhší čas."</string>
     <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"Kratší čas."</string>
+    <string name="zen_mode_enable_dialog_turn_on" msgid="8287824809739581837">"Zapnúť"</string>
+    <string name="cancel" msgid="6859253417269739139">"Zrušiť"</string>
+    <string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"Zapnite režim Nerušiť"</string>
+    <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"Nikdy"</string>
+    <string name="zen_interruption_level_priority" msgid="2078370238113347720">"Iba prioritné"</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>
+    <string name="zen_alarm_warning_indef" msgid="3007988140196673193">"Ak toto nastavenie nevypnete, váš budík o <xliff:g id="WHEN">%1$s</xliff:g> sa nespustí"</string>
+    <string name="zen_alarm_warning" msgid="6236690803924413088">"Váš budík o <xliff:g id="WHEN">%1$s</xliff:g> sa nespustí"</string>
+    <string name="alarm_template" msgid="4996153414057676512">"o <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template_far" msgid="3779172822607461675">"o <xliff:g id="WHEN">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml
index fecc548..fd177e5 100644
--- a/packages/SettingsLib/res/values-sl/strings.xml
+++ b/packages/SettingsLib/res/values-sl/strings.xml
@@ -53,16 +53,16 @@
     <string name="bluetooth_disconnected" msgid="6557104142667339895">"Prekinjena povezava"</string>
     <string name="bluetooth_disconnecting" msgid="8913264760027764974">"Prekinjanje povezave ..."</string>
     <string name="bluetooth_connecting" msgid="8555009514614320497">"Vzpostavljanje povezave ..."</string>
-    <string name="bluetooth_connected" msgid="6038755206916626419">"Povezava je vzpostavljena"</string>
+    <string name="bluetooth_connected" msgid="5427152882755735944">"Povezano <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
     <string name="bluetooth_pairing" msgid="1426882272690346242">"Seznanjanje ..."</string>
-    <string name="bluetooth_connected_no_headset" msgid="2866994875046035609">"Povezava vzpostavljena (brez telefona)"</string>
-    <string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Povezava vzpostavljena (brez predstavnosti)"</string>
-    <string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Povezava vzp. (ni dostopa do sporočil)"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Povezava vzpostavljena (brez telefona ali predstavnosti)"</string>
-    <string name="bluetooth_connected_battery_level" msgid="7049181126136692368">"Povezava je vzpostavljena, raven napolnjenosti akumulatorja je <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_headset_battery_level" msgid="5504193961248406027">"Povezava je vzpostavljena (brez telefona), raven napolnjenosti akumulatorja je <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="4751724026365870779">"Povezava je vzpostavljena (brez predstavnosti), raven napolnjenosti akumulatorja je <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1549265779323455261">"Povezava je vzpostavljena (brez telefona ali predstavnosti), raven napolnjenosti akumulatorja je <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset" msgid="616068069034994802">"Povezano (brez telefona) <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp" msgid="3736431800395923868">"Povezano (brez predstavnosti) <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_map" msgid="3200033913678466453">"Povezano (brez dostopa do sporočil) <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2047403011284187056">"Povezano (brez telefona/predstavnosti) <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_battery_level" msgid="5162924691231307748">"Povezano, raven napolnjenosti akumulatorja je <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"Povezano (brez telefona), raven napolnjenosti akumulatorja je <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"Povezano (brez predstavnosti), raven napolnjenosti akumulatorja je <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"Povezano (brez telefona ali predstavnosti), raven napolnjenosti akumulatorja je <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Zvok predstavnosti"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"Telefonski klici"</string>
     <string name="bluetooth_profile_opp" msgid="9168139293654233697">"Prenos datoteke"</string>
@@ -75,6 +75,10 @@
     <string name="bluetooth_profile_sap" msgid="5764222021851283125">"Dostop do kartice SIM"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"Zvok visoke kakovosti: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"Zvok visoke kakovosti"</string>
+    <!-- no translation found for bluetooth_profile_hearing_aid (7999237886427812595) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (7188282786730266159) -->
+    <skip />
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Povezan s profilom za predstavnostni zvok"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Povezava s profilom za zvok telefona vzpostavljena"</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Povezava s strežnikom za prenos datotek je vzpostavljena"</string>
@@ -91,6 +95,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Uporabi za zvok telefona"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Uporabi za prenos datotek"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Uporabi za vnos"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (908775281788309484) -->
+    <skip />
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Seznani"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"SEZNANI"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Prekliči"</string>
@@ -327,9 +333,10 @@
     <item msgid="8280754435979370728">"Naravne barve, kot jih vidimo s prostim očesom"</item>
     <item msgid="5363960654009010371">"Barve, optimizirane za digitalno vsebino"</item>
   </string-array>
-    <string name="inactive_apps_title" msgid="1317817863508274533">"Neaktivne aplikacije"</string>
+    <string name="inactive_apps_title" msgid="9042996804461901648">"Aplikacije v stanju pripravljenosti"</string>
     <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"Neaktivno. Dotaknite se za preklop."</string>
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"Aktivno. Dotaknite se za preklop."</string>
+    <string name="standby_bucket_summary" msgid="6567835350910684727">"Stanje pripravljenosti aplikacije: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="runningservices_settings_title" msgid="8097287939865165213">"Zagnane storitve"</string>
     <string name="runningservices_settings_summary" msgid="854608995821032748">"Preglejte in nadzorujte storitve, ki so trenutno zagnane"</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"Izvedba spletnega pogleda"</string>
@@ -351,16 +358,24 @@
     <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Popravljanje barv"</string>
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"To je preskusna funkcija in lahko vpliva na učinkovitost delovanja."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Preglasila nastavitev: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only" msgid="845431008899029842">"Še približno <xliff:g id="TIME">^1</xliff:g>"</string>
-    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Glede na način uporabe imate na voljo še približno <xliff:g id="TIME">^1</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Še <xliff:g id="TIME">^1</xliff:g> do polne napolnjenosti"</string>
-    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Še <xliff:g id="TIME">^1</xliff:g>"</string>
-    <string name="power_remaining_duration_only_short_enhanced" msgid="7450425624026394823">"Glede na način uporabe imate na voljo še <xliff:g id="TIME">^1</xliff:g>"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">^1</xliff:g> – še približno <xliff:g id="TIME">^2</xliff:g>"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">^1</xliff:g> – glede na način uporabe imate na voljo še približno <xliff:g id="TIME">^2</xliff:g>"</string>
-    <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> – še <xliff:g id="TIME">^2</xliff:g>"</string>
+    <string name="power_remaining_duration_only" msgid="845431008899029842">"Še približno <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Glede na način uporabe imate na voljo še približno <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Še <xliff:g id="TIME">%1$s</xliff:g> do polne napolnjenosti"</string>
+    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Še <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Preostalo manj kot <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
+    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> – preostalo manj kot <xliff:g id="THRESHOLD">%2$s</xliff:g>"</string>
+    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g> – preostalo več kot <xliff:g id="TIME_REMAINING">%2$s</xliff:g>"</string>
+    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"preostalo več kot <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"telefon se bo morda kmalu zaustavil"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"tablični računalnik se bo morda kmalu zaustavil"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"naprava se bo morda kmalu zaustavila"</string>
+    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> – še približno <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> – glede na način uporabe imate na voljo še približno <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> – telefon se bo morda kmalu zaustavil"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> – tablični računalnik se bo morda kmalu zaustavil"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> – naprava se bo morda kmalu zaustavila"</string>
     <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> do napolnjenosti"</string>
+    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do napolnjenosti"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Neznano"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Polnjenje"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"polnjenje"</string>
@@ -416,4 +431,8 @@
     <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"Nikoli"</string>
     <string name="zen_interruption_level_priority" msgid="2078370238113347720">"Samo prednostno"</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>
+    <string name="zen_alarm_warning_indef" msgid="3007988140196673193">"Naslednjega alarma ob <xliff:g id="WHEN">%1$s</xliff:g> ne boste slišali, razen če prej izklopite to nastavitev"</string>
+    <string name="zen_alarm_warning" msgid="6236690803924413088">"Naslednjega alarma ob <xliff:g id="WHEN">%1$s</xliff:g> ne boste slišali"</string>
+    <string name="alarm_template" msgid="4996153414057676512">"ob <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template_far" msgid="3779172822607461675">"v <xliff:g id="WHEN">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-sq/strings.xml b/packages/SettingsLib/res/values-sq/strings.xml
index 0999b75..cf0fe12 100644
--- a/packages/SettingsLib/res/values-sq/strings.xml
+++ b/packages/SettingsLib/res/values-sq/strings.xml
@@ -53,16 +53,16 @@
     <string name="bluetooth_disconnected" msgid="6557104142667339895">"Shkëputur"</string>
     <string name="bluetooth_disconnecting" msgid="8913264760027764974">"Po shkëputet..."</string>
     <string name="bluetooth_connecting" msgid="8555009514614320497">"Po lidhet..."</string>
-    <string name="bluetooth_connected" msgid="6038755206916626419">"U lidh"</string>
+    <string name="bluetooth_connected" msgid="5427152882755735944">"E lidhur<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
     <string name="bluetooth_pairing" msgid="1426882272690346242">"Po çiftohet..."</string>
-    <string name="bluetooth_connected_no_headset" msgid="2866994875046035609">"U lidh (pa telefon)"</string>
-    <string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"U lidh (nuk ka media)"</string>
-    <string name="bluetooth_connected_no_map" msgid="6504436917057479986">"U lidh (pa qasje te mesazhet)"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"I lidhur (pa telefon apo media)"</string>
-    <string name="bluetooth_connected_battery_level" msgid="7049181126136692368">"E lidhur, bateria <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_headset_battery_level" msgid="5504193961248406027">"E lidhur (nuk ka telefon), bateria <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="4751724026365870779">"E lidhur (nuk ka media), bateria <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1549265779323455261">"E lidhur (nuk ka telefon ose media), bateria <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset" msgid="616068069034994802">"E lidhur (pa telefon)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp" msgid="3736431800395923868">"E lidhur (pa media)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_map" msgid="3200033913678466453">"E lidhur (nuk ka qasje te mesazhet)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2047403011284187056">"E lidhur (pa telefon ose media)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_battery_level" msgid="5162924691231307748">"E lidhur, bateria <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"E lidhur (pa telefon), bateria <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"E lidhur (pa media), bateria <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"E lidhur (pa telefon ose media), bateria <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Audioja e klipit \"media\""</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"Telefonatat"</string>
     <string name="bluetooth_profile_opp" msgid="9168139293654233697">"Transferimi i skedarëve"</string>
@@ -75,6 +75,10 @@
     <string name="bluetooth_profile_sap" msgid="5764222021851283125">"Qasje në kartën SIM"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"Audio HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"Audio HD"</string>
+    <!-- no translation found for bluetooth_profile_hearing_aid (7999237886427812595) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (7188282786730266159) -->
+    <skip />
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"U lidh me audion e medias"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"U lidh me audion e telefonit"</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"U lidh me serverin e transferimit të skedarëve"</string>
@@ -91,6 +95,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Përdor për audion e telefonit"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Përdor për transferimin e skedarëve"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Përdore për hyrjen"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (908775281788309484) -->
+    <skip />
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Çifto"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"ÇIFTO"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Anulo"</string>
@@ -327,9 +333,10 @@
     <item msgid="8280754435979370728">"Ngjyra natyrale siç shikohen me sy të lirë"</item>
     <item msgid="5363960654009010371">"Ngjyra të optimizuara për përmbajtjet dixhitale"</item>
   </string-array>
-    <string name="inactive_apps_title" msgid="1317817863508274533">"Aplikacionet joaktive"</string>
+    <string name="inactive_apps_title" msgid="9042996804461901648">"Aplikacionet në gatishmëri"</string>
     <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"Joaktiv. Trokit për ta ndryshuar."</string>
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"Aktiv. Trokit për ta ndryshuar."</string>
+    <string name="standby_bucket_summary" msgid="6567835350910684727">"Gjendja e gatishmërisë e aplikacionit:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="runningservices_settings_title" msgid="8097287939865165213">"Shërbimet në ekzekutim"</string>
     <string name="runningservices_settings_summary" msgid="854608995821032748">"Shiko dhe kontrollo shërbimet që po ekzekutohen aktualisht"</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"Zbatimi i WebView"</string>
@@ -351,16 +358,24 @@
     <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Korrigjimi i ngjyrës"</string>
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Ky funksion është eksperimental dhe mund të ndikojë në veprimtari."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Mbivendosur nga <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only" msgid="845431008899029842">"Rreth <xliff:g id="TIME">^1</xliff:g> të mbetura"</string>
-    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Rreth <xliff:g id="TIME">^1</xliff:g> të mbetura bazuar në përdorimin tënd"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">^1</xliff:g> të mbetura deri në ngarkimin e plotë"</string>
-    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">^1</xliff:g> të mbetura"</string>
-    <string name="power_remaining_duration_only_short_enhanced" msgid="7450425624026394823">"<xliff:g id="TIME">^1</xliff:g> të mbetura bazuar në përdorimin tënd"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">^1</xliff:g> - rreth <xliff:g id="TIME">^2</xliff:g> të mbetura"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">^1</xliff:g> - rreth <xliff:g id="TIME">^2</xliff:g> të mbetura bazuar në përdorimin tënd"</string>
-    <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g> të mbetura"</string>
+    <string name="power_remaining_duration_only" msgid="845431008899029842">"Rreth <xliff:g id="TIME">%1$s</xliff:g> të mbetura"</string>
+    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Rreth <xliff:g id="TIME">%1$s</xliff:g> të mbetura bazuar në përdorimin tënd"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> të mbetura deri në ngarkimin e plotë"</string>
+    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">%1$s</xliff:g> të mbetura"</string>
+    <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Më pak se <xliff:g id="THRESHOLD">%1$s</xliff:g> të mbetura"</string>
+    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> - Më pak se <xliff:g id="THRESHOLD">%2$s</xliff:g> të mbetura"</string>
+    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g>më pak se <xliff:g id="TIME_REMAINING">%2$s</xliff:g> të mbetura"</string>
+    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"më shumë se <xliff:g id="TIME_REMAINING">%1$s</xliff:g> të mbetura"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"telefoni mund të fiket së shpejti"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"tableti mund të fiket së shpejti"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"pajisja mund të fiket së shpejti"</string>
+    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> - rreth <xliff:g id="TIME">%2$s</xliff:g> të mbetura"</string>
+    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> - rreth <xliff:g id="TIME">%2$s</xliff:g> të mbetura bazuar në përdorimin tënd"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> - telefoni mund të fiket së shpejti"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> - tableti mund të fiket së shpejti"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> - tableti mund të fiket së shpejti"</string>
     <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> derisa të mbushet plotësisht"</string>
+    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> derisa të mbushet plotësisht"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"I panjohur"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Po ngarkohet"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"po ngarkohet"</string>
@@ -414,4 +429,8 @@
     <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"Asnjëherë"</string>
     <string name="zen_interruption_level_priority" msgid="2078370238113347720">"Vetëm me prioritet"</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>
+    <string name="zen_alarm_warning_indef" msgid="3007988140196673193">"Nuk do ta dëgjosh alarmin e radhës në <xliff:g id="WHEN">%1$s</xliff:g> nëse nuk e çaktivizon këtë përpara asaj ore"</string>
+    <string name="zen_alarm_warning" msgid="6236690803924413088">"Nuk do ta dëgjosh alarmin e radhës në <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template" msgid="4996153414057676512">"në <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template_far" msgid="3779172822607461675">"ditën <xliff:g id="WHEN">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-sr/arrays.xml b/packages/SettingsLib/res/values-sr/arrays.xml
index 4486bf1..8767185 100644
--- a/packages/SettingsLib/res/values-sr/arrays.xml
+++ b/packages/SettingsLib/res/values-sr/arrays.xml
@@ -234,10 +234,6 @@
     <item msgid="7688197031296835369">"Прикажи области преклапања"</item>
     <item msgid="2290859360633824369">"Прикажи области за деутераномалију"</item>
   </string-array>
-  <string-array name="debug_hw_renderer_entries">
-    <item msgid="2578620445459945681">"OpenGL (подразумевано)"</item>
-    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
-  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"Стандардно ограничење"</item>
     <item msgid="4071574792028999443">"Без позадинских процеса"</item>
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index 226315b..b76c4dd 100644
--- a/packages/SettingsLib/res/values-sr/strings.xml
+++ b/packages/SettingsLib/res/values-sr/strings.xml
@@ -53,16 +53,16 @@
     <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>
+    <string name="bluetooth_connected" msgid="5427152882755735944">"Повезано: <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
     <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>
+    <string name="bluetooth_connected_no_headset" msgid="616068069034994802">"Повезано (без телефона): <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp" msgid="3736431800395923868">"Повезано (без медија): <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_map" msgid="3200033913678466453">"Повезано је (без приступа порукама): <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2047403011284187056">"Повезано (без телефона или медија): <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_battery_level" msgid="5162924691231307748">"Повезано, ниво батерије је <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"Повезано (без телефона), ниво батерије је <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"Повезано (без медија), ниво батерије је <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"Повезано (без телефона или медија), ниво батерије је <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Звук медија"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"Телефонски позиви"</string>
     <string name="bluetooth_profile_opp" msgid="9168139293654233697">"Пренос датотеке"</string>
@@ -75,6 +75,10 @@
     <string name="bluetooth_profile_sap" msgid="5764222021851283125">"Приступ SIM картици"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD звук: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD звук"</string>
+    <!-- no translation found for bluetooth_profile_hearing_aid (7999237886427812595) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (7188282786730266159) -->
+    <skip />
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Повезано са звуком медија"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Повезано са звуком телефона"</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Повезано са сервером за пренос датотека"</string>
@@ -91,6 +95,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Коришћење за аудио телефона"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Коришћење за пренос датотека"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Користи за улаз"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (908775281788309484) -->
+    <skip />
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Упари"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"УПАРИ"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Откажи"</string>
@@ -275,7 +281,6 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"Прикажи ажурирања хардверских слојева"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Хардверски слојеви трепере зелено када се ажурирају"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"Отклони грешке GPU преклапања"</string>
-    <string name="debug_hw_renderer" msgid="7568529019431785816">"Подеси GPU приказивач"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"Онемог. HW пост. елементе"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"Увек користи GPU за компоновање екрана"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"Симулирај простор боје"</string>
@@ -328,9 +333,10 @@
     <item msgid="8280754435979370728">"Природне боје налик онима које региструје око"</item>
     <item msgid="5363960654009010371">"Боје оптимизоване за дигитални садржај"</item>
   </string-array>
-    <string name="inactive_apps_title" msgid="1317817863508274533">"Неактивне апликације"</string>
+    <string name="inactive_apps_title" msgid="9042996804461901648">"Апликације у стању приправности"</string>
     <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"Неактивна. Додирните да бисте је активирали."</string>
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"Активна. Додирните да бисте је деактивирали."</string>
+    <string name="standby_bucket_summary" msgid="6567835350910684727">"Стање приправности апликације: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <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>
@@ -352,16 +358,24 @@
     <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>
+    <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Преостало је мање од <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
+    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> – преостало је мање од <xliff:g id="THRESHOLD">%2$s</xliff:g>"</string>
+    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g> – преостало је више од <xliff:g id="TIME_REMAINING">%2$s</xliff:g>"</string>
+    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"преостало је више од <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"телефон ће се ускоро искључити"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"таблет ће се ускоро искључити"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"уређај ће се ускоро искључити"</string>
+    <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>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> – телефон ће се ускоро искључити"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> – таблет ће се ускоро искључити"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> – уређај ће се ускоро искључити"</string>
     <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>
@@ -410,4 +424,14 @@
     </plurals>
     <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"Више времена."</string>
     <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"Мање времена."</string>
+    <string name="zen_mode_enable_dialog_turn_on" msgid="8287824809739581837">"Укључи"</string>
+    <string name="cancel" msgid="6859253417269739139">"Откажи"</string>
+    <string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"Укључите режим Не узнемиравај"</string>
+    <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>
+    <string name="zen_alarm_warning_indef" msgid="3007988140196673193">"Нећете чути следећи аларм у <xliff:g id="WHEN">%1$s</xliff:g> ако не искључите ово пре тога"</string>
+    <string name="zen_alarm_warning" msgid="6236690803924413088">"Нећете чути следећи аларм у <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template" msgid="4996153414057676512">"у <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template_far" msgid="3779172822607461675">"<xliff:g id="WHEN">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-sv/arrays.xml b/packages/SettingsLib/res/values-sv/arrays.xml
index de1e54f..b359aab 100644
--- a/packages/SettingsLib/res/values-sv/arrays.xml
+++ b/packages/SettingsLib/res/values-sv/arrays.xml
@@ -234,10 +234,6 @@
     <item msgid="7688197031296835369">"Visa överritningsområden"</item>
     <item msgid="2290859360633824369">"Visa områden för deuteranomali"</item>
   </string-array>
-  <string-array name="debug_hw_renderer_entries">
-    <item msgid="2578620445459945681">"OpenGL (standard)"</item>
-    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
-  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"Standardgräns"</item>
     <item msgid="4071574792028999443">"Inga bakgrundsprocesser"</item>
diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml
index 874294f..4509470 100644
--- a/packages/SettingsLib/res/values-sv/strings.xml
+++ b/packages/SettingsLib/res/values-sv/strings.xml
@@ -53,16 +53,16 @@
     <string name="bluetooth_disconnected" msgid="6557104142667339895">"Kopplas ifrån"</string>
     <string name="bluetooth_disconnecting" msgid="8913264760027764974">"Kopplar ifrån…"</string>
     <string name="bluetooth_connecting" msgid="8555009514614320497">"Ansluter…"</string>
-    <string name="bluetooth_connected" msgid="6038755206916626419">"Ansluten"</string>
+    <string name="bluetooth_connected" msgid="5427152882755735944">"Ansluten<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
     <string name="bluetooth_pairing" msgid="1426882272690346242">"Parkoppling…"</string>
-    <string name="bluetooth_connected_no_headset" msgid="2866994875046035609">"Ansluten (ingen telefon)"</string>
-    <string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Ansluten (inga media)"</string>
-    <string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Ansluten (ingen meddelandeåtkomst)"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Ansluten (ingen telefon och inga media)"</string>
-    <string name="bluetooth_connected_battery_level" msgid="7049181126136692368">"Ansluten, batterinivå <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_headset_battery_level" msgid="5504193961248406027">"Ansluten (ingen mobil), batterinivå <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="4751724026365870779">"Ansluten (inga medier), batterinivå <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1549265779323455261">"Ansluten (ingen mobil och inga medier), batterinivå <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset" msgid="616068069034994802">"Ansluten (ingen mobil)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp" msgid="3736431800395923868">"Ansluten (inga medier)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_map" msgid="3200033913678466453">"Ansluten (ingen meddelandeåtkomst)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2047403011284187056">"Ansluten (ingen mobil och inga medier) <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_battery_level" msgid="5162924691231307748">"Ansluten, batterinivå <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"Ansluten (ingen mobil), batterinivå <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"Ansluten (inga medier), batterinivå <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"Ansluten (ingen mobil och inga medier), batterinivå <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Medialjud"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"Telefonsamtal"</string>
     <string name="bluetooth_profile_opp" msgid="9168139293654233697">"Filöverföring"</string>
@@ -75,6 +75,10 @@
     <string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM-åtkomst"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD-ljud: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD-ljud"</string>
+    <!-- no translation found for bluetooth_profile_hearing_aid (7999237886427812595) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (7188282786730266159) -->
+    <skip />
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Ansluten till medialjud"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Ansluten till telefonens ljud"</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Ansluten till filöverföringsserver"</string>
@@ -91,6 +95,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Använd för telefonens ljud"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Använd för filöverföring"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Använd för inmatning"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (908775281788309484) -->
+    <skip />
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Parkoppling"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"PARKOPPLA"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Avbryt"</string>
@@ -275,7 +281,6 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"Visa maskinvaruskiktuppd."</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Låt maskinvaruskikt blinka grönt vid uppdateringar"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"Felsök GPU-överritning"</string>
-    <string name="debug_hw_renderer" msgid="7568529019431785816">"Ange GPU-renderare"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"Inaktivera HW-överlagringar"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"Använd alltid GPU för skärmsammansättning"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"Simulera färgrymd"</string>
@@ -328,9 +333,10 @@
     <item msgid="8280754435979370728">"Naturliga färger så som ögat ser dem"</item>
     <item msgid="5363960654009010371">"Färger som har anpassats för digitalt innehåll"</item>
   </string-array>
-    <string name="inactive_apps_title" msgid="1317817863508274533">"Inaktiva appar"</string>
+    <string name="inactive_apps_title" msgid="9042996804461901648">"Appar i viloläge"</string>
     <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"Inaktiv. Tryck om du vill aktivera."</string>
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"Aktiv. Tryck om du vill inaktivera."</string>
+    <string name="standby_bucket_summary" msgid="6567835350910684727">"Status för strömsparfunktion för appar:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="runningservices_settings_title" msgid="8097287939865165213">"Aktiva tjänster"</string>
     <string name="runningservices_settings_summary" msgid="854608995821032748">"Visa och styr aktiva tjänster"</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView-implementering"</string>
@@ -352,16 +358,24 @@
     <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Färgkorrigering"</string>
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Den här funktionen är experimentell och kan påverka prestandan."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Har åsidosatts av <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only" msgid="845431008899029842">"Cirka <xliff:g id="TIME">^1</xliff:g> återstår"</string>
-    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Cirka <xliff:g id="TIME">^1</xliff:g> kvar utifrån din användning"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Batteriet är fulladdat om <xliff:g id="TIME">^1</xliff:g>"</string>
-    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">^1</xliff:g> kvar"</string>
-    <string name="power_remaining_duration_only_short_enhanced" msgid="7450425624026394823">"<xliff:g id="TIME">^1</xliff:g> kvar utifrån din användning"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">^1</xliff:g> – cirka <xliff:g id="TIME">^2</xliff:g> kvar"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">^1</xliff:g> – cirka <xliff:g id="TIME">^2</xliff:g> kvar utifrån din användning"</string>
-    <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> – <xliff:g id="TIME">^2</xliff:g> kvar"</string>
+    <string name="power_remaining_duration_only" msgid="845431008899029842">"Cirka <xliff:g id="TIME">%1$s</xliff:g> återstår"</string>
+    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Cirka <xliff:g id="TIME">%1$s</xliff:g> kvar utifrån din användning"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Batteriet är fulladdat om <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> kvar"</string>
+    <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Mindre än <xliff:g id="THRESHOLD">%1$s</xliff:g> återstår"</string>
+    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> – Mindre än <xliff:g id="THRESHOLD">%2$s</xliff:g> återstår"</string>
+    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g>mer än <xliff:g id="TIME_REMAINING">%2$s</xliff:g> återstår"</string>
+    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"mer än <xliff:g id="TIME_REMAINING">%1$s</xliff:g> återstår"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"mobilen kan stängas av snart"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"surfplattan kan stängas av snart"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"enheten kan stängas av snart"</string>
+    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> – cirka <xliff:g id="TIME">%2$s</xliff:g> kvar"</string>
+    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> – cirka <xliff:g id="TIME">%2$s</xliff:g> kvar utifrån din användning"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> – mobilen kan stängas av snart"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> – surfplattan kan stängas av snart"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> – enheten kan stängas av snart"</string>
     <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> tills det är fulladdat"</string>
+    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> tills det är fulladdat"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Okänd"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Laddar"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"laddas"</string>
@@ -409,4 +423,14 @@
     </plurals>
     <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"Längre tid."</string>
     <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"Kortare tid."</string>
+    <string name="zen_mode_enable_dialog_turn_on" msgid="8287824809739581837">"Aktivera"</string>
+    <string name="cancel" msgid="6859253417269739139">"Avbryt"</string>
+    <string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"Aktivera Stör ej."</string>
+    <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"Aldrig"</string>
+    <string name="zen_interruption_level_priority" msgid="2078370238113347720">"Endast prioriterade"</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>
+    <string name="zen_alarm_warning_indef" msgid="3007988140196673193">"Nästa alarm, kl. <xliff:g id="WHEN">%1$s</xliff:g>, kommer inte att höras om du inte inaktiverar detta innan dess"</string>
+    <string name="zen_alarm_warning" msgid="6236690803924413088">"Nästa alarm, kl. <xliff:g id="WHEN">%1$s</xliff:g>, kommer inte att höras"</string>
+    <string name="alarm_template" msgid="4996153414057676512">"kl. <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template_far" msgid="3779172822607461675">"på <xliff:g id="WHEN">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml
index 72850d4..ad8edcc 100644
--- a/packages/SettingsLib/res/values-sw/strings.xml
+++ b/packages/SettingsLib/res/values-sw/strings.xml
@@ -53,16 +53,16 @@
     <string name="bluetooth_disconnected" msgid="6557104142667339895">"Haijaunganishwa"</string>
     <string name="bluetooth_disconnecting" msgid="8913264760027764974">"Inatenganisha..."</string>
     <string name="bluetooth_connecting" msgid="8555009514614320497">"Inaunganisha…"</string>
-    <string name="bluetooth_connected" msgid="6038755206916626419">"Umeunganishwa"</string>
+    <string name="bluetooth_connected" msgid="5427152882755735944">"Imeunganishwa<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
     <string name="bluetooth_pairing" msgid="1426882272690346242">"Inaoanisha..."</string>
-    <string name="bluetooth_connected_no_headset" msgid="2866994875046035609">"Imeunganishwa (hakuna simu)"</string>
-    <string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Imeunganishwa(hakuna vyombo vya habari)"</string>
-    <string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Imeunganishwa (hakuna ufikiaji kwa ujumbe)"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Imeunganishwa(hakuna simu au vyombo vya habari)"</string>
-    <string name="bluetooth_connected_battery_level" msgid="7049181126136692368">"Imeunganishwa, kiwango cha betri ni <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_headset_battery_level" msgid="5504193961248406027">"Imeunganishwa (hakuna simu), kiwango cha betri ni <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="4751724026365870779">"Imeunganishwa (hakuna maudhui), kiwango cha betri ni <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1549265779323455261">"Imeunganishwa (hakuna simu wala maudhui), kiwango cha betri ni <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset" msgid="616068069034994802">"Imeunganishwa (hamna simu)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp" msgid="3736431800395923868">"Imeunganishwa (hamna kifaa cha sauti)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_map" msgid="3200033913678466453">"Imeunganishwa (haifikii ujumbe)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2047403011284187056">"Imeunganishwa (hamna simu au kifaa cha sauti)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_battery_level" msgid="5162924691231307748">"Imeunganishwa, kiasi cha chaji ni <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"Imeunganishwa (hamna simu), kiasi cha chaji ni <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"Imeunganishwa (hamna kifaa cha sauti), kiasi cha chaji ni <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"Imeunganishwa (hamna simu au kifaa cha sauti), kiasi cha chaji ni <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Media ya sauti"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"Simu"</string>
     <string name="bluetooth_profile_opp" msgid="9168139293654233697">"Uhamishaji wa faili"</string>
@@ -75,6 +75,10 @@
     <string name="bluetooth_profile_sap" msgid="5764222021851283125">"Ufikiaji wa SIM"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"Sauti ya HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"Sauti ya HD"</string>
+    <!-- no translation found for bluetooth_profile_hearing_aid (7999237886427812595) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (7188282786730266159) -->
+    <skip />
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Imeunganishwa kwenye sikika ya njia ya mawasiliano"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Imeunganishwa kwenye sauti ya simu"</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Imeunganishwa kwenye seva ya kuhamisha faili"</string>
@@ -91,6 +95,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Tumia kwa sauti ya simu"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Tumia kwa hali faili"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Tumia kwa kuingiza"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (908775281788309484) -->
+    <skip />
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Oanisha"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"OANISHA"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Ghairi"</string>
@@ -327,9 +333,10 @@
     <item msgid="8280754435979370728">"Rangi asili kama zinavyoonekana kwa macho"</item>
     <item msgid="5363960654009010371">"Rangi zilizoboreshwa kwa ajili ya maudhui dijitali"</item>
   </string-array>
-    <string name="inactive_apps_title" msgid="1317817863508274533">"Programu zilizozimwa"</string>
+    <string name="inactive_apps_title" msgid="9042996804461901648">"Programu zisizo na shughuli"</string>
     <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"Haitumika. Gusa ili ugeuze."</string>
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"Inatumika. Gusa ili ugeuze."</string>
+    <string name="standby_bucket_summary" msgid="6567835350910684727">"Hali ya kisitisha programu:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="runningservices_settings_title" msgid="8097287939865165213">"Huduma zinazoendeshwa"</string>
     <string name="runningservices_settings_summary" msgid="854608995821032748">"Onyesha na dhibiti huduma zinazoendeshwa kwa sasa"</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"Utekelezaji wa WebView"</string>
@@ -351,16 +358,24 @@
     <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Usahihishaji wa rangi"</string>
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Kipengele hiki ni cha majaribio na huenda kikaathiri utendaji wa kifaa chako."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Imetanguliwa na <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only" msgid="845431008899029842">"Zimesalia takribani <xliff:g id="TIME">^1</xliff:g>"</string>
-    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Takriban <xliff:g id="TIME">^1</xliff:g> zimesalia kulingana na matumizi yako"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Imebaki <xliff:g id="TIME">^1</xliff:g> chaji ijae"</string>
-    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Zimesalia <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> zimesalia kulingana na matumizi yako"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">^1</xliff:g> - imesalia takribani <xliff:g id="TIME">^2</xliff:g>"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">^1</xliff:g> - takriban <xliff:g id="TIME">^2</xliff:g> zimesalia kulingana na matumizi yako"</string>
-    <string name="power_discharging_duration_short" msgid="4192244429001842403">"Imechaji <xliff:g id="LEVEL">^1</xliff:g> - Zimesalia <xliff:g id="TIME">^2</xliff:g>"</string>
+    <string name="power_remaining_duration_only" msgid="845431008899029842">"Zimesalia takribani <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Takriban <xliff:g id="TIME">%1$s</xliff:g> zimesalia kulingana na matumizi yako"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Imebaki <xliff:g id="TIME">%1$s</xliff:g> chaji ijae"</string>
+    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Zimesalia <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Zimesalia chini ya <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
+    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> - Zimesalia chini ya <xliff:g id="THRESHOLD">%2$s</xliff:g>"</string>
+    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g> zimesalia zaidi ya <xliff:g id="TIME_REMAINING">%2$s</xliff:g>"</string>
+    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"zimesalia zaidi ya <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"simu inakaribia kuzimika"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"kompyuta kibao inakaribia kuzimika"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"kifaa kinakaribia kuzimika"</string>
+    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> - imesalia takribani <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> - takriban <xliff:g id="TIME">%2$s</xliff:g> zimesalia kulingana na matumizi yako"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> - simu inakaribia kuzimika"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> - kompyuta kibao inakaribia kuzimika"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> - kifaa kinakaribia kuzimika"</string>
     <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> hadi ijae chaji"</string>
+    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> hadi ijae chaji"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Haijulikani"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Inachaji"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"inachaji"</string>
@@ -414,4 +429,8 @@
     <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"Kamwe"</string>
     <string name="zen_interruption_level_priority" msgid="2078370238113347720">"Kipaumbele tu"</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>
+    <string name="zen_alarm_warning_indef" msgid="3007988140196673193">"Hutasikia kengele inayofuata ya saa <xliff:g id="WHEN">%1$s</xliff:g> isipokuwa uzime mipangilio hii kabla ya wakati huo"</string>
+    <string name="zen_alarm_warning" msgid="6236690803924413088">"Hutasikia kengele inayofuata ya saa <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template" msgid="4996153414057676512">"saa <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template_far" msgid="3779172822607461675">"siku ya <xliff:g id="WHEN">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml
index 64bc434..274222b 100644
--- a/packages/SettingsLib/res/values-ta/strings.xml
+++ b/packages/SettingsLib/res/values-ta/strings.xml
@@ -53,16 +53,16 @@
     <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>
+    <string name="bluetooth_connected" msgid="5427152882755735944">"<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> சாதனம் இணைக்கப்பட்டது"</string>
     <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>
+    <string name="bluetooth_connected_no_headset" msgid="616068069034994802">"<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> இணைக்கப்பட்டது (மொபைல் இல்லை)"</string>
+    <string name="bluetooth_connected_no_a2dp" msgid="3736431800395923868">"<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> இணைக்கப்பட்டது (மீடியா இல்லை)"</string>
+    <string name="bluetooth_connected_no_map" msgid="3200033913678466453">"<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> இணைக்கப்பட்டது (செய்தி அணுகல் இல்லை)"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2047403011284187056">"<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> இணைக்கப்பட்டது (மொபைல்/மீடியா இல்லை)"</string>
+    <string name="bluetooth_connected_battery_level" msgid="5162924691231307748">"இணைக்கப்பட்டது, பேட்டரி <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"இணைக்கப்பட்டது (மொபைல் இல்லை), பேட்டரி <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"இணைக்கப்பட்டது (மீடியா இல்லை), பேட்டரி <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"இணைக்கப்பட்டது (மொபைல் அல்லது மீடியா இல்லை), பேட்டரி <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"மீடியா ஆடியோ"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"ஃபோன் அழைப்புகள்"</string>
     <string name="bluetooth_profile_opp" msgid="9168139293654233697">"கோப்பு இடமாற்றம்"</string>
@@ -75,6 +75,10 @@
     <string name="bluetooth_profile_sap" msgid="5764222021851283125">"சிம் அணுகல்"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD ஆடியோ: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD ஆடியோ"</string>
+    <!-- no translation found for bluetooth_profile_hearing_aid (7999237886427812595) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (7188282786730266159) -->
+    <skip />
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"மீடியா ஆடியோவுடன் இணைக்கப்பட்டது"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"மொபைல் ஆடியோவுடன் இணைக்கப்பட்டது"</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"கோப்பைப் பரிமாற்றும் சேவையகத்துடன் இணைக்கப்பட்டது"</string>
@@ -91,6 +95,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"மொபைல் ஆடியோவைப் பயன்படுத்து"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"கோப்பு பரிமாற்றத்திற்காகப் பயன்படுத்து"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"உள்ளீட்டுக்குப் பயன்படுத்து"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (908775281788309484) -->
+    <skip />
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"இணை"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"இணை"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"ரத்துசெய்"</string>
@@ -327,9 +333,10 @@
     <item msgid="8280754435979370728">"கண்களால் பார்ப்பதைப் போலவே இயற்கையான வண்ணங்கள்"</item>
     <item msgid="5363960654009010371">"டிஜிட்டல் உள்ளடக்கத்திற்கு ஏற்ப மேம்படுத்தப்பட்ட வண்ணங்கள்"</item>
   </string-array>
-    <string name="inactive_apps_title" msgid="1317817863508274533">"செயலில் இல்லாத பயன்பாடுகள்"</string>
+    <string name="inactive_apps_title" msgid="9042996804461901648">"காத்திருப்பில் உள்ள ஆப்ஸ்"</string>
     <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"செயலில் இல்லை. மாற்ற, தட்டவும்."</string>
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"செயலில் உள்ளது. மாற்ற, தட்டவும்."</string>
+    <string name="standby_bucket_summary" msgid="6567835350910684727">"காத்திருப்பில் உள்ள பயன்பாட்டின் நிலை:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <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 +358,24 @@
     <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>
+    <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"<xliff:g id="THRESHOLD">%1$s</xliff:g>க்கும் குறைவாகவே பயன்படுத்த முடியும்"</string>
+    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> பேட்டரி மட்டுமே உள்ளது, <xliff:g id="THRESHOLD">%2$s</xliff:g>க்கும் குறைவாகவே பயன்படுத்தமுடியும்"</string>
+    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"பேட்டரி <xliff:g id="LEVEL">%1$s</xliff:g> உள்ளது, <xliff:g id="TIME_REMAINING">%2$s</xliff:g>க்கு மேல் பயன்படுத்த முடியும்"</string>
+    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g>க்கு மேல் பயன்படுத்த முடியும்"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"மொபைல் விரைவில் ஆஃப் ஆகக்கூடும்"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"டேப்லெட் விரைவில் ஆஃப் ஆகக்கூடும்"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"சாதனம் விரைவில் ஆஃப் ஆகக்கூடும்"</string>
+    <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>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> - மொபைல் விரைவில் ஆஃப் ஆகக்கூடும்"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> - டேப்லெட் விரைவில் ஆஃப் ஆகக்கூடும்"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> - சாதனம் விரைவில் ஆஃப் ஆகக்கூடும்"</string>
     <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 +429,8 @@
     <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>
+    <string name="zen_alarm_warning_indef" msgid="3007988140196673193">"<xliff:g id="WHEN">%1$s</xliff:g>க்கு முன்பு இதை ஆஃப் செய்யாவிட்டால், அடுத்த அலாரத்திற்கு ஒலி இருக்காது"</string>
+    <string name="zen_alarm_warning" msgid="6236690803924413088">"<xliff:g id="WHEN">%1$s</xliff:g>க்கான அடுத்த அலாரத்திற்கு ஒலி இருக்காது"</string>
+    <string name="alarm_template" msgid="4996153414057676512">"அலாரம்: <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template_far" msgid="3779172822607461675">"அலாரம்: <xliff:g id="WHEN">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml
index 2e00dfb..31f0cdf 100644
--- a/packages/SettingsLib/res/values-te/strings.xml
+++ b/packages/SettingsLib/res/values-te/strings.xml
@@ -53,16 +53,16 @@
     <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>
+    <string name="bluetooth_connected" msgid="5427152882755735944">"కనెక్ట్ చేయబడిన<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
     <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>
+    <string name="bluetooth_connected_no_headset" msgid="616068069034994802">"కనెక్ట్ చేయబడింది (ఫోన్ కాదు)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp" msgid="3736431800395923868">"కనెక్ట్ చేయబడింది (మీడియా కాదు)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_map" msgid="3200033913678466453">"కనెక్ట్ చేయబడింది (సందేశ యాక్సెస్ లేదు)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2047403011284187056">"కనెక్ట్ చేయబడింది (ఫోన్ లేదా మీడియా కాదు)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_battery_level" msgid="5162924691231307748">"కనెక్ట్ చేయబడింది, బ్యాటరీ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"కనెక్ట్ చేయబడింది (ఫోన్ కాదు), బ్యాటరీ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"కనెక్ట్ చేయబడింది (మీడియా కాదు), బ్యాటరీ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"కనెక్ట్ చేయబడింది (ఫోన్ లేదా మీడియా కాదు), బ్యాటరీ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"మీడియా ఆడియో"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"ఫోన్ కాల్‌లు"</string>
     <string name="bluetooth_profile_opp" msgid="9168139293654233697">"ఫైల్ బదిలీ"</string>
@@ -75,6 +75,10 @@
     <string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM యాక్సెస్"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD ఆడియో: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD ఆడియో"</string>
+    <!-- no translation found for bluetooth_profile_hearing_aid (7999237886427812595) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (7188282786730266159) -->
+    <skip />
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"మీడియా ఆడియోకు కనెక్ట్ చేయబడింది"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"ఫోన్ ఆడియోకు కనెక్ట్ చేయబడింది"</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"ఫైల్ బదిలీ సర్వర్‌కు కనెక్ట్ చేయబడింది"</string>
@@ -91,6 +95,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"ఫోన్ ఆడియో కోసం ఉపయోగించు"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"ఫైల్ బదిలీ కోసం ఉపయోగించు"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"ఇన్‌పుట్ కోసం ఉపయోగించు"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (908775281788309484) -->
+    <skip />
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"జత చేయి"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"జత చేయి"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"రద్దు చేయి"</string>
@@ -327,9 +333,10 @@
     <item msgid="8280754435979370728">"కంటికి కనిపించే విధంగా సహజమైన రంగులు"</item>
     <item msgid="5363960654009010371">"డిజిటల్ కంటెంట్ కోసం అనుకూలీకరించిన రంగులు"</item>
   </string-array>
-    <string name="inactive_apps_title" msgid="1317817863508274533">"నిష్క్రియ అనువర్తనాలు"</string>
+    <string name="inactive_apps_title" msgid="9042996804461901648">"స్టాండ్‌బై యాప్‌లు"</string>
     <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"నిష్క్రియంగా ఉంది. టోగుల్ చేయడానికి నొక్కండి."</string>
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"సక్రియంగా ఉంది. టోగుల్ చేయడానికి నొక్కండి."</string>
+    <string name="standby_bucket_summary" msgid="6567835350910684727">"యాప్ స్టాండ్‌బై స్థితి:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="runningservices_settings_title" msgid="8097287939865165213">"అమలులో ఉన్న సేవలు"</string>
     <string name="runningservices_settings_summary" msgid="854608995821032748">"ప్రస్తుతం అమలులో ఉన్న సేవలను వీక్షించండి మరియు నియంత్రించండి"</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"వెబ్ వీక్షణ అమలు"</string>
@@ -351,16 +358,24 @@
     <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>
+    <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"<xliff:g id="THRESHOLD">%1$s</xliff:g> కంటే తక్కువ సమయం మిగిలి ఉంది"</string>
+    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="THRESHOLD">%2$s</xliff:g> కంటే తక్కువ సమయం మిగిలి ఉంది"</string>
+    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g><xliff:g id="TIME_REMAINING">%2$s</xliff:g> కంటే ఎక్కువ సమయం మిగిలి ఉంది"</string>
+    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> కంటే ఎక్కువ సమయం మిగిలి ఉంది"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"ఫోన్ త్వరలో షట్‌డౌన్ కావచ్చు"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"టాబ్లెట్ త్వరలో షట్‌డౌన్ కావచ్చు"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"పరికరం త్వరలో షట్‌డౌన్ కావచ్చు"</string>
+    <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>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> - ఫోన్ త్వరలో షట్‌డౌన్ కావచ్చు"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> - టాబ్లెట్ త్వరలో షట్‌డౌన్ కావచ్చు"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> - పరికరం త్వరలో షట్‌డౌన్ కావచ్చు"</string>
     <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 +429,8 @@
     <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>
+    <string name="zen_alarm_warning_indef" msgid="3007988140196673193">"మీరు <xliff:g id="WHEN">%1$s</xliff:g> సెట్ చేసిన మీ తర్వాత అలారం మీరు ఆ లోపల దీన్ని ఆఫ్ చేయకుంటే వినిపించదు"</string>
+    <string name="zen_alarm_warning" msgid="6236690803924413088">"మీరు <xliff:g id="WHEN">%1$s</xliff:g> సెట్ చేసిన మీ తర్వాత అలారం మీకు వినిపించదు"</string>
+    <string name="alarm_template" msgid="4996153414057676512">"<xliff:g id="WHEN">%1$s</xliff:g>కి"</string>
+    <string name="alarm_template_far" msgid="3779172822607461675">"<xliff:g id="WHEN">%1$s</xliff:g>కి"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-th/arrays.xml b/packages/SettingsLib/res/values-th/arrays.xml
index 6d1c5d7..a577ab7 100644
--- a/packages/SettingsLib/res/values-th/arrays.xml
+++ b/packages/SettingsLib/res/values-th/arrays.xml
@@ -234,10 +234,6 @@
     <item msgid="7688197031296835369">"แสดงพื้นที่การวาดทับ"</item>
     <item msgid="2290859360633824369">"แสดงพื้นที่สำหรับคนตาบอดสีเขียว"</item>
   </string-array>
-  <string-array name="debug_hw_renderer_entries">
-    <item msgid="2578620445459945681">"OpenGL (ค่าเริ่มต้น)"</item>
-    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
-  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"ขีดจำกัดมาตรฐาน"</item>
     <item msgid="4071574792028999443">"ไม่มีกระบวนการพื้นหลัง"</item>
diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index 9f7bc73..ce2c143 100644
--- a/packages/SettingsLib/res/values-th/strings.xml
+++ b/packages/SettingsLib/res/values-th/strings.xml
@@ -53,16 +53,16 @@
     <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>
+    <string name="bluetooth_connected" msgid="5427152882755735944">"เชื่อมต่อแล้ว<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
     <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>
+    <string name="bluetooth_connected_no_headset" msgid="616068069034994802">"เชื่อมต่อแล้ว (ไม่รวมโทรศัพท์)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp" msgid="3736431800395923868">"เชื่อมต่อแล้ว (ไม่รวมสื่อ)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_map" msgid="3200033913678466453">"เชื่อมต่อแล้ว (ไม่มีการเข้าถึงข้อความ)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2047403011284187056">"เชื่อมต่อแล้ว (ไม่รวมโทรศัพท์หรือสื่อ)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_battery_level" msgid="5162924691231307748">"เชื่อมต่อแล้ว แบตเตอรี่ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"เชื่อมต่อแล้ว (ไม่รวมโทรศัพท์) แบตเตอรี่ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"เชื่อมต่อแล้ว (ไม่รวมสื่อ) แบตเตอรี่ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"เชื่อมต่อแล้ว (ไม่รวมโทรศัพท์หรือสื่อ) แบตเตอรี่ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"เสียงของสื่อ"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"โทรศัพท์"</string>
     <string name="bluetooth_profile_opp" msgid="9168139293654233697">"การถ่ายโอนไฟล์"</string>
@@ -75,6 +75,10 @@
     <string name="bluetooth_profile_sap" msgid="5764222021851283125">"การเข้าถึงซิม"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"เสียง HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"เสียง HD"</string>
+    <!-- no translation found for bluetooth_profile_hearing_aid (7999237886427812595) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (7188282786730266159) -->
+    <skip />
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"เชื่อมต่อกับระบบเสียงของสื่อแล้ว"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"เชื่อมต่อกับระบบเสียงของโทรศัพท์แล้ว"</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"เชื่อมต่อกับเซิร์ฟเวอร์สำหรับโอนไฟล์แล้ว"</string>
@@ -91,6 +95,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"ใช้สำหรับระบบเสียงของโทรศัพท์"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"ใช้สำหรับการโอนไฟล์"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"ใช้สำหรับการป้อนข้อมูล"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (908775281788309484) -->
+    <skip />
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"จับคู่อุปกรณ์"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"จับคู่อุปกรณ์"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"ยกเลิก"</string>
@@ -275,7 +281,6 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"แสดงอัปเดตเลเยอร์ฮาร์ดแวร์"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"เลเยอร์ฮาร์ดแวร์กะพริบเป็นสีเขียว เมื่อมีการอัปเดต"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"แก้ปัญหาการวาดทับด้วย GPU"</string>
-    <string name="debug_hw_renderer" msgid="7568529019431785816">"ตั้งค่า GPU Renderer"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"ปิดใช้งานการวางซ้อน HW"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"ใช้ GPU ในการจัดวางองค์ประกอบหน้าจอเสมอ"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"จำลองระบบสี"</string>
@@ -328,9 +333,10 @@
     <item msgid="8280754435979370728">"สีธรรมชาติตามที่ดวงตามองเห็น"</item>
     <item msgid="5363960654009010371">"สีที่เหมาะกับเนื้อหาดิจิทัล"</item>
   </string-array>
-    <string name="inactive_apps_title" msgid="1317817863508274533">"แอปที่ไม่ได้ใช้งาน"</string>
+    <string name="inactive_apps_title" msgid="9042996804461901648">"แอปที่สแตนด์บายอยู่"</string>
     <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"ไม่ได้ใช้งาน แตะเพื่อสลับ"</string>
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"ใช้งานอยู่ แตะเพื่อสลับ"</string>
+    <string name="standby_bucket_summary" msgid="6567835350910684727">"สถานะการสแตนด์บายของแอป:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <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>
@@ -352,16 +358,24 @@
     <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>
+    <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"เหลืออีกไม่ถึง <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
+    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> - เหลืออีกไม่ถึง <xliff:g id="THRESHOLD">%2$s</xliff:g>"</string>
+    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g> - เหลือเวลามากกว่า <xliff:g id="TIME_REMAINING">%2$s</xliff:g>"</string>
+    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"เหลือเวลามากกว่า <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"โทรศัพท์อาจปิดเครื่องในไม่ช้า"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"แท็บเล็ตอาจปิดเครื่องในไม่ช้า"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"อุปกรณ์อาจปิดเครื่องในไม่ช้า"</string>
+    <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>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> - โทรศัพท์อาจปิดเครื่องในไม่ช้า"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> - แท็บเล็ตอาจปิดเครื่องในไม่ช้า"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> - อุปกรณ์อาจปิดเครื่องในไม่ช้า"</string>
     <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>
@@ -409,4 +423,14 @@
     </plurals>
     <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"เวลามากขึ้น"</string>
     <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"เวลาน้อยลง"</string>
+    <string name="zen_mode_enable_dialog_turn_on" msgid="8287824809739581837">"เปิด"</string>
+    <string name="cancel" msgid="6859253417269739139">"ยกเลิก"</string>
+    <string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"เปิด \"ห้ามรบกวน\""</string>
+    <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>
+    <string name="zen_alarm_warning_indef" msgid="3007988140196673193">"คุณจะไม่ได้ยินเสียงปลุกครั้งถัดไปในเวลา <xliff:g id="WHEN">%1$s</xliff:g> เว้นแต่คุณจะปิดการปลุกนี้ไปก่อนแล้ว"</string>
+    <string name="zen_alarm_warning" msgid="6236690803924413088">"คุณจะไม่ได้ยินเสียงปลุกครั้งถัดไปในเวลา <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template" msgid="4996153414057676512">"เวลา <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template_far" msgid="3779172822607461675">"วัน<xliff:g id="WHEN">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-tl/arrays.xml b/packages/SettingsLib/res/values-tl/arrays.xml
index 7a3fd30..e9e7fff 100644
--- a/packages/SettingsLib/res/values-tl/arrays.xml
+++ b/packages/SettingsLib/res/values-tl/arrays.xml
@@ -234,10 +234,6 @@
     <item msgid="7688197031296835369">"Tingnan ang mga overdraw na bahagi"</item>
     <item msgid="2290859360633824369">"Ipakita ang mga lugar para sa Deuteranomaly"</item>
   </string-array>
-  <string-array name="debug_hw_renderer_entries">
-    <item msgid="2578620445459945681">"OpenGL (Default)"</item>
-    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
-  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"Karaniwang limitasyon"</item>
     <item msgid="4071574792028999443">"Walang mga proseso sa background"</item>
diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml
index 1b5eb2f..b6006fe 100644
--- a/packages/SettingsLib/res/values-tl/strings.xml
+++ b/packages/SettingsLib/res/values-tl/strings.xml
@@ -53,16 +53,16 @@
     <string name="bluetooth_disconnected" msgid="6557104142667339895">"Hindi nakakonekta"</string>
     <string name="bluetooth_disconnecting" msgid="8913264760027764974">"Nadidiskonekta..."</string>
     <string name="bluetooth_connecting" msgid="8555009514614320497">"Kumukonekta…"</string>
-    <string name="bluetooth_connected" msgid="6038755206916626419">"Konektado"</string>
+    <string name="bluetooth_connected" msgid="5427152882755735944">"Nakakonekta<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
     <string name="bluetooth_pairing" msgid="1426882272690346242">"Pinapares…"</string>
-    <string name="bluetooth_connected_no_headset" msgid="2866994875046035609">"Nakakonekta (walang telepono)"</string>
-    <string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Nakakonekta (walang media)"</string>
-    <string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Nakakonekta (walang access sa mensahe)"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Nakakonekta (walang telepono o media)"</string>
-    <string name="bluetooth_connected_battery_level" msgid="7049181126136692368">"Nakakonekta, baterya <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_headset_battery_level" msgid="5504193961248406027">"Nakakonekta (walang telepono), baterya <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="4751724026365870779">"Nakakonekta (walang media), baterya <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1549265779323455261">"Nakakonekta (walang telepono o media), baterya <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset" msgid="616068069034994802">"Nakakonekta (walang telepono)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp" msgid="3736431800395923868">"Nakakonekta (walang media)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_map" msgid="3200033913678466453">"Nakakonekta (walang access sa mensahe)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2047403011284187056">"Nakakonekta (walang telepono o media)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_battery_level" msgid="5162924691231307748">"Nakakonekta, baterya <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"Nakakonekta (walang telepono), baterya <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"Nakakonekta (walang media), baterya <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"Nakakonekta (walang telepono o media), baterya <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Audio ng media"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"Mga tawag sa telepono"</string>
     <string name="bluetooth_profile_opp" msgid="9168139293654233697">"Paglilipat ng file"</string>
@@ -75,6 +75,10 @@
     <string name="bluetooth_profile_sap" msgid="5764222021851283125">"Access sa SIM"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD audio: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD audio"</string>
+    <!-- no translation found for bluetooth_profile_hearing_aid (7999237886427812595) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (7188282786730266159) -->
+    <skip />
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Konektado sa media audio"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Nakakonekta sa audio ng telepono"</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Nakakonekta sa server sa paglilipat ng file"</string>
@@ -91,6 +95,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Ginagamit para sa audio ng telepono"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Ginagamit para sa paglilipat ng file"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Gamitin para sa input"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (908775281788309484) -->
+    <skip />
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Pares"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"IPARES"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Kanselahin"</string>
@@ -275,7 +281,6 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"Ipakita ang mga update ng hardware layers"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"I-flash nang berde ang hardware layer pag nag-update ito"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"I-debug ang GPU overdraw"</string>
-    <string name="debug_hw_renderer" msgid="7568529019431785816">"Itakda ang GPU Renderer"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"Wag paganahin HW overlay"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"Laging gamitin ang GPU para sa screen compositing"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"Gayahin ang color space"</string>
@@ -328,9 +333,10 @@
     <item msgid="8280754435979370728">"Mga natural na kulay tulad ng nakikita ng mata"</item>
     <item msgid="5363960654009010371">"Mga kulay na naka-optimize para sa digital na content"</item>
   </string-array>
-    <string name="inactive_apps_title" msgid="1317817863508274533">"Mga hindi aktibong app"</string>
+    <string name="inactive_apps_title" msgid="9042996804461901648">"Mga standby app"</string>
     <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"Hindi aktibo. I-tap upang i-toggle."</string>
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"Aktibo. I-tap upang i-toggle."</string>
+    <string name="standby_bucket_summary" msgid="6567835350910684727">"Status ng app standby:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="runningservices_settings_title" msgid="8097287939865165213">"Mga tumatakbong serbisyo"</string>
     <string name="runningservices_settings_summary" msgid="854608995821032748">"Tingnan at kontrolin ang mga kasalukuyang tumatakbong serbisyo"</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"Pagpapatupad sa WebView"</string>
@@ -352,16 +358,24 @@
     <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Pagtatama ng kulay"</string>
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Ang feature na ito ay pinag-eeksperimentuhan at maaaring makaapekto sa performance."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Na-override ng <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only" msgid="845431008899029842">"Humigit-kumulang <xliff:g id="TIME">^1</xliff:g> ang natitira"</string>
-    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Humigit-kumulang <xliff:g id="TIME">^1</xliff:g> ang natitira batay sa iyong paggamit"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">^1</xliff:g> ang natitira bago makumpleto ang charge"</string>
-    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">^1</xliff:g> pa"</string>
-    <string name="power_remaining_duration_only_short_enhanced" msgid="7450425624026394823">"<xliff:g id="TIME">^1</xliff:g> ang natitira batay sa iyong paggamit"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">^1</xliff:g> - humigit-kumulang <xliff:g id="TIME">^2</xliff:g> pa ang natitira"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">^1</xliff:g> - humigit-kumulang <xliff:g id="TIME">^2</xliff:g> ang natitira batay sa iyong paggamit"</string>
-    <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g> pa"</string>
+    <string name="power_remaining_duration_only" msgid="845431008899029842">"Humigit-kumulang <xliff:g id="TIME">%1$s</xliff:g> ang natitira"</string>
+    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Humigit-kumulang <xliff:g id="TIME">%1$s</xliff:g> ang natitira batay sa iyong paggamit"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> ang natitira bago makumpleto ang charge"</string>
+    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">%1$s</xliff:g> pa"</string>
+    <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Wala nang <xliff:g id="THRESHOLD">%1$s</xliff:g> ang natitira"</string>
+    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> - Wala nang <xliff:g id="THRESHOLD">%2$s</xliff:g> ang natitira"</string>
+    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g>may mahigit <xliff:g id="TIME_REMAINING">%2$s</xliff:g> pa"</string>
+    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"may mahigit <xliff:g id="TIME_REMAINING">%1$s</xliff:g> pa"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"malapit nang mag-shut down ang telepono"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"malapit nang mag-shut down ang tablet"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"malapit nang mag-shut down ang device"</string>
+    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> - humigit-kumulang <xliff:g id="TIME">%2$s</xliff:g> pa ang natitira"</string>
+    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> - humigit-kumulang <xliff:g id="TIME">%2$s</xliff:g> ang natitira batay sa iyong paggamit"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> - malapit nang mag-shut down ang telepono"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> - malapit nang mag-shut down ang tablet"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> - malapit nang mag-shut down ang device"</string>
     <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> hanggang sa makumpleto ang charge"</string>
+    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> hanggang sa makumpleto ang charge"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Hindi Kilala"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Nagcha-charge"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"nagcha-charge"</string>
@@ -409,4 +423,14 @@
     </plurals>
     <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"Dagdagan ang oras."</string>
     <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"Bawasan ang oras."</string>
+    <string name="zen_mode_enable_dialog_turn_on" msgid="8287824809739581837">"I-on"</string>
+    <string name="cancel" msgid="6859253417269739139">"Kanselahin"</string>
+    <string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"I-on ang Huwag Istorbohin"</string>
+    <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"Hindi kailanman"</string>
+    <string name="zen_interruption_level_priority" msgid="2078370238113347720">"Priyoridad lang"</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>
+    <string name="zen_alarm_warning_indef" msgid="3007988140196673193">"Hindi mo maririnig ang iyong susunod na alarm <xliff:g id="WHEN">%1$s</xliff:g> maliban na lang kung io-off mo ito bago sumapit ang oras na iyon"</string>
+    <string name="zen_alarm_warning" msgid="6236690803924413088">"Hindi mo maririnig ang iyong susunod na alarm <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template" msgid="4996153414057676512">"sa <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template_far" msgid="3779172822607461675">"sa <xliff:g id="WHEN">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-tr/arrays.xml b/packages/SettingsLib/res/values-tr/arrays.xml
index 2a70fda..acf0051 100644
--- a/packages/SettingsLib/res/values-tr/arrays.xml
+++ b/packages/SettingsLib/res/values-tr/arrays.xml
@@ -234,10 +234,6 @@
     <item msgid="7688197031296835369">"Fazla çizilen alanları göster"</item>
     <item msgid="2290859360633824369">"Alanları renk körlüğüne uygun olarak göster"</item>
   </string-array>
-  <string-array name="debug_hw_renderer_entries">
-    <item msgid="2578620445459945681">"OpenGL (Varsayılan)"</item>
-    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
-  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"Standart sınır"</item>
     <item msgid="4071574792028999443">"Arka planda işlem yok"</item>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index b570e88..1985bda 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -53,16 +53,16 @@
     <string name="bluetooth_disconnected" msgid="6557104142667339895">"Bağlantı kesildi"</string>
     <string name="bluetooth_disconnecting" msgid="8913264760027764974">"Bağlantı kesiliyor…"</string>
     <string name="bluetooth_connecting" msgid="8555009514614320497">"Bağlanıyor…"</string>
-    <string name="bluetooth_connected" msgid="6038755206916626419">"Bağlandı"</string>
+    <string name="bluetooth_connected" msgid="5427152882755735944">"<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> cihazına bağlandı"</string>
     <string name="bluetooth_pairing" msgid="1426882272690346242">"Eşleniyor…"</string>
-    <string name="bluetooth_connected_no_headset" msgid="2866994875046035609">"Bağlandı (telefon yok)"</string>
-    <string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Bağlandı (medya yok)"</string>
-    <string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Bağlı (mesaj erişimi yok)"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Bağlandı (telefon veya medya yok)"</string>
-    <string name="bluetooth_connected_battery_level" msgid="7049181126136692368">"Bağlandı, pil seviyesi <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_headset_battery_level" msgid="5504193961248406027">"Bağlandı (telefon yok), pil seviyesi <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="4751724026365870779">"Bağlandı (medya yok), pil seviyesi <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1549265779323455261">"Bağlandı (telefon veya medya yok), pil seviyesi <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset" msgid="616068069034994802">"<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> cihazına bağlandı (telefon yok)"</string>
+    <string name="bluetooth_connected_no_a2dp" msgid="3736431800395923868">"<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> cihazına bağlandı (medya yok)"</string>
+    <string name="bluetooth_connected_no_map" msgid="3200033913678466453">"<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> cihazına bağlandı (mesaj erişimi yok)"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2047403011284187056">"<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> cihazına bağlandı (telefon veya medya yok)"</string>
+    <string name="bluetooth_connected_battery_level" msgid="5162924691231307748">"<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> cihazına bağlandı, pil <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> cihazına bağlandı (telefon yok), pil <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> cihazına bağlandı (medya yok), pil <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> cihazına bağlandı (telefon veya medya yok), pil seviyesi <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Medya sesi"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"Telefon çağrıları"</string>
     <string name="bluetooth_profile_opp" msgid="9168139293654233697">"Dosya aktarımı"</string>
@@ -75,6 +75,10 @@
     <string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM Erişimi"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD ses: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD ses"</string>
+    <!-- no translation found for bluetooth_profile_hearing_aid (7999237886427812595) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (7188282786730266159) -->
+    <skip />
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Medya sesine bağlanıldı"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Telefon sesine bağlandı"</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Dosya aktarım sunucusuna bağlandı"</string>
@@ -91,6 +95,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Telefon sesi için kullan"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Dosya aktarımı için kullan"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Giriş için kullan"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (908775281788309484) -->
+    <skip />
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Eşle"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"EŞLE"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"İptal"</string>
@@ -275,7 +281,6 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"Donanım katmanı güncellemelerini göster"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Flash donanım katmanları güncellendiğinde yeşildir"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"GPU fazla çizim hatasını ayıkla"</string>
-    <string name="debug_hw_renderer" msgid="7568529019431785816">"GPU Oluşturucu\'yu ayarla"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"Donanım katmanlarını devre dışı bırak"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"Ekran oluştururken her zaman GPU\'yu kullan"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"Renk uzayını simüle et"</string>
@@ -328,9 +333,10 @@
     <item msgid="8280754435979370728">"Göze göründüğü şekilde doğal renkler"</item>
     <item msgid="5363960654009010371">"Dijital içerik için optimize edilmiş renkler"</item>
   </string-array>
-    <string name="inactive_apps_title" msgid="1317817863508274533">"Devre dışı uygulamalar"</string>
+    <string name="inactive_apps_title" msgid="9042996804461901648">"Bekleme modundaki uygulamalar"</string>
     <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"Etkin değil. Geçiş yapmak için dokunun."</string>
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"Etkin. Geçiş yapmak için dokunun."</string>
+    <string name="standby_bucket_summary" msgid="6567835350910684727">"Uygulamayı beklemeye alma durumu: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="runningservices_settings_title" msgid="8097287939865165213">"Çalışan hizmetler"</string>
     <string name="runningservices_settings_summary" msgid="854608995821032748">"Şu anda çalışan hizmetleri görüntüle ve denetle"</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView kullanımı"</string>
@@ -352,16 +358,24 @@
     <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Renk düzeltme"</string>
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Bu özellik deneyseldir ve performansı etkileyebilir."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> tarafından geçersiz kılındı"</string>
-    <string name="power_remaining_duration_only" msgid="845431008899029842">"Yaklaşık <xliff:g id="TIME">^1</xliff:g> kaldı"</string>
-    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Kullanımınıza dayalı olarak yaklaşık <xliff:g id="TIME">^1</xliff:g> kaldı"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Tam olarak şarj olmasına <xliff:g id="TIME">^1</xliff:g> kaldı"</string>
-    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">^1</xliff:g> kaldı"</string>
-    <string name="power_remaining_duration_only_short_enhanced" msgid="7450425624026394823">"Kullanımınıza dayalı olarak <xliff:g id="TIME">^1</xliff:g> kaldı"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">^1</xliff:g> - yaklaşık <xliff:g id="TIME">^2</xliff:g> kaldı"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">^1</xliff:g> - kullanımınıza dayalı olarak yaklaşık <xliff:g id="TIME">^2</xliff:g> kaldı"</string>
-    <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g> kaldı"</string>
+    <string name="power_remaining_duration_only" msgid="845431008899029842">"Yaklaşık <xliff:g id="TIME">%1$s</xliff:g> kaldı"</string>
+    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Kullanımınıza dayalı olarak yaklaşık <xliff:g id="TIME">%1$s</xliff:g> kaldı"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Tam olarak şarj olmasına <xliff:g id="TIME">%1$s</xliff:g> kaldı"</string>
+    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">%1$s</xliff:g> kaldı"</string>
+    <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"En fazla <xliff:g id="THRESHOLD">%1$s</xliff:g> kaldı"</string>
+    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> - En fazla <xliff:g id="THRESHOLD">%2$s</xliff:g> kaldı"</string>
+    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g> - en az <xliff:g id="TIME_REMAINING">%2$s</xliff:g> kaldı"</string>
+    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"en az <xliff:g id="TIME_REMAINING">%1$s</xliff:g> kaldı"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"telefon kısa süre içinde kapanabilir"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"tablet kısa süre içinde kapanabilir"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"cihaz kısa süre içinde kapanabilir"</string>
+    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> - yaklaşık <xliff:g id="TIME">%2$s</xliff:g> kaldı"</string>
+    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> - kullanımınıza dayalı olarak yaklaşık <xliff:g id="TIME">%2$s</xliff:g> kaldı"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> - telefon kısa süre içinde kapanabilir"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> - tablet kısa süre içinde kapanabilir"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> - cihaz kısa süre içinde kapanabilir"</string>
     <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> - Tam şarj olmasına <xliff:g id="TIME">^2</xliff:g> kaldı"</string>
+    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - Tam şarj olmasına <xliff:g id="TIME">%2$s</xliff:g> kaldı"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Bilinmiyor"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Şarj oluyor"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"şarj oluyor"</string>
@@ -409,4 +423,14 @@
     </plurals>
     <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"Daha uzun süre."</string>
     <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"Daha kısa süre."</string>
+    <string name="zen_mode_enable_dialog_turn_on" msgid="8287824809739581837">"Aç"</string>
+    <string name="cancel" msgid="6859253417269739139">"İptal"</string>
+    <string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"Rahatsız Etmeyin\'i açın"</string>
+    <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"Hiçbir zaman"</string>
+    <string name="zen_interruption_level_priority" msgid="2078370238113347720">"Yalnızca öncelikliler"</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>
+    <string name="zen_alarm_warning_indef" msgid="3007988140196673193">"<xliff:g id="WHEN">%1$s</xliff:g> olarak ayarlanmış bir sonraki alarmınızdan önce bu işlevi kapatmazsanız alarmı duymayacaksınız"</string>
+    <string name="zen_alarm_warning" msgid="6236690803924413088">"<xliff:g id="WHEN">%1$s</xliff:g> olarak ayarlanmış bir sonraki alarmınızı duymayacaksınız"</string>
+    <string name="alarm_template" msgid="4996153414057676512">"saat: <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template_far" msgid="3779172822607461675">"zaman: <xliff:g id="WHEN">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml
index 6b864ea..07fbb43 100644
--- a/packages/SettingsLib/res/values-uk/strings.xml
+++ b/packages/SettingsLib/res/values-uk/strings.xml
@@ -53,16 +53,16 @@
     <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>
+    <string name="bluetooth_connected" msgid="5427152882755735944">"<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> під’єднано"</string>
     <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>
+    <string name="bluetooth_connected_no_headset" msgid="616068069034994802">"<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> під’єднано (без телефона)"</string>
+    <string name="bluetooth_connected_no_a2dp" msgid="3736431800395923868">"<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> під’єдно (без медіа)"</string>
+    <string name="bluetooth_connected_no_map" msgid="3200033913678466453">"<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> під’єднано (без доступу до повідомлень)"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2047403011284187056">"<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> під’єднано (без телефона й медіа)"</string>
+    <string name="bluetooth_connected_battery_level" msgid="5162924691231307748">"<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> під’єднано, заряд акумулятора – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> під’єднано (без телефона), заряд акумулятора – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> під’єднано (без медіа), заряд акумулятора – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> під’єднано (без телефона й медіа), заряд акумулятора – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Звук медіа-файлів"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"Телефонні дзвінки"</string>
     <string name="bluetooth_profile_opp" msgid="9168139293654233697">"Передавання файлів"</string>
@@ -75,6 +75,10 @@
     <string name="bluetooth_profile_sap" msgid="5764222021851283125">"Доступ до SIM-карти"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD-аудіо: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD-аудіо"</string>
+    <!-- no translation found for bluetooth_profile_hearing_aid (7999237886427812595) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (7188282786730266159) -->
+    <skip />
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Підключено до аудіоджерела"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Підключено до звуку телеф."</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Підключ. до сервера передачі файлів"</string>
@@ -91,6 +95,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Викор. для звуку тел."</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Викор. для перед. файлів"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Викор. для введ."</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (908775281788309484) -->
+    <skip />
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Підключити"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"ПІДКЛЮЧИТИСЯ"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Скасувати"</string>
@@ -327,9 +333,10 @@
     <item msgid="8280754435979370728">"Природні кольори"</item>
     <item msgid="5363960654009010371">"Кольори для цифрового вмісту"</item>
   </string-array>
-    <string name="inactive_apps_title" msgid="1317817863508274533">"Неактивні додатки"</string>
+    <string name="inactive_apps_title" msgid="9042996804461901648">"Додатки в режимі очікування"</string>
     <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"Неактивний додаток. Торкніться, щоб активувати."</string>
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"Активний додаток. Торкніться, щоб дезактивувати."</string>
+    <string name="standby_bucket_summary" msgid="6567835350910684727">"Режим очікування: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <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 +358,24 @@
     <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>
+    <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Залишилося менше ніж <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
+    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> – залишилося менше ніж <xliff:g id="THRESHOLD">%2$s</xliff:g>"</string>
+    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g> – залишилося більше ніж <xliff:g id="TIME_REMAINING">%2$s</xliff:g>"</string>
+    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"залишилося більше ніж <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"телефон може невдовзі вимкнутися"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"планшет може невдовзі вимкнутися"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"пристрій може невдовзі вимкнутися"</string>
+    <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>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> – телефон може невдовзі вимкнутися"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> – планшет може невдовзі вимкнутися"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> – пристрій може невдовзі вимкнутися"</string>
     <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>
@@ -416,4 +431,8 @@
     <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>
+    <string name="zen_alarm_warning_indef" msgid="3007988140196673193">"Наступний сигнал <xliff:g id="WHEN">%1$s</xliff:g> не пролунає, якщо ви до того часу не вимкнете цю функцію"</string>
+    <string name="zen_alarm_warning" msgid="6236690803924413088">"Наступний сигнал <xliff:g id="WHEN">%1$s</xliff:g> не пролунає"</string>
+    <string name="alarm_template" msgid="4996153414057676512">"о <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template_far" msgid="3779172822607461675">"<xliff:g id="WHEN">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml
index 41ec303..90c7774 100644
--- a/packages/SettingsLib/res/values-ur/strings.xml
+++ b/packages/SettingsLib/res/values-ur/strings.xml
@@ -53,16 +53,16 @@
     <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>
+    <string name="bluetooth_connected" msgid="5427152882755735944">"<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> سے منسلک ہو گیا"</string>
     <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>
+    <string name="bluetooth_connected_no_headset" msgid="616068069034994802">"منسلک ہے (فون کے علاوہ)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp" msgid="3736431800395923868">"منسلک ہے (میڈیا کے علاوہ)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_map" msgid="3200033913678466453">"منسلک ہے (پیغام تک رسائی نہیں ہے)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2047403011284187056">"منسلک ہے (فون یا میڈیا کے علاوہ)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_battery_level" msgid="5162924691231307748">"منسلک ہو گیا، بٹری <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"منسلک ہے (فون کے علاوہ)، بیٹری <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"منسلک ہے (میڈیا کے علاوہ)، بیٹری <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"منسلک ہے (فون یا میڈیا کے علاوہ)، بیٹری <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"میڈيا آڈیو"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"فون کالز"</string>
     <string name="bluetooth_profile_opp" msgid="9168139293654233697">"فائل کی منتقلی"</string>
@@ -75,6 +75,10 @@
     <string name="bluetooth_profile_sap" msgid="5764222021851283125">"‏SIM رسائی"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"‏HD آڈیو: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"‏HD آڈیو"</string>
+    <!-- no translation found for bluetooth_profile_hearing_aid (7999237886427812595) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (7188282786730266159) -->
+    <skip />
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"میڈیا آڈیو سے مربوط"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"فون آڈیو سے مربوط"</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"فائل منتقلی سرور سے مربوط ہو گیا ہے"</string>
@@ -91,6 +95,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"فون آڈیو کیلئے استعمال کریں"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"فائل منتقل کرنے کیلئے استعمال کریں"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"ان پٹ کیلئے استعمال"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (908775281788309484) -->
+    <skip />
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"جوڑا بنائیں"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"جوڑا بنائیں"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"منسوخ کریں"</string>
@@ -327,9 +333,10 @@
     <item msgid="8280754435979370728">"آنکھ سے نظر آنے والے قدرتی رنگ"</item>
     <item msgid="5363960654009010371">"ڈیجیٹیل مواد کیلئے بہترین کردہ رنگ"</item>
   </string-array>
-    <string name="inactive_apps_title" msgid="1317817863508274533">"غیر فعال ایپس"</string>
+    <string name="inactive_apps_title" msgid="9042996804461901648">"اسٹینڈ بائی ایپس"</string>
     <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"غیر فعال۔ ٹوگل کرنے کیلئے تھپتھپائیں۔"</string>
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"فعال۔ ٹوگل کرنے کیلئے تھپتھپائیں۔"</string>
+    <string name="standby_bucket_summary" msgid="6567835350910684727">"ایپ اسٹینڈ بائی کی حالت:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <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 +358,24 @@
     <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>
+    <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"<xliff:g id="THRESHOLD">%1$s</xliff:g> سے کم باقی ہے"</string>
+    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="THRESHOLD">%2$s</xliff:g> سے کم باقی ہے"</string>
+    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g> <xliff:g id="TIME_REMAINING">%2$s</xliff:g> سے زیادہ باقی ہے"</string>
+    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> سے زیادہ باقی ہے"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"فون جلد ہی بند ہو سکتا ہے"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"ٹیبلیٹ جلد ہی بند ہو سکتا ہے"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"آلہ جلد ہی بند ہو سکتا ہے"</string>
+    <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>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> - فون جلد ہی بند ہو سکتا ہے"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> - ٹیبلیٹ جلد ہی بند ہو سکتا ہے"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> - آلہ جلد ہی بند ہو سکتا ہے"</string>
     <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 +429,8 @@
     <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>
+    <string name="zen_alarm_warning_indef" msgid="3007988140196673193">"آپ کو <xliff:g id="WHEN">%1$s</xliff:g> بجے اپنا اگلا الارم نہیں سنائی دے گا الّا یہ کہ آپ اسے اس وقت سے پہلے آف کر دیں"</string>
+    <string name="zen_alarm_warning" msgid="6236690803924413088">"آپ کو <xliff:g id="WHEN">%1$s</xliff:g> بجے اپنا اگلا الارم سنائی نہیں دے گا"</string>
+    <string name="alarm_template" msgid="4996153414057676512">"<xliff:g id="WHEN">%1$s</xliff:g> بجے"</string>
+    <string name="alarm_template_far" msgid="3779172822607461675">"<xliff:g id="WHEN">%1$s</xliff:g> بجے"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml
index 0a65c13..ab6a176 100644
--- a/packages/SettingsLib/res/values-uz/strings.xml
+++ b/packages/SettingsLib/res/values-uz/strings.xml
@@ -53,16 +53,16 @@
     <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>
+    <string name="bluetooth_connected" msgid="5427152882755735944">"<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> ulandi"</string>
     <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>
+    <string name="bluetooth_connected_no_headset" msgid="616068069034994802">"<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> ulandi (telefondan tashqari)"</string>
+    <string name="bluetooth_connected_no_a2dp" msgid="3736431800395923868">"<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> ulandi (mediadan tashqari)"</string>
+    <string name="bluetooth_connected_no_map" msgid="3200033913678466453">"<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> ulandi (xabarlarga ruxsatsiz)"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2047403011284187056">"<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> ulandi (telefon yoki mediadan tashqari)"</string>
+    <string name="bluetooth_connected_battery_level" msgid="5162924691231307748">"<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> ulandi, batareya quvvati: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> ulandi (telefondan tashqari), batareya quvvati: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> ulandi (mediadan 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="1163440823807659316">"<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> ulandi (telefon yoki mediadan tashqari), batareya quvvati: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <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>
@@ -75,6 +75,10 @@
     <string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM-kartaga kirish"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD audio: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD audio"</string>
+    <!-- no translation found for bluetooth_profile_hearing_aid (7999237886427812595) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (7188282786730266159) -->
+    <skip />
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Audio qurilmasiga ulangan"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Telefon karnayiga ulanildi"</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Fayl almashinish serveriga ulanildi"</string>
@@ -91,6 +95,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Dok’dan karnay sifatida foydalanish"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Fayl almashinish uchun foydalanish"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Kiritish qurilmasi sifatida foydalanish"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (908775281788309484) -->
+    <skip />
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Biriktirish"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"ULANISH"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Bekor qilish"</string>
@@ -327,9 +333,10 @@
     <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>
+    <string name="inactive_apps_title" msgid="9042996804461901648">"Kutish rejimidagi ilovalar"</string>
     <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>
+    <string name="standby_bucket_summary" msgid="6567835350910684727">"Kutish rejimi holati: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <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 +358,24 @@
     <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>
+    <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"<xliff:g id="THRESHOLD">%1$s</xliff:g>dan kamroq vaqt qoldi"</string>
+    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="THRESHOLD">%2$s</xliff:g>dan kamroq vaqt qoldi"</string>
+    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME_REMAINING">%2$s</xliff:g>dan ko‘proq vaqt qoldi"</string>
+    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g>dan ko‘proq vaqt qoldi"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"telefon tez orada o‘chib qolishi mumkin"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"planshet tez orada o‘chib qolishi mumkin"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"qurilma tez orada o‘chib qolishi mumkin"</string>
+    <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>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> – telefon tez orada o‘chib qolishi mumkin"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> – planshet tez orada o‘chib qolishi mumkin"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> – qurilma tez orada o‘chib qolishi mumkin"</string>
     <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 +429,8 @@
     <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>
+    <string name="zen_alarm_warning_indef" msgid="3007988140196673193">"Agar uni o‘chirib qo‘ymasangiz, keyingi signal (<xliff:g id="WHEN">%1$s</xliff:g>) chalinmaydi"</string>
+    <string name="zen_alarm_warning" msgid="6236690803924413088">"Keyingi signal (<xliff:g id="WHEN">%1$s</xliff:g>) chalinmaydi"</string>
+    <string name="alarm_template" msgid="4996153414057676512">"<xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template_far" msgid="3779172822607461675">"<xliff:g id="WHEN">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-vi/arrays.xml b/packages/SettingsLib/res/values-vi/arrays.xml
index 57e749f..34dd4bc 100644
--- a/packages/SettingsLib/res/values-vi/arrays.xml
+++ b/packages/SettingsLib/res/values-vi/arrays.xml
@@ -234,10 +234,6 @@
     <item msgid="7688197031296835369">"Hiển thị các vùng vẽ quá"</item>
     <item msgid="2290859360633824369">"Hiển thị các vùng mô phỏng mù màu lục"</item>
   </string-array>
-  <string-array name="debug_hw_renderer_entries">
-    <item msgid="2578620445459945681">"OpenGL (Mặc định)"</item>
-    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
-  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"Giới hạn tiêu chuẩn"</item>
     <item msgid="4071574792028999443">"Không có quá trình nền"</item>
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index 5d8f543..e37ab74 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -53,16 +53,16 @@
     <string name="bluetooth_disconnected" msgid="6557104142667339895">"Đã ngắt kết nối"</string>
     <string name="bluetooth_disconnecting" msgid="8913264760027764974">"Đang ngắt kết nối…"</string>
     <string name="bluetooth_connecting" msgid="8555009514614320497">"Đang kết nối…"</string>
-    <string name="bluetooth_connected" msgid="6038755206916626419">"Đã kết nối"</string>
+    <string name="bluetooth_connected" msgid="5427152882755735944">"Đã kết nối <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
     <string name="bluetooth_pairing" msgid="1426882272690346242">"Đang ghép nối…"</string>
-    <string name="bluetooth_connected_no_headset" msgid="2866994875046035609">"Đã kết nối (không có điện thoại)"</string>
-    <string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Đã kết nối (không có phương tiện)"</string>
-    <string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Đã kết nối (không truy cập tin nhắn)"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Đã k.nối (kg có ĐT hoặc p.tiện nào)"</string>
-    <string name="bluetooth_connected_battery_level" msgid="7049181126136692368">"Đã kết nối, mức pin <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_headset_battery_level" msgid="5504193961248406027">"Đã kết nối (không có điện thoại), mức pin <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="4751724026365870779">"Đã kết nối (không có phương tiện), mức pin <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1549265779323455261">"Đã kết nối (không có điện thoại hoặc phương tiện), mức pin <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset" msgid="616068069034994802">"Đã kết nối (không có điện thoại) <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp" msgid="3736431800395923868">"Đã kết nối (không có phương tiện) <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_map" msgid="3200033913678466453">"Đã kết nối (không có quyền truy cập tin nhắn) <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2047403011284187056">"Đã kết nối (không có điện thoại hoặc phương tiện) <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_battery_level" msgid="5162924691231307748">"Đã kết nối, mức pin <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"Đã kết nối (không có điện thoại), mức pin <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"Đã kết nối (không có phương tiện), mức pin <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"Đã kết nối (không có điện thoại hoặc phương tiện), mức pin <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Âm thanh của phương tiện"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"Cuộc gọi điện thoại"</string>
     <string name="bluetooth_profile_opp" msgid="9168139293654233697">"Chuyển tệp"</string>
@@ -75,6 +75,10 @@
     <string name="bluetooth_profile_sap" msgid="5764222021851283125">"Quyền truy cập SIM"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"Âm thanh HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"Âm thanh HD"</string>
+    <!-- no translation found for bluetooth_profile_hearing_aid (7999237886427812595) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (7188282786730266159) -->
+    <skip />
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Đã kết nối với âm thanh phương tiện"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Đã kết nối với âm thanh điện thoại"</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Đã kết nối với máy chủ chuyển tệp"</string>
@@ -91,6 +95,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Sử dụng cho âm thanh điện thoại"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Sử dụng để chuyển tệp"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Sử dụng để nhập"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (908775281788309484) -->
+    <skip />
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Ghép nối"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"GHÉP NỐI"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Hủy"</string>
@@ -275,7 +281,6 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"Hiện c.nhật lớp phần cứng"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Lớp phần cứng flash có màu xanh khi chúng cập nhật"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"Hiển thị mức vẽ quá GPU"</string>
-    <string name="debug_hw_renderer" msgid="7568529019431785816">"Đặt kết xuất đồ họa GPU"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"Vô hiệu hóa các lớp phủ HW"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"Luôn sử dụng GPU để tổng hợp màn hình"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"Mô phỏng không gian màu"</string>
@@ -328,9 +333,10 @@
     <item msgid="8280754435979370728">"Màu tự nhiên giống như nhìn bằng mắt"</item>
     <item msgid="5363960654009010371">"Màu được tối ưu hóa cho nội dung kỹ thuật số"</item>
   </string-array>
-    <string name="inactive_apps_title" msgid="1317817863508274533">"Ứng dụng không hoạt động"</string>
+    <string name="inactive_apps_title" msgid="9042996804461901648">"Ứng dụng ở chế độ chờ"</string>
     <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"Không hoạt động. Nhấn để chuyển đổi."</string>
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"Hiện hoạt. Nhấn để chuyển đổi."</string>
+    <string name="standby_bucket_summary" msgid="6567835350910684727">"Trạng thái chờ ứng dụng:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="runningservices_settings_title" msgid="8097287939865165213">"Các dịch vụ đang hoạt động"</string>
     <string name="runningservices_settings_summary" msgid="854608995821032748">"Xem và kiểm soát các dịch vụ hiện đang hoạt động"</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"Triển khai WebView"</string>
@@ -352,16 +358,24 @@
     <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Sửa màu"</string>
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Tính năng này là tính năng thử nghiệm và có thể ảnh hưởng đến hoạt động."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Bị ghi đè bởi <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only" msgid="845431008899029842">"Còn khoảng <xliff:g id="TIME">^1</xliff:g>"</string>
-    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Còn khoảng <xliff:g id="TIME">^1</xliff:g> dựa trên mức sử dụng của bạn"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Còn <xliff:g id="TIME">^1</xliff:g> cho tới khi được sạc đầy"</string>
-    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Còn lại <xliff:g id="TIME">^1</xliff:g>"</string>
-    <string name="power_remaining_duration_only_short_enhanced" msgid="7450425624026394823">"Còn <xliff:g id="TIME">^1</xliff:g> dựa trên mức sử dụng của bạn"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">^1</xliff:g> - còn khoảng <xliff:g id="TIME">^2</xliff:g>"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">^1</xliff:g> - còn khoảng <xliff:g id="TIME">^2</xliff:g> dựa trên mức sử dụng của bạn"</string>
-    <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> - còn lại <xliff:g id="TIME">^2</xliff:g>"</string>
+    <string name="power_remaining_duration_only" msgid="845431008899029842">"Còn khoảng <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Còn khoảng <xliff:g id="TIME">%1$s</xliff:g> dựa trên mức sử dụng của bạn"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Còn <xliff:g id="TIME">%1$s</xliff:g> cho tới khi được sạc đầy"</string>
+    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Còn lại <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Còn lại không đến <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
+    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> - Còn lại không đến <xliff:g id="THRESHOLD">%2$s</xliff:g>"</string>
+    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g> còn lại hơn <xliff:g id="TIME_REMAINING">%2$s</xliff:g>"</string>
+    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"còn lại hơn <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"điện thoại có thể sắp tắt"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"máy tính bảng có thể sắp tắt"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"thiết bị có thể sắp tắt"</string>
+    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> - còn khoảng <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> - còn khoảng <xliff:g id="TIME">%2$s</xliff:g> dựa trên mức sử dụng của bạn"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> - điện thoại có thể sắp tắt"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> - máy tính bảng có thể sắp tắt"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> - thiết bị có thể sắp tắt"</string>
     <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> cho tới khi được sạc đầy"</string>
+    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> cho tới khi được sạc đầy"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Không xác định"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Đang sạc"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"đang sạc"</string>
@@ -409,4 +423,14 @@
     </plurals>
     <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"Nhiều thời gian hơn."</string>
     <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"Ít thời gian hơn."</string>
+    <string name="zen_mode_enable_dialog_turn_on" msgid="8287824809739581837">"Bật"</string>
+    <string name="cancel" msgid="6859253417269739139">"Hủy"</string>
+    <string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"Bật chế độ Không làm phiền"</string>
+    <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"Không bao giờ"</string>
+    <string name="zen_interruption_level_priority" msgid="2078370238113347720">"Chỉ ưu tiên"</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>
+    <string name="zen_alarm_warning_indef" msgid="3007988140196673193">"Bạn sẽ không nghe thấy báo thức tiếp theo lúc <xliff:g id="WHEN">%1$s</xliff:g> của mình trừ khi bạn tắt chức năng này trước"</string>
+    <string name="zen_alarm_warning" msgid="6236690803924413088">"Bạn sẽ không nghe thấy báo thức tiếp theo lúc <xliff:g id="WHEN">%1$s</xliff:g> của mình"</string>
+    <string name="alarm_template" msgid="4996153414057676512">"lúc <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template_far" msgid="3779172822607461675">"vào <xliff:g id="WHEN">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index 7bd7e7d..89edf54 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -53,16 +53,16 @@
     <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>
+    <string name="bluetooth_connected" msgid="5427152882755735944">"已连接<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
     <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>
+    <string name="bluetooth_connected_no_headset" msgid="616068069034994802">"已连接(无手机信号)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp" msgid="3736431800395923868">"已连接(无媒体信号)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_map" msgid="3200033913678466453">"已连接(无消息访问权限)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2047403011284187056">"已连接(无手机或媒体信号)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_battery_level" msgid="5162924691231307748">"已连接,电量为 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"已连接(无手机信号),电量为 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"已连接(无媒体信号),电量为 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"已连接(无手机或媒体信号),电量为 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"媒体音频"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"通话"</string>
     <string name="bluetooth_profile_opp" msgid="9168139293654233697">"文件传输"</string>
@@ -75,6 +75,10 @@
     <string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM 卡存取权限"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD 音频:<xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD 音频"</string>
+    <!-- no translation found for bluetooth_profile_hearing_aid (7999237886427812595) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (7188282786730266159) -->
+    <skip />
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"已连接到媒体音频"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"已连接到手机音频"</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"已连接到文件传输服务器"</string>
@@ -91,6 +95,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"用于手机音频"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"用于文件传输"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"用于输入"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (908775281788309484) -->
+    <skip />
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"配对"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"配对"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"取消"</string>
@@ -327,9 +333,10 @@
     <item msgid="8280754435979370728">"肉眼所看到的自然颜色"</item>
     <item msgid="5363960654009010371">"针对数字内容优化的颜色"</item>
   </string-array>
-    <string name="inactive_apps_title" msgid="1317817863508274533">"未启用的应用"</string>
+    <string name="inactive_apps_title" msgid="9042996804461901648">"待机应用"</string>
     <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"未启用。点按即可切换。"</string>
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"已启用。点按即可切换。"</string>
+    <string name="standby_bucket_summary" msgid="6567835350910684727">"应用待机状态:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <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 +358,24 @@
     <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>
+    <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"剩余电池续航时间不到 <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
+    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> - 剩余电池续航时间不到 <xliff:g id="THRESHOLD">%2$s</xliff:g>"</string>
+    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g> - 剩余电池续航时间超过 <xliff:g id="TIME_REMAINING">%2$s</xliff:g>"</string>
+    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"剩余电池续航时间超过 <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"手机可能即将关机"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"平板电脑可能即将关机"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"设备可能即将关机"</string>
+    <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>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> - 手机可能即将关机"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> - 平板电脑可能即将关机"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> - 设备可能即将关机"</string>
     <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 +429,8 @@
     <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>
+    <string name="zen_alarm_warning_indef" msgid="3007988140196673193">"您将不会听到下一个<xliff:g id="WHEN">%1$s</xliff:g> 的闹钟响铃,除非您在该时间之前关闭这项功能"</string>
+    <string name="zen_alarm_warning" msgid="6236690803924413088">"您将不会听到下一个<xliff:g id="WHEN">%1$s</xliff:g> 的闹钟响铃"</string>
+    <string name="alarm_template" msgid="4996153414057676512">"时间:<xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template_far" msgid="3779172822607461675">"时间:<xliff:g id="WHEN">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-zh-rHK/arrays.xml b/packages/SettingsLib/res/values-zh-rHK/arrays.xml
index 85c151e..5e24e2a 100644
--- a/packages/SettingsLib/res/values-zh-rHK/arrays.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/arrays.xml
@@ -234,10 +234,6 @@
     <item msgid="7688197031296835369">"顯示過度繪製區域"</item>
     <item msgid="2290859360633824369">"顯示綠色弱視區域"</item>
   </string-array>
-  <string-array name="debug_hw_renderer_entries">
-    <item msgid="2578620445459945681">"OpenGL (預設)"</item>
-    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
-  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"標準限制"</item>
     <item msgid="4071574792028999443">"無背景處理程序"</item>
diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml
index 695990d..9b0ec86 100644
--- a/packages/SettingsLib/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml
@@ -53,16 +53,16 @@
     <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>
+    <string name="bluetooth_connected" msgid="5427152882755735944">"已連接「<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>」"</string>
     <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>
+    <string name="bluetooth_connected_no_headset" msgid="616068069034994802">"已連接「<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>」(無手機音訊)"</string>
+    <string name="bluetooth_connected_no_a2dp" msgid="3736431800395923868">"已連接「<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>」(無媒體音訊)"</string>
+    <string name="bluetooth_connected_no_map" msgid="3200033913678466453">"已連接「<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>」(無訊息存取權)"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2047403011284187056">"已連接「<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>」(無手機或媒體音訊)"</string>
+    <string name="bluetooth_connected_battery_level" msgid="5162924691231307748">"已連接,電量為 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"已連接 (無手機音訊),電量為 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"已連接 (無媒體音訊),電量為 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"已連接 (無手機或媒體音訊),電量為 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"媒體音效"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"通話"</string>
     <string name="bluetooth_profile_opp" msgid="9168139293654233697">"檔案傳輸"</string>
@@ -75,6 +75,10 @@
     <string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM 卡存取"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"高清音訊:<xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"高清音訊"</string>
+    <!-- no translation found for bluetooth_profile_hearing_aid (7999237886427812595) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (7188282786730266159) -->
+    <skip />
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"已連接媒體音頻裝置"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"已連接手機耳機"</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"已連線至檔案傳輸伺服器"</string>
@@ -91,6 +95,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"用於手機音效"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"用於傳輸檔案"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"用於輸入"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (908775281788309484) -->
+    <skip />
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"配對"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"配對"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"取消"</string>
@@ -275,7 +281,6 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"顯示硬件層更新"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"在硬件層更新時閃動綠燈"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"GPU 透支偵錯"</string>
-    <string name="debug_hw_renderer" msgid="7568529019431785816">"設定 GPU 轉譯器"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"停用 HW 重疊效果"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"永遠使用 GPU 進行畫面合成"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"模擬色彩空間"</string>
@@ -328,9 +333,10 @@
     <item msgid="8280754435979370728">"如眼前所見的自然顏色"</item>
     <item msgid="5363960654009010371">"優化作數碼內容使用的顏色"</item>
   </string-array>
-    <string name="inactive_apps_title" msgid="1317817863508274533">"已暫停的應用程式"</string>
+    <string name="inactive_apps_title" msgid="9042996804461901648">"備用應用程式"</string>
     <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"未啟用。輕按即可切換。"</string>
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"已啟用。輕按即可切換。"</string>
+    <string name="standby_bucket_summary" msgid="6567835350910684727">"備用應用程式狀態:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <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>
@@ -352,16 +358,24 @@
     <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>
+    <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"剩餘電量時間少於 <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
+    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> - 剩餘電量時間少於 <xliff:g id="THRESHOLD">%2$s</xliff:g>"</string>
+    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g> - 剩餘電量時間超過 <xliff:g id="TIME_REMAINING">%2$s</xliff:g>"</string>
+    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"剩餘電量時間超過 <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"手機可能即將關機"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"平板電腦可能即將關機"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"裝置可能即將關機"</string>
+    <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>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> - 手機可能即將關機"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> - 平板電腦可能即將關機"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> - 裝置可能即將關機"</string>
     <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>
@@ -409,4 +423,14 @@
     </plurals>
     <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"增加時間。"</string>
     <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"減少時間。"</string>
+    <string name="zen_mode_enable_dialog_turn_on" msgid="8287824809739581837">"開啟"</string>
+    <string name="cancel" msgid="6859253417269739139">"取消"</string>
+    <string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"開啟「請勿騷擾」模式"</string>
+    <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>
+    <string name="zen_alarm_warning_indef" msgid="3007988140196673193">"除非您預先關閉此功能,否則您不會聽到下一個<xliff:g id="WHEN">%1$s</xliff:g>的鬧鐘響鬧"</string>
+    <string name="zen_alarm_warning" msgid="6236690803924413088">"您不會聽到下一個<xliff:g id="WHEN">%1$s</xliff:g>的鬧鐘響鬧"</string>
+    <string name="alarm_template" msgid="4996153414057676512">"時間:<xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template_far" msgid="3779172822607461675">"時間:<xliff:g id="WHEN">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index 4e9e4a8..1d6b4b9 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -53,16 +53,16 @@
     <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>
+    <string name="bluetooth_connected" msgid="5427152882755735944">"已連線到「<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>」"</string>
     <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>
+    <string name="bluetooth_connected_no_headset" msgid="616068069034994802">"已連線到「<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>」(無手機音訊)"</string>
+    <string name="bluetooth_connected_no_a2dp" msgid="3736431800395923868">"已連線到「<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>」(無媒體音訊)"</string>
+    <string name="bluetooth_connected_no_map" msgid="3200033913678466453">"已連線到「<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>」(無訊息存取權)"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2047403011284187056">"已連線到「<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>」(無手機或媒體音訊)"</string>
+    <string name="bluetooth_connected_battery_level" msgid="5162924691231307748">"已連線,電量為 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"已連線 (無手機音訊),電量為 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"已連線 (無媒體音訊),電量為 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"已連線 (無手機或媒體音訊),電量為 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"媒體音訊"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"通話"</string>
     <string name="bluetooth_profile_opp" msgid="9168139293654233697">"檔案傳輸"</string>
@@ -75,6 +75,10 @@
     <string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM 卡存取權"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD 高解析音訊:<xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD 高解析音訊"</string>
+    <!-- no translation found for bluetooth_profile_hearing_aid (7999237886427812595) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (7188282786730266159) -->
+    <skip />
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"連接至媒體音訊"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"連接至電話音訊"</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"已連線到檔案傳輸伺服器"</string>
@@ -91,6 +95,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"用於電話音訊"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"用於傳輸檔案"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"用於輸入"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (908775281788309484) -->
+    <skip />
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"配對"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"配對"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"取消"</string>
@@ -327,9 +333,10 @@
     <item msgid="8280754435979370728">"眼睛所見的自然色彩"</item>
     <item msgid="5363960654009010371">"針對數位內容最佳化的色彩"</item>
   </string-array>
-    <string name="inactive_apps_title" msgid="1317817863508274533">"未啟用的應用程式"</string>
+    <string name="inactive_apps_title" msgid="9042996804461901648">"待命應用程式"</string>
     <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"未啟用。輕觸即可切換。"</string>
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"已啟用。輕觸即可切換。"</string>
+    <string name="standby_bucket_summary" msgid="6567835350910684727">"應用程式待命狀態:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <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 +358,24 @@
     <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>
+    <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"電池可用時間不到 <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
+    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> - 電池可用時間不到 <xliff:g id="THRESHOLD">%2$s</xliff:g>"</string>
+    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g> - 電池可用時間超過 <xliff:g id="TIME_REMAINING">%2$s</xliff:g>"</string>
+    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"電池可用時間超過 <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"手機可能即將關機"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"平板電腦可能即將關機"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"裝置可能即將關機"</string>
+    <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>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> - 手機可能即將關機"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> - 平板電腦可能即將關機"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> - 裝置可能即將關機"</string>
     <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 +429,8 @@
     <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>
+    <string name="zen_alarm_warning_indef" msgid="3007988140196673193">"你不會聽到下一個<xliff:g id="WHEN">%1$s</xliff:g> 的鬧鐘,除非你預先關閉這項功能"</string>
+    <string name="zen_alarm_warning" msgid="6236690803924413088">"你不會聽到下一個<xliff:g id="WHEN">%1$s</xliff:g> 的鬧鐘"</string>
+    <string name="alarm_template" msgid="4996153414057676512">"時間:<xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template_far" msgid="3779172822607461675">"時間:<xliff:g id="WHEN">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml
index 4f7f419..1b04f4b 100644
--- a/packages/SettingsLib/res/values-zu/strings.xml
+++ b/packages/SettingsLib/res/values-zu/strings.xml
@@ -53,16 +53,16 @@
     <string name="bluetooth_disconnected" msgid="6557104142667339895">"Ayixhunyiwe"</string>
     <string name="bluetooth_disconnecting" msgid="8913264760027764974">"Inqamula uxhumano kwi-inthanethi..."</string>
     <string name="bluetooth_connecting" msgid="8555009514614320497">"Iyaxhuma..."</string>
-    <string name="bluetooth_connected" msgid="6038755206916626419">"Ixhunyiwe"</string>
+    <string name="bluetooth_connected" msgid="5427152882755735944">"Ixhunyiwe<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
     <string name="bluetooth_pairing" msgid="1426882272690346242">"Iyabhangqa..."</string>
-    <string name="bluetooth_connected_no_headset" msgid="2866994875046035609">"Ixhunyiwe (ayikho ifoni)"</string>
-    <string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Ixhunyiwe (ayikho imidiya)"</string>
-    <string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Kuxhunyiwe (akukho ukufinyelela umlayezo)"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Ixhunyiwe (ayikho ifoni noma imidiya)"</string>
-    <string name="bluetooth_connected_battery_level" msgid="7049181126136692368">"Kuxhunyiwe, ibhethri elingu-<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_headset_battery_level" msgid="5504193961248406027">"Kuxhunyiwe (ayikho ifoni), ibhethri lingu-<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="4751724026365870779">"Kuxhunyiwe (ayikho imidiya), ibhethri lingu-<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1549265779323455261">"Kuxhunyiwe (ayikho ifoni noma imidiya), ibhethri lingu-<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset" msgid="616068069034994802">"Ixhunyiwe (ayikho ifoni)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp" msgid="3736431800395923868">"Ixhunyiwe (ayikho imidiya)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_map" msgid="3200033913678466453">"Ixhunyiwe (akukho ukufinyelela kumlayezo)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2047403011284187056">"Ixhunyiwe (ayikho ifoni noma imidiya)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_battery_level" msgid="5162924691231307748">"Ixhunyiwe, ibhethri ngu-<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"Ixhunyiwe (ayikho ifoni), ibhethri ngu-<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"Ixhunyiwe (ayikho imidiya), ibhethri iku-<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"Ixhunyiwe (ayikho ifoni noma imidiya), ibhethri ngu-<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Umsindo wemidiya"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"Amakholi efoni"</string>
     <string name="bluetooth_profile_opp" msgid="9168139293654233697">"Dlulisa ifayela"</string>
@@ -75,6 +75,10 @@
     <string name="bluetooth_profile_sap" msgid="5764222021851283125">"Ukufinyelela kwe-SIM"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"Umsindo we-HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"Umsindo we-HD"</string>
+    <!-- no translation found for bluetooth_profile_hearing_aid (7999237886427812595) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (7188282786730266159) -->
+    <skip />
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Ixhume emsindweni wemidiya"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Ixhunywe kumsindo wefoni"</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Ixhunywe kwiseva yokudlulisa ifayela"</string>
@@ -91,6 +95,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Sebenziselwa umsindo wefoni"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Sebenziselwa ukudlulisa ifayela"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Isetshenziselwa okufakwayo"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (908775281788309484) -->
+    <skip />
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Bhangqa"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"BHANQA"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Khansela"</string>
@@ -327,9 +333,10 @@
     <item msgid="8280754435979370728">"Imibala yemvelo njengoba ibonwa yilihlo"</item>
     <item msgid="5363960654009010371">"Imibala elungiselelwe yokuqukethwe kwedijithali"</item>
   </string-array>
-    <string name="inactive_apps_title" msgid="1317817863508274533">"Izinhlelo zokusebenza ezingasebenzi"</string>
+    <string name="inactive_apps_title" msgid="9042996804461901648">"Izinhlelo zokusebenza zokulinda"</string>
     <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"Akusebenzi. Thepha ukuze ushintshe."</string>
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"Kuyasebenza. Thepha ukuze ushintshe."</string>
+    <string name="standby_bucket_summary" msgid="6567835350910684727">"Isimo sokulinda kohlelo lokusebenza:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="runningservices_settings_title" msgid="8097287939865165213">"Amasevisi asebenzayo"</string>
     <string name="runningservices_settings_summary" msgid="854608995821032748">"Buka futhi ulawule amasevisi  asebenzayo okwamanje"</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"Ukufakwa ke-WebView"</string>
@@ -351,16 +358,24 @@
     <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Ukulungiswa kombala"</string>
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Lesi sici esesilingo futhi singathinta ukusebenza."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Igitshezwe ngaphezulu yi-<xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only" msgid="845431008899029842">"Cishe u-<xliff:g id="TIME">^1</xliff:g> osele"</string>
-    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Cishe kusele okungu-<xliff:g id="TIME">^1</xliff:g> kusukela ekusetshenzisweni kwakho"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">^1</xliff:g> kushiywe ishaja"</string>
-    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">^1</xliff:g> esisele"</string>
-    <string name="power_remaining_duration_only_short_enhanced" msgid="7450425624026394823">"<xliff:g id="TIME">^1</xliff:g> esele kusukela ekusetshenzisweni kwakho"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">^1</xliff:g> - cishe ngu-<xliff:g id="TIME">^2</xliff:g> osele"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">^1</xliff:g> - cishe ngu-<xliff:g id="TIME">^2</xliff:g> osele kusukela ekusetshenzisweni kwakho"</string>
-    <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g> okusele"</string>
+    <string name="power_remaining_duration_only" msgid="845431008899029842">"Cishe u-<xliff:g id="TIME">%1$s</xliff:g> osele"</string>
+    <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Cishe kusele okungu-<xliff:g id="TIME">%1$s</xliff:g> kusukela ekusetshenzisweni kwakho"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> kushiywe ishaja"</string>
+    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">%1$s</xliff:g> esisele"</string>
+    <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Kusele okungaphansi kunokungu-<xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
+    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> - Kusele okungaphansi kokungu<xliff:g id="THRESHOLD">%2$s</xliff:g>"</string>
+    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g>ngaphezu kokungu-<xliff:g id="TIME_REMAINING">%2$s</xliff:g> okusele"</string>
+    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"ngaphezulu kokungu-<xliff:g id="TIME_REMAINING">%1$s</xliff:g> okusele"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"ifoni ingacisha maduze"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"ithebulethi ingacisha maduze"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"idivayisi ingacisha maduze"</string>
+    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> - cishe ngu-<xliff:g id="TIME">%2$s</xliff:g> osele"</string>
+    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> - cishe ngu-<xliff:g id="TIME">%2$s</xliff:g> osele kusukela ekusetshenzisweni kwakho"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> - ifoni ingacisha maduze"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> - ithebulethi ingacisha maduze"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> - idivayisi ingacisha maduze"</string>
     <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> kuze ligcwale ngokuphelele"</string>
+    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> kuze ligcwale ngokuphelele"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Akwaziwa"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Iyashaja"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"iyashaja"</string>
@@ -414,4 +429,8 @@
     <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"Soze"</string>
     <string name="zen_interruption_level_priority" msgid="2078370238113347720">"Okubalulekile kuphela"</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>
+    <string name="zen_alarm_warning_indef" msgid="3007988140196673193">"Ngeke uzwe i-alamu yakho elandelayo ngo-<xliff:g id="WHEN">%1$s</xliff:g> ngaphandle kokuthi uvale lokhu ngaphambi kwalokho"</string>
+    <string name="zen_alarm_warning" msgid="6236690803924413088">"Ngeke uzwe i-alamu yakho elandelayo ngo-<xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template" msgid="4996153414057676512">"ngo-<xliff:g id="WHEN">%1$s</xliff:g>"</string>
+    <string name="alarm_template_far" msgid="3779172822607461675">"nge-<xliff:g id="WHEN">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values/arrays.xml b/packages/SettingsLib/res/values/arrays.xml
index c926e1f..c1aa2dc 100644
--- a/packages/SettingsLib/res/values/arrays.xml
+++ b/packages/SettingsLib/res/values/arrays.xml
@@ -250,6 +250,19 @@
         <item>Best Effort (Adaptive Bit Rate)</item>
     </string-array>
 
+    <!-- TODO: Enable for translation per b/73007419 -->
+    <!-- Summaries for Bluetooth Audio Active Device status. [CHAR LIMIT=50]-->
+    <string-array name="bluetooth_audio_active_device_summaries" translatable="false" >
+        <!-- Status message when the device is not Active. -->
+        <item></item>
+        <!-- Status message when the device is Active for Media and Phone. -->
+        <item>, active</item>
+        <!-- Status message when the device is Active for Media only. -->
+        <item>, active(media)</item>
+        <!-- Status message when the device is Active for Phone only. -->
+        <item>, active(phone)</item>
+    </string-array>
+
     <!-- Titles for logd limit size selection preference. [CHAR LIMIT=14] -->
     <string-array name="select_logd_size_titles">
         <item>Off</item>
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/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index 486a9bb..c78f454 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -128,27 +128,27 @@
      <!-- Bluetooth settings.  Message when connecting to a device -->
     <string name="bluetooth_connecting">Connecting\u2026</string>
     <!-- Bluetooth settings.  Message when connected to a device. [CHAR LIMIT=40] -->
-    <string name="bluetooth_connected">Connected</string>
+    <string name="bluetooth_connected">Connected<xliff:g id="active_device">%1$s</xliff:g></string>
     <!--Bluetooth settings screen, summary text under individual Bluetooth devices when pairing -->
     <string name="bluetooth_pairing">Pairing\u2026</string>
 
     <!-- Bluetooth settings.  Message when connected to a device, except for phone audio. [CHAR LIMIT=40] -->
-    <string name="bluetooth_connected_no_headset">Connected (no phone)</string>
+    <string name="bluetooth_connected_no_headset">Connected (no phone)<xliff:g id="active_device">%1$s</xliff:g></string>
     <!-- Bluetooth settings.  Message when connected to a device, except for media audio. [CHAR LIMIT=40] -->
-    <string name="bluetooth_connected_no_a2dp">Connected (no media)</string>
+    <string name="bluetooth_connected_no_a2dp">Connected (no media)<xliff:g id="active_device">%1$s</xliff:g></string>
     <!-- Bluetooth settings.  Message when connected to a device, except for map. [CHAR LIMIT=40] -->
-    <string name="bluetooth_connected_no_map">Connected (no message access)</string>
+    <string name="bluetooth_connected_no_map">Connected (no message access)<xliff:g id="active_device">%1$s</xliff:g></string>
     <!-- Bluetooth settings.  Message when connected to a device, except for phone/media audio. [CHAR LIMIT=40] -->
-    <string name="bluetooth_connected_no_headset_no_a2dp">Connected (no phone or media)</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp">Connected (no phone or media)<xliff:g id="active_device">%1$s</xliff:g></string>
 
     <!-- Bluetooth settings.  Message when connected to a device, showing remote device battery level. [CHAR LIMIT=NONE] -->
-    <string name="bluetooth_connected_battery_level">Connected, battery <xliff:g id="battery_level_as_percentage">%1$s</xliff:g></string>
+    <string name="bluetooth_connected_battery_level">Connected, battery <xliff:g id="battery_level_as_percentage">%1$s</xliff:g><xliff:g id="active_device">%2$s</xliff:g></string>
     <!-- Bluetooth settings.  Message when connected to a device, except for phone audio, showing remote device battery level. [CHAR LIMIT=NONE] -->
-    <string name="bluetooth_connected_no_headset_battery_level">Connected (no phone), battery <xliff:g id="battery_level_as_percentage">%1$s</xliff:g></string>
+    <string name="bluetooth_connected_no_headset_battery_level">Connected (no phone), battery <xliff:g id="battery_level_as_percentage">%1$s</xliff:g><xliff:g id="active_device">%2$s</xliff:g></string>
     <!-- Bluetooth settings.  Message when connected to a device, except for media audio, showing remote device battery level. [CHAR LIMIT=NONE] -->
-    <string name="bluetooth_connected_no_a2dp_battery_level">Connected (no media), battery <xliff:g id="battery_level_as_percentage">%1$s</xliff:g></string>
+    <string name="bluetooth_connected_no_a2dp_battery_level">Connected (no media), battery <xliff:g id="battery_level_as_percentage">%1$s</xliff:g><xliff:g id="active_device">%2$s</xliff:g></string>
     <!-- Bluetooth settings.  Message when connected to a device, except for phone/media audio, showing remote device battery level. [CHAR LIMIT=NONE] -->
-    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level">Connected (no phone or media), battery <xliff:g id="battery_level_as_percentage">%1$s</xliff:g></string>
+    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level">Connected (no phone or media), battery <xliff:g id="battery_level_as_percentage">%1$s</xliff:g><xliff:g id="active_device">%2$s</xliff:g></string>
 
     <!-- Bluetooth settings.  The user-visible string that is used whenever referring to the A2DP profile. -->
     <string name="bluetooth_profile_a2dp">Media audio</string>
@@ -177,6 +177,11 @@
     <!-- Bluetooth settings. Similar to bluetooth_profile_a2dp_high_quality, but used when the device supports high quality audio but we don't know which codec that will be used. -->
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec">HD audio</string>
 
+    <!-- Bluetooth settings.  The user-visible string that is used whenever referring to the Hearing Aid profile. -->
+    <string name="bluetooth_profile_hearing_aid">Hearing Aid</string>
+    <!-- Bluetooth settings.  Connection options screen.  The summary for the Hearing Aid checkbox preference when Hearing Aid is connected. -->
+    <string name="bluetooth_hearing_aid_profile_summary_connected">Connected to Hearing Aid</string>
+
     <!-- Bluetooth settings.  Connection options screen.  The summary for the A2DP checkbox preference when A2DP is connected. -->
     <string name="bluetooth_a2dp_profile_summary_connected">Connected to media audio</string>
     <!-- Bluetooth settings.  Connection options screen.  The summary for the headset checkbox preference when headset is connected. -->
@@ -214,6 +219,8 @@
          for the HID checkbox preference that describes how checking it
          will set the HID profile as preferred. -->
     <string name="bluetooth_hid_profile_summary_use_for">Use for input</string>
+    <!-- Bluetooth settings.  Connection options screen.  The summary for the Hearing Aid checkbox preference that describes how checking it will set the Hearing Aid profile as preferred. -->
+    <string name="bluetooth_hearing_aid_profile_summary_use_for">Use for Hearing Aid</string>
 
     <!-- Button text for accepting an incoming pairing request. [CHAR LIMIT=20] -->
     <string name="bluetooth_pairing_accept">Pair</string>
@@ -805,13 +812,17 @@
         <item>Colors optimized for digital content</item>
     </string-array>
 
-    <!-- Settings item title for inactive apps [CHAR LIMIT=35] -->
-    <string name="inactive_apps_title">Inactive apps</string>
+    <!-- Settings item title for apps in standby (limiting background activity) [CHAR LIMIT=35] -->
+    <string name="inactive_apps_title">Standby apps</string>
     <!-- Settings item summary for inactive app [CHAR LIMIT=100] -->
     <string name="inactive_app_inactive_summary">Inactive. Tap to toggle.</string>
     <!-- Settings item summary for active app [CHAR LIMIT=100] -->
     <string name="inactive_app_active_summary">Active. Tap to toggle.</string>
 
+    <!-- Settings item summary for standby bucket value of an app. [CHAR LIMIT=100] -->
+    <string name="standby_bucket_summary">App standby
+        state:<xliff:g id="bucket"> %s</xliff:g></string>
+
     <!-- Services settings screen, setting option name for the user to go to the screen to view running services -->
     <string name="runningservices_settings_title">Running services</string>
     <!-- Services settings screen, setting option summary for the user to go to the screen to view running services  -->
@@ -865,30 +876,49 @@
     <!-- Summary shown for color space correction preference when its value is overridden by another preference [CHAR LIMIT=35] -->
     <string name="daltonizer_type_overridden">Overridden by <xliff:g id="title" example="Simulate color space">%1$s</xliff:g></string>
 
-    <!-- [CHAR_LIMIT=40] Label for estimated remaining duration of battery discharging -->
-    <string name="power_remaining_duration_only">About <xliff:g id="time">^1</xliff:g> left</string>
-    <!-- [CHAR_LIMIT=60] Label for estimated remaining duration of battery discharging -->
-    <string name="power_remaining_duration_only_enhanced">About <xliff:g id="time">^1</xliff:g> left based on your usage</string>
-    <!-- [CHAR_LIMIT=40] Label for estimated remaining duration of battery charging -->
-    <string name="power_remaining_charging_duration_only"><xliff:g id="time">^1</xliff:g> left until fully charged</string>
+  <!-- [CHAR_LIMIT=40] Label for estimated remaining duration of battery discharging -->
+  <string name="power_remaining_duration_only">About <xliff:g id="time">%1$s</xliff:g> left</string>
+  <!-- [CHAR_LIMIT=60] Label for estimated remaining duration of battery discharging -->
+  <string name="power_remaining_duration_only_enhanced">About <xliff:g id="time">%1$s</xliff:g> left based on your usage</string>
+  <!-- [CHAR_LIMIT=40] Label for estimated remaining duration of battery charging -->
+  <string name="power_remaining_charging_duration_only"><xliff:g id="time">%1$s</xliff:g> left until fully charged</string>
 
-    <!-- [CHAR_LIMIT=40] Short label for estimated remaining duration of battery charging/discharging -->
-    <string name="power_remaining_duration_only_short"><xliff:g id="time">^1</xliff:g> left</string>
-    <!-- [CHAR_LIMIT=60] Short label for estimated remaining duration of battery charging/discharging -->
-    <string name="power_remaining_duration_only_short_enhanced"><xliff:g id="time">^1</xliff:g> left based on your usage</string>
+  <!-- [CHAR_LIMIT=40] Short label for estimated remaining duration of battery charging/discharging -->
+  <string name="power_remaining_duration_only_short"><xliff:g id="time">%1$s</xliff:g> left</string>
 
-    <!-- [CHAR_LIMIT=40] Label for battery level chart when discharging with duration -->
-    <string name="power_discharging_duration"><xliff:g id="level">^1</xliff:g> - about <xliff:g id="time">^2</xliff:g> left</string>
-    <!-- [CHAR_LIMIT=60] Label for battery level chart when discharging with duration and using enhanced estimate -->
-    <string name="power_discharging_duration_enhanced"><xliff:g id="level">^1</xliff:g> - about <xliff:g id="time">^2</xliff:g> left based on your usage</string>
+  <!-- [CHAR_LIMIT=60] label for estimated remaining duration of battery when under a certain amount -->
+  <string name="power_remaining_less_than_duration_only">Less than <xliff:g id="threshold">%1$s</xliff:g> remaining</string>
+  <!-- [CHAR_LIMIT=60] label for estimated remaining duration of battery when under a certain amount with the percentage -->
+  <string name="power_remaining_less_than_duration"><xliff:g id="level">%1$s</xliff:g> - Less than <xliff:g id="threshold">%2$s</xliff:g> remaining</string>
 
-    <!-- [CHAR_LIMIT=40] Label for battery level chart when discharging with duration -->
-    <string name="power_discharging_duration_short"><xliff:g id="level">^1</xliff:g> - <xliff:g id="time">^2</xliff:g> left</string>
+  <!-- Used to let users know that they have more than some amount of battery life remaining with percentage. ex: 75% - more than 1 day remaining [CHAR LIMIT = 80] -->
+  <string name="power_remaining_more_than_subtext"><xliff:g id="level">%1$s</xliff:g>more than <xliff:g id="time_remaining">%2$s</xliff:g> remaining</string>
+  <!-- Used to let users know that they have more than some amount of battery life remaining. ex: more than 1 day remaining [CHAR LIMIT = 40] -->
+  <string name="power_remaining_only_more_than_subtext">more than <xliff:g id="time_remaining">%1$s</xliff:g> remaining</string>
+
+  <!-- [CHAR_LIMIT=50] Short label for imminent shutdown warning of device -->
+  <string name="power_remaining_duration_only_shutdown_imminent" product="default">phone may shutdown soon</string>
+  <!-- [CHAR_LIMIT=50] Short label for imminent shutdown warning of device -->
+  <string name="power_remaining_duration_only_shutdown_imminent" product="tablet">tablet may shutdown soon</string>
+  <!-- [CHAR_LIMIT=50] Short label for imminent shutdown warning of device -->
+  <string name="power_remaining_duration_only_shutdown_imminent" product="device">device may shutdown soon</string>
+
+  <!-- [CHAR_LIMIT=40] Label for battery level chart when discharging with duration -->
+  <string name="power_discharging_duration"><xliff:g id="level">%1$s</xliff:g> - about <xliff:g id="time">%2$s</xliff:g> left</string>
+  <!-- [CHAR_LIMIT=60] Label for battery level chart when discharging with duration and using enhanced estimate -->
+  <string name="power_discharging_duration_enhanced"><xliff:g id="level">%1$s</xliff:g> - about <xliff:g id="time">%2$s</xliff:g> left based on your usage</string>
+
+  <!-- [CHAR_LIMIT=60] Label for battery level chart when shutdown is imminent-->
+  <string name="power_remaining_duration_shutdown_imminent" product="default"><xliff:g id="level">%1$s</xliff:g> - phone may shutdown soon</string>
+  <!-- [CHAR_LIMIT=60] Label for battery level chart when shutdown is imminent-->
+  <string name="power_remaining_duration_shutdown_imminent" product="tablet"><xliff:g id="level">%1$s</xliff:g> - tablet may shutdown soon</string>
+  <!-- [CHAR_LIMIT=60] Label for battery level chart when shutdown is imminent-->
+  <string name="power_remaining_duration_shutdown_imminent" product="device"><xliff:g id="level">%1$s</xliff:g> - device may shutdown soon</string>
 
     <!-- [CHAR_LIMIT=40] Label for battery level chart when charging -->
     <string name="power_charging"><xliff:g id="level">%1$s</xliff:g> - <xliff:g id="state">%2$s</xliff:g></string>
     <!-- [CHAR_LIMIT=40] Label for battery level chart when charging with duration -->
-    <string name="power_charging_duration"><xliff:g id="level">^1</xliff:g> - <xliff:g id="time">^2</xliff:g> until fully charged</string>
+    <string name="power_charging_duration"><xliff:g id="level">%1$s</xliff:g> - <xliff:g id="time">%2$s</xliff:g> until fully charged</string>
 
     <!-- Battery Info screen. Value for a status item.  Used for diagnostic info screens, precise translation isn't needed -->
     <string name="battery_info_status_unknown">Unknown</string>
@@ -1039,5 +1069,13 @@
     <string name="zen_interruption_level_priority">Priority only</string>
     <!-- [CHAR LIMIT=20] Accessibility string for current zen mode and selected exit condition. A template that simply concatenates existing mode string and the current condition description.  -->
     <string name="zen_mode_and_condition"><xliff:g id="zen_mode" example="Priority interruptions only">%1$s</xliff:g>. <xliff:g id="exit_condition" example="For one hour">%2$s</xliff:g></string>
+    <!-- Warning text when an alarm might be silenced by Do Not Disturb [CHAR LIMIT=NONE] -->
+    <string name="zen_alarm_warning_indef">You won\'t hear your next alarm <xliff:g id="when" example="at 7:00 AM">%1$s</xliff:g> unless you turn this off before then</string>
+    <!-- Warning text when an alarm might be silenced by Do Not Disturb due to a time-based condition [CHAR LIMIT=NONE] -->
+    <string name="zen_alarm_warning">You won\'t hear your next alarm <xliff:g id="when" example="at 7:00 AM">%1$s</xliff:g></string>
+    <!-- Alarm template for near alarms [CHAR LIMIT=25] -->
+    <string name="alarm_template">at <xliff:g id="when" example="7:00 AM">%1$s</xliff:g></string>
+    <!-- Alarm template for far in the future alarms [CHAR LIMIT=25] -->
+    <string name="alarm_template_far">on <xliff:g id="when" example="Fri 7:00 AM">%1$s</xliff:g></string>
 
 </resources>
diff --git a/packages/SettingsLib/src/com/android/settingslib/Utils.java b/packages/SettingsLib/src/com/android/settingslib/Utils.java
index 1f67dfb..9947dec 100644
--- a/packages/SettingsLib/src/com/android/settingslib/Utils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/Utils.java
@@ -1,6 +1,7 @@
 package com.android.settingslib;
 
 import android.annotation.ColorInt;
+import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageInfo;
@@ -17,10 +18,13 @@
 import android.location.LocationManager;
 import android.net.ConnectivityManager;
 import android.os.BatteryManager;
+import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.print.PrintManager;
 import android.provider.Settings;
+
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.UserIcons;
 import com.android.settingslib.drawable.UserIconDrawable;
 import com.android.settingslib.wrapper.LocationManagerWrapper;
@@ -30,6 +34,9 @@
 
     private static final String CURRENT_MODE_KEY = "CURRENT_MODE";
     private static final String NEW_MODE_KEY = "NEW_MODE";
+    @VisibleForTesting
+    static final String STORAGE_MANAGER_SHOW_OPT_IN_PROPERTY =
+            "ro.storage_manager.show_opt_in";
 
     private static Signature[] sSystemSignature;
     private static String sPermissionControllerPackageName;
@@ -37,11 +44,11 @@
     private static String sSharedSystemSharedLibPackageName;
 
     static final int[] WIFI_PIE = {
-        com.android.internal.R.drawable.ic_wifi_signal_0,
-        com.android.internal.R.drawable.ic_wifi_signal_1,
-        com.android.internal.R.drawable.ic_wifi_signal_2,
-        com.android.internal.R.drawable.ic_wifi_signal_3,
-        com.android.internal.R.drawable.ic_wifi_signal_4
+            com.android.internal.R.drawable.ic_wifi_signal_0,
+            com.android.internal.R.drawable.ic_wifi_signal_1,
+            com.android.internal.R.drawable.ic_wifi_signal_2,
+            com.android.internal.R.drawable.ic_wifi_signal_3,
+            com.android.internal.R.drawable.ic_wifi_signal_4
     };
 
     public static void updateLocationEnabled(Context context, boolean enabled, int userId,
@@ -262,7 +269,7 @@
      */
     public static boolean isSystemPackage(Resources resources, PackageManager pm, PackageInfo pkg) {
         if (sSystemSignature == null) {
-            sSystemSignature = new Signature[]{ getSystemSignature(pm) };
+            sSystemSignature = new Signature[]{getSystemSignature(pm)};
         }
         if (sPermissionControllerPackageName == null) {
             sPermissionControllerPackageName = pm.getPermissionControllerPackageName();
@@ -274,7 +281,7 @@
             sSharedSystemSharedLibPackageName = pm.getSharedSystemSharedLibraryPackageName();
         }
         return (sSystemSignature[0] != null
-                        && sSystemSignature[0].equals(getFirstSignature(pkg)))
+                && sSystemSignature[0].equals(getFirstSignature(pkg)))
                 || pkg.packageName.equals(sPermissionControllerPackageName)
                 || pkg.packageName.equals(sServicesSystemSharedLibPackageName)
                 || pkg.packageName.equals(sSharedSystemSharedLibPackageName)
@@ -312,7 +319,6 @@
      * Returns the Wifi icon resource for a given RSSI level.
      *
      * @param level The number of bars to show (0-4)
-     *
      * @throws IllegalArgumentException if an invalid RSSI level is given.
      */
     public static int getWifiIconResource(int level) {
@@ -342,4 +348,19 @@
         return !context.getSystemService(ConnectivityManager.class)
                 .isNetworkSupported(ConnectivityManager.TYPE_MOBILE);
     }
+
+    /** Returns if the automatic storage management feature is turned on or not. **/
+    public static boolean isStorageManagerEnabled(Context context) {
+        boolean isDefaultOn;
+        try {
+            // Turn off by default if the opt-in was shown.
+            isDefaultOn = !SystemProperties.getBoolean(STORAGE_MANAGER_SHOW_OPT_IN_PROPERTY, true);
+        } catch (Resources.NotFoundException e) {
+            isDefaultOn = false;
+        }
+        return Settings.Secure.getInt(context.getContentResolver(),
+                Settings.Secure.AUTOMATIC_STORAGE_MANAGER_ENABLED,
+                isDefaultOn ? 1 : 0)
+                != 0;
+    }
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
index fb0f75b..e1ebbc4 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
@@ -940,60 +940,55 @@
                     com.android.settingslib.Utils.formatPercentage(batteryLevel);
         }
 
-        // TODO: A temporary workaround solution using string description the device is active.
-        // Issue tracked by b/72317067 .
-        // An alternative solution would be visual indication.
-        // Intentionally not adding the strings to strings.xml for now:
-        //  1) If this is just a short-term solution, no need to waste translation effort
-        //  2) The number of strings with all possible combinations becomes enormously large.
-        // If string description becomes part of the final solution, we MUST NOT
-        // concatenate the strings here: this does not translate well.
-        String activeString = null;
+        // Prepare the string for the Active Device summary
+        String[] activeDeviceStringsArray = mContext.getResources().getStringArray(
+                R.array.bluetooth_audio_active_device_summaries);
+        String activeDeviceString = activeDeviceStringsArray[0];  // Default value: not active
         if (mIsActiveDeviceA2dp && mIsActiveDeviceHeadset) {
-            activeString = ", active";
+            activeDeviceString = activeDeviceStringsArray[1];     // Active for Media and Phone
         } else {
             if (mIsActiveDeviceA2dp) {
-                activeString = ", active(media)";
+                activeDeviceString = activeDeviceStringsArray[2]; // Active for Media only
             }
             if (mIsActiveDeviceHeadset) {
-                activeString = ", active(phone)";
+                activeDeviceString = activeDeviceStringsArray[3]; // Active for Phone only
             }
         }
-        if (activeString == null) activeString = "";
 
         if (profileConnected) {
             if (a2dpNotConnected && hfpNotConnected) {
                 if (batteryLevelPercentageString != null) {
                     return mContext.getString(
                             R.string.bluetooth_connected_no_headset_no_a2dp_battery_level,
-                            batteryLevelPercentageString) + activeString;
+                            batteryLevelPercentageString, activeDeviceString);
                 } else {
-                    return mContext.getString(R.string.bluetooth_connected_no_headset_no_a2dp) +
-                        activeString;
+                    return mContext.getString(R.string.bluetooth_connected_no_headset_no_a2dp,
+                            activeDeviceString);
                 }
 
             } else if (a2dpNotConnected) {
                 if (batteryLevelPercentageString != null) {
                     return mContext.getString(R.string.bluetooth_connected_no_a2dp_battery_level,
-                            batteryLevelPercentageString) + activeString;
+                            batteryLevelPercentageString, activeDeviceString);
                 } else {
-                    return mContext.getString(R.string.bluetooth_connected_no_a2dp) + activeString;
+                    return mContext.getString(R.string.bluetooth_connected_no_a2dp,
+                            activeDeviceString);
                 }
 
             } else if (hfpNotConnected) {
                 if (batteryLevelPercentageString != null) {
                     return mContext.getString(R.string.bluetooth_connected_no_headset_battery_level,
-                            batteryLevelPercentageString) + activeString;
+                            batteryLevelPercentageString, activeDeviceString);
                 } else {
-                    return mContext.getString(R.string.bluetooth_connected_no_headset)
-                          + activeString;
+                    return mContext.getString(R.string.bluetooth_connected_no_headset,
+                            activeDeviceString);
                 }
             } else {
                 if (batteryLevelPercentageString != null) {
                     return mContext.getString(R.string.bluetooth_connected_battery_level,
-                            batteryLevelPercentageString) + activeString;
+                            batteryLevelPercentageString, activeDeviceString);
                 } else {
-                    return mContext.getString(R.string.bluetooth_connected) + activeString;
+                    return mContext.getString(R.string.bluetooth_connected, activeDeviceString);
                 }
             }
         }
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java
new file mode 100644
index 0000000..8f9e4635
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java
@@ -0,0 +1,235 @@
+/*
+ * 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.settingslib.bluetooth;
+
+import android.bluetooth.BluetoothHearingAid;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothClass;
+import android.bluetooth.BluetoothCodecConfig;
+import android.bluetooth.BluetoothCodecStatus;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothProfile;
+import android.bluetooth.BluetoothUuid;
+import android.content.Context;
+import android.os.ParcelUuid;
+import android.util.Log;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.settingslib.R;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public class HearingAidProfile implements LocalBluetoothProfile {
+    private static final String TAG = "HearingAidProfile";
+    private static boolean V = true;
+
+    private Context mContext;
+
+    private BluetoothHearingAid mService;
+    private boolean mIsProfileReady;
+
+    private final LocalBluetoothAdapter mLocalAdapter;
+    private final CachedBluetoothDeviceManager mDeviceManager;
+
+    static final String NAME = "HearingAid";
+    private final LocalBluetoothProfileManager mProfileManager;
+
+    // Order of this profile in device profiles list
+    private static final int ORDINAL = 1;
+
+    // These callbacks run on the main thread.
+    private final class HearingAidServiceListener
+            implements BluetoothProfile.ServiceListener {
+
+        public void onServiceConnected(int profile, BluetoothProfile proxy) {
+            if (V) Log.d(TAG,"Bluetooth service connected");
+            mService = (BluetoothHearingAid) proxy;
+            // We just bound to the service, so refresh the UI for any connected HearingAid devices.
+            List<BluetoothDevice> deviceList = mService.getConnectedDevices();
+            while (!deviceList.isEmpty()) {
+                BluetoothDevice nextDevice = deviceList.remove(0);
+                CachedBluetoothDevice device = mDeviceManager.findDevice(nextDevice);
+                // we may add a new device here, but generally this should not happen
+                if (device == null) {
+                    Log.w(TAG, "HearingAidProfile found new device: " + nextDevice);
+                    device = mDeviceManager.addDevice(mLocalAdapter, mProfileManager, nextDevice);
+                }
+                device.onProfileStateChanged(HearingAidProfile.this, BluetoothProfile.STATE_CONNECTED);
+                device.refresh();
+            }
+            mIsProfileReady=true;
+        }
+
+        public void onServiceDisconnected(int profile) {
+            if (V) Log.d(TAG,"Bluetooth service disconnected");
+            mIsProfileReady=false;
+        }
+    }
+
+    public boolean isProfileReady() {
+        return mIsProfileReady;
+    }
+
+    HearingAidProfile(Context context, LocalBluetoothAdapter adapter,
+            CachedBluetoothDeviceManager deviceManager,
+            LocalBluetoothProfileManager profileManager) {
+        mContext = context;
+        mLocalAdapter = adapter;
+        mDeviceManager = deviceManager;
+        mProfileManager = profileManager;
+        mLocalAdapter.getProfileProxy(context, new HearingAidServiceListener(),
+                BluetoothProfile.HEARING_AID);
+    }
+
+    public boolean isConnectable() {
+        return true;
+    }
+
+    public boolean isAutoConnectable() {
+        return true;
+    }
+
+    public List<BluetoothDevice> getConnectedDevices() {
+        if (mService == null) return new ArrayList<BluetoothDevice>(0);
+        return mService.getDevicesMatchingConnectionStates(
+              new int[] {BluetoothProfile.STATE_CONNECTED,
+                         BluetoothProfile.STATE_CONNECTING,
+                         BluetoothProfile.STATE_DISCONNECTING});
+    }
+
+    public boolean connect(BluetoothDevice device) {
+        if (mService == null) return false;
+        return mService.connect(device);
+    }
+
+    public boolean disconnect(BluetoothDevice device) {
+        if (mService == null) return false;
+        // Downgrade priority as user is disconnecting the hearing aid.
+        if (mService.getPriority(device) > BluetoothProfile.PRIORITY_ON){
+            mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
+        }
+        return mService.disconnect(device);
+    }
+
+    public int getConnectionStatus(BluetoothDevice device) {
+        if (mService == null) {
+            return BluetoothProfile.STATE_DISCONNECTED;
+        }
+        return mService.getConnectionState(device);
+    }
+
+    public boolean isPreferred(BluetoothDevice device) {
+        if (mService == null) return false;
+        return mService.getPriority(device) > BluetoothProfile.PRIORITY_OFF;
+    }
+
+    public int getPreferred(BluetoothDevice device) {
+        if (mService == null) return BluetoothProfile.PRIORITY_OFF;
+        return mService.getPriority(device);
+    }
+
+    public void setPreferred(BluetoothDevice device, boolean preferred) {
+        if (mService == null) return;
+        if (preferred) {
+            if (mService.getPriority(device) < BluetoothProfile.PRIORITY_ON) {
+                mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
+            }
+        } else {
+            mService.setPriority(device, BluetoothProfile.PRIORITY_OFF);
+        }
+    }
+
+    public int getVolume() {
+        if (mService == null) {
+            return 0;
+        }
+        return mService.getVolume();
+    }
+
+    public void setVolume(int volume) {
+        if (mService == null) {
+            return;
+        }
+        mService.setVolume(volume);
+    }
+
+    public long getHiSyncId(BluetoothDevice device) {
+        if (mService == null) {
+            return BluetoothHearingAid.HI_SYNC_ID_INVALID;
+        }
+        return mService.getHiSyncId(device);
+    }
+
+    public int getDeviceSide(BluetoothDevice device) {
+        if (mService == null) {
+            return BluetoothHearingAid.SIDE_LEFT;
+        }
+        return mService.getDeviceSide(device);
+    }
+
+    public int getDeviceMode(BluetoothDevice device) {
+        if (mService == null) {
+            return BluetoothHearingAid.MODE_MONAURAL;
+        }
+        return mService.getDeviceMode(device);
+    }
+
+    public String toString() {
+        return NAME;
+    }
+
+    public int getOrdinal() {
+        return ORDINAL;
+    }
+
+    public int getNameResource(BluetoothDevice device) {
+        return R.string.bluetooth_profile_hearing_aid;
+    }
+
+    public int getSummaryResourceForDevice(BluetoothDevice device) {
+        int state = getConnectionStatus(device);
+        switch (state) {
+            case BluetoothProfile.STATE_DISCONNECTED:
+                return R.string.bluetooth_hearing_aid_profile_summary_use_for;
+
+            case BluetoothProfile.STATE_CONNECTED:
+                return R.string.bluetooth_hearing_aid_profile_summary_connected;
+
+            default:
+                return Utils.getConnectionStateSummary(state);
+        }
+    }
+
+    public int getDrawableResource(BluetoothClass btClass) {
+        return R.drawable.ic_bt_hearing_aid;
+    }
+
+    protected void finalize() {
+        if (V) Log.d(TAG, "finalize()");
+        if (mService != null) {
+            try {
+                BluetoothAdapter.getDefaultAdapter().closeProfileProxy(BluetoothProfile.HEARING_AID,
+                                                                       mService);
+                mService = null;
+            }catch (Throwable t) {
+                Log.w(TAG, "Error cleaning up Hearing Aid proxy", t);
+            }
+        }
+    }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothAdapter.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothAdapter.java
old mode 100755
new mode 100644
index cda4e45..5f7ba586
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothAdapter.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothAdapter.java
@@ -194,8 +194,13 @@
         return mState;
     }
 
-    synchronized void setBluetoothStateInt(int state) {
-        mState = state;
+    void setBluetoothStateInt(int state) {
+        synchronized(this) {
+            if (mState == state) {
+                return;
+            }
+            mState = state;
+        }
 
         if (state == BluetoothAdapter.STATE_ON) {
             // if mProfileManager hasn't been constructed yet, it will
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
index 991d922..34a099c 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
@@ -21,6 +21,7 @@
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothHeadset;
 import android.bluetooth.BluetoothHeadsetClient;
+import android.bluetooth.BluetoothHearingAid;
 import android.bluetooth.BluetoothHidHost;
 import android.bluetooth.BluetoothMap;
 import android.bluetooth.BluetoothMapClient;
@@ -91,6 +92,7 @@
     private final PbapServerProfile mPbapProfile;
     private final boolean mUsePbapPce;
     private final boolean mUseMapClient;
+    private HearingAidProfile mHearingAidProfile;
 
     /**
      * Mapping from profile name, e.g. "HEADSET" to profile object.
@@ -143,10 +145,14 @@
 
         //Create PBAP server profile
         if(DEBUG) Log.d(TAG, "Adding local PBAP profile");
+
         mPbapProfile = new PbapServerProfile(context);
         addProfile(mPbapProfile, PbapServerProfile.NAME,
              BluetoothPbap.ACTION_CONNECTION_STATE_CHANGED);
 
+        mHearingAidProfile = new HearingAidProfile(mContext, mLocalAdapter, mDeviceManager, this);
+        addProfile(mHearingAidProfile, HearingAidProfile.NAME,
+                   BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED);
         if (DEBUG) Log.d(TAG, "LocalBluetoothProfileManager construction complete");
     }
 
@@ -254,6 +260,18 @@
                 "Warning: PBAP Client profile was previously added but the UUID is now missing.");
         }
 
+        //Hearing Aid Client
+        if (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.HearingAid)) {
+            if (mHearingAidProfile == null) {
+                if(DEBUG) Log.d(TAG, "Adding local Hearing Aid profile");
+                mHearingAidProfile = new HearingAidProfile(mContext, mLocalAdapter, mDeviceManager, this);
+                addProfile(mHearingAidProfile, HearingAidProfile.NAME,
+                        BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED);
+            }
+        } else if (mHearingAidProfile != null) {
+            Log.w(TAG, "Warning: Hearing Aid profile was previously added but the UUID is now missing.");
+        }
+
         mEventManager.registerProfileIntentReceiver();
 
         // There is no local SDP record for HID and Settings app doesn't control PBAP Server.
@@ -416,6 +434,10 @@
         return mMapClientProfile;
     }
 
+    public HearingAidProfile getHearingAidProfile() {
+        return mHearingAidProfile;
+    }
+
     /**
      * Fill in a list of LocalBluetoothProfile objects that are supported by
      * the local device and the remote device.
@@ -515,6 +537,12 @@
             removedProfiles.remove(mPbapClientProfile);
         }
 
+        if (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.HearingAid) &&
+            mHearingAidProfile != null) {
+            profiles.add(mHearingAidProfile);
+            removedProfiles.remove(mHearingAidProfile);
+        }
+
         if (DEBUG) {
             Log.d(TAG,"New Profiles" + profiles.toString());
         }
diff --git a/packages/SettingsLib/src/com/android/settingslib/development/DevelopmentSettingsEnabler.java b/packages/SettingsLib/src/com/android/settingslib/development/DevelopmentSettingsEnabler.java
index 4e78d9b..85bf4e8 100644
--- a/packages/SettingsLib/src/com/android/settingslib/development/DevelopmentSettingsEnabler.java
+++ b/packages/SettingsLib/src/com/android/settingslib/development/DevelopmentSettingsEnabler.java
@@ -19,6 +19,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.os.Build;
+import android.os.UserManager;
 import android.provider.Settings;
 import android.support.v4.content.LocalBroadcastManager;
 
@@ -27,7 +28,8 @@
     public static final String DEVELOPMENT_SETTINGS_CHANGED_ACTION =
             "com.android.settingslib.development.DevelopmentSettingsEnabler.SETTINGS_CHANGED";
 
-    private DevelopmentSettingsEnabler() {}
+    private DevelopmentSettingsEnabler() {
+    }
 
     public static void setDevelopmentSettingsEnabled(Context context, boolean enable) {
         Settings.Global.putInt(context.getContentResolver(),
@@ -37,8 +39,14 @@
     }
 
     public static boolean isDevelopmentSettingsEnabled(Context context) {
-        return Settings.Global.getInt(context.getContentResolver(),
+        final UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE);
+        final boolean settingEnabled = Settings.Global.getInt(context.getContentResolver(),
                 Settings.Global.DEVELOPMENT_SETTINGS_ENABLED,
                 Build.TYPE.equals("eng") ? 1 : 0) != 0;
+        final boolean hasRestriction = um.hasUserRestriction(
+                UserManager.DISALLOW_DEBUGGING_FEATURES);
+        final boolean isAdmin = um.isAdminUser();
+
+        return isAdmin && !hasRestriction && settingEnabled;
     }
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java b/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java
index 190f5e6..68ead09 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java
@@ -17,7 +17,6 @@
 
 import android.annotation.LayoutRes;
 import android.annotation.Nullable;
-import android.app.ActionBar;
 import android.app.Activity;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
@@ -72,9 +71,9 @@
             requestWindowFeature(Window.FEATURE_NO_TITLE);
         }
         super.setContentView(R.layout.settings_with_drawer);
-        mContentHeaderContainer = (FrameLayout) findViewById(R.id.content_header_container);
+        mContentHeaderContainer = findViewById(R.id.content_header_container);
 
-        Toolbar toolbar = (Toolbar) findViewById(R.id.action_bar);
+        Toolbar toolbar = findViewById(R.id.action_bar);
         if (theme.getBoolean(android.R.styleable.Theme_windowNoTitle, false)) {
             toolbar.setVisibility(View.GONE);
             return;
@@ -89,7 +88,9 @@
 
     @Override
     public boolean onNavigateUp() {
-        finish();
+        if (!super.onNavigateUp()) {
+            finish();
+        }
         return true;
     }
 
@@ -104,11 +105,6 @@
         registerReceiver(mPackageReceiver, filter);
 
         new CategoriesUpdateTask().execute();
-        final Intent intent = getIntent();
-        if (intent != null && intent.getBooleanExtra(EXTRA_SHOW_MENU, false)) {
-            // Intent explicitly set to show menu.
-            showMenuIcon();
-        }
     }
 
     @Override
@@ -125,13 +121,6 @@
         mCategoryListeners.remove(listener);
     }
 
-    public void setContentHeaderView(View headerView) {
-        mContentHeaderContainer.removeAllViews();
-        if (headerView != null) {
-            mContentHeaderContainer.addView(headerView);
-        }
-    }
-
     @Override
     public void setContentView(@LayoutRes int layoutResID) {
         final ViewGroup parent = findViewById(R.id.content_frame);
@@ -151,13 +140,6 @@
         ((ViewGroup) findViewById(R.id.content_frame)).addView(view, params);
     }
 
-    private void showMenuIcon() {
-        final ActionBar actionBar = getActionBar();
-        if (actionBar != null) {
-            actionBar.setDisplayHomeAsUpEnabled(true);
-        }
-    }
-
     private void onCategoriesChanged() {
         final int N = mCategoryListeners.size();
         for (int i = 0; i < N; i++) {
@@ -165,10 +147,6 @@
         }
     }
 
-    public void onProfileTileOpen() {
-        finish();
-    }
-
     /**
      * @return whether or not the enabled state actually changed.
      */
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/src/com/android/settingslib/net/DataUsageController.java b/packages/SettingsLib/src/com/android/settingslib/net/DataUsageController.java
index ed3696c..f7aa297 100644
--- a/packages/SettingsLib/src/com/android/settingslib/net/DataUsageController.java
+++ b/packages/SettingsLib/src/com/android/settingslib/net/DataUsageController.java
@@ -158,6 +158,9 @@
             usage.startDate = start;
             usage.usageLevel = totalBytes;
             usage.period = formatDateRange(start, end);
+            usage.cycleStart = start;
+            usage.cycleEnd = end;
+
             if (policy != null) {
                 usage.limitLevel = policy.limitBytes > 0 ? policy.limitBytes : 0;
                 usage.warningLevel = policy.warningBytes > 0 ? policy.warningBytes : 0;
@@ -245,6 +248,8 @@
         public long limitLevel;
         public long warningLevel;
         public long usageLevel;
+        public long cycleStart;
+        public long cycleEnd;
     }
 
     public interface Callback {
diff --git a/packages/SettingsLib/src/com/android/settingslib/notification/EnableZenModeDialog.java b/packages/SettingsLib/src/com/android/settingslib/notification/EnableZenModeDialog.java
index a20f687..b98f27e 100644
--- a/packages/SettingsLib/src/com/android/settingslib/notification/EnableZenModeDialog.java
+++ b/packages/SettingsLib/src/com/android/settingslib/notification/EnableZenModeDialog.java
@@ -1,5 +1,3 @@
-package com.android.settingslib.notification;
-
 /*
  * Copyright (C) 2018 The Android Open Source Project
  *
@@ -16,6 +14,8 @@
  * limitations under the License.
  */
 
+package com.android.settingslib.notification;
+
 import android.app.ActivityManager;
 import android.app.AlarmManager;
 import android.app.AlertDialog;
@@ -28,6 +28,7 @@
 import android.service.notification.Condition;
 import android.service.notification.ZenModeConfig;
 import android.text.TextUtils;
+import android.text.format.DateFormat;
 import android.util.Log;
 import android.util.Slog;
 import android.view.LayoutInflater;
@@ -40,6 +41,7 @@
 import android.widget.ScrollView;
 import android.widget.TextView;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto;
 import com.android.internal.policy.PhoneWindow;
@@ -48,11 +50,11 @@
 import java.util.Arrays;
 import java.util.Calendar;
 import java.util.GregorianCalendar;
+import java.util.Locale;
 import java.util.Objects;
 
 public class EnableZenModeDialog {
-
-    private static final String TAG = "QSEnableZenModeDialog";
+    private static final String TAG = "EnableZenModeDialog";
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
 
     private static final int[] MINUTE_BUCKETS = ZenModeConfig.MINUTE_BUCKETS;
@@ -60,31 +62,45 @@
     private static final int MAX_BUCKET_MINUTES = MINUTE_BUCKETS[MINUTE_BUCKETS.length - 1];
     private static final int DEFAULT_BUCKET_INDEX = Arrays.binarySearch(MINUTE_BUCKETS, 60);
 
-    private static final int FOREVER_CONDITION_INDEX = 0;
-    private static final int COUNTDOWN_CONDITION_INDEX = 1;
-    private static final int COUNTDOWN_ALARM_CONDITION_INDEX = 2;
+    @VisibleForTesting
+    protected static final int FOREVER_CONDITION_INDEX = 0;
+    @VisibleForTesting
+    protected static final int COUNTDOWN_CONDITION_INDEX = 1;
+    @VisibleForTesting
+    protected static final int COUNTDOWN_ALARM_CONDITION_INDEX = 2;
 
     private static final int SECONDS_MS = 1000;
     private static final int MINUTES_MS = 60 * SECONDS_MS;
 
-    private Uri mForeverId;
+    @VisibleForTesting
+    protected Uri mForeverId;
     private int mBucketIndex = -1;
 
+    @VisibleForTesting
+    protected NotificationManager mNotificationManager;
     private AlarmManager mAlarmManager;
     private int mUserId;
     private boolean mAttached;
 
-    private Context mContext;
+    @VisibleForTesting
+    protected Context mContext;
+    @VisibleForTesting
+    protected TextView mZenAlarmWarning;
+    @VisibleForTesting
+    protected LinearLayout mZenRadioGroupContent;
+
     private RadioGroup mZenRadioGroup;
-    private LinearLayout mZenRadioGroupContent;
     private int MAX_MANUAL_DND_OPTIONS = 3;
 
+    @VisibleForTesting
+    protected LayoutInflater mLayoutInflater;
+
     public EnableZenModeDialog(Context context) {
         mContext = context;
     }
 
     public Dialog createDialog() {
-        NotificationManager noMan = (NotificationManager) mContext.
+        mNotificationManager = (NotificationManager) mContext.
                 getSystemService(Context.NOTIFICATION_SERVICE);
         mForeverId =  Condition.newId(mContext).appendPath("forever").build();
         mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
@@ -117,7 +133,8 @@
                                     Slog.d(TAG, "Invalid manual condition: " + tag.condition);
                                 }
                                 // always triggers priority-only dnd with chosen condition
-                                noMan.setZenMode(Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS,
+                                mNotificationManager.setZenMode(
+                                        Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS,
                                         getRealConditionId(tag.condition), TAG);
                             }
                         });
@@ -133,32 +150,40 @@
         for (int i = 0; i < N; i++) {
             mZenRadioGroupContent.getChildAt(i).setVisibility(View.GONE);
         }
+
+        mZenAlarmWarning.setVisibility(View.GONE);
     }
 
     protected View getContentView() {
-        final LayoutInflater inflater = new PhoneWindow(mContext).getLayoutInflater();
-        View contentView = inflater.inflate(R.layout.zen_mode_turn_on_dialog_container, null);
+        if (mLayoutInflater == null) {
+            mLayoutInflater = new PhoneWindow(mContext).getLayoutInflater();
+        }
+        View contentView = mLayoutInflater.inflate(R.layout.zen_mode_turn_on_dialog_container,
+                null);
         ScrollView container = (ScrollView) contentView.findViewById(R.id.container);
 
         mZenRadioGroup = container.findViewById(R.id.zen_radio_buttons);
         mZenRadioGroupContent = container.findViewById(R.id.zen_radio_buttons_content);
+        mZenAlarmWarning = container.findViewById(R.id.zen_alarm_warning);
 
         for (int i = 0; i < MAX_MANUAL_DND_OPTIONS; i++) {
-            final View radioButton = inflater.inflate(R.layout.zen_mode_radio_button,
+            final View radioButton = mLayoutInflater.inflate(R.layout.zen_mode_radio_button,
                     mZenRadioGroup, false);
             mZenRadioGroup.addView(radioButton);
             radioButton.setId(i);
 
-            final View radioButtonContent = inflater.inflate(R.layout.zen_mode_condition,
+            final View radioButtonContent = mLayoutInflater.inflate(R.layout.zen_mode_condition,
                     mZenRadioGroupContent, false);
             radioButtonContent.setId(i + MAX_MANUAL_DND_OPTIONS);
             mZenRadioGroupContent.addView(radioButtonContent);
         }
+
         hideAllConditions();
         return contentView;
     }
 
-    private void bind(final Condition condition, final View row, final int rowId) {
+    @VisibleForTesting
+    protected void bind(final Condition condition, final View row, final int rowId) {
         if (condition == null) throw new IllegalArgumentException("condition must not be null");
         final boolean enabled = condition.state == Condition.STATE_TRUE;
         final ConditionTag tag = row.getTag() != null ? (ConditionTag) row.getTag() :
@@ -181,6 +206,7 @@
                     if (DEBUG) Log.d(TAG, "onCheckedChanged " + conditionId);
                     MetricsLogger.action(mContext,
                             MetricsProto.MetricsEvent.QS_DND_CONDITION_SELECT);
+                    updateAlarmWarningText(tag.condition);
                     announceConditionSelection(tag);
                 }
             }
@@ -190,11 +216,13 @@
         row.setVisibility(View.VISIBLE);
     }
 
-    private ConditionTag getConditionTagAt(int index) {
+    @VisibleForTesting
+    protected ConditionTag getConditionTagAt(int index) {
         return (ConditionTag) mZenRadioGroupContent.getChildAt(index).getTag();
     }
 
-    private void bindConditions(Condition c) {
+    @VisibleForTesting
+    protected void bindConditions(Condition c) {
         // forever
         bind(forever(), mZenRadioGroupContent.getChildAt(FOREVER_CONDITION_INDEX),
                 FOREVER_CONDITION_INDEX);
@@ -236,11 +264,13 @@
         return info != null ? info.getTriggerTime() : 0;
     }
 
-    private boolean isAlarm(Condition c) {
+    @VisibleForTesting
+    protected boolean isAlarm(Condition c) {
         return c != null && ZenModeConfig.isValidCountdownToAlarmConditionId(c.id);
     }
 
-    private boolean isCountdown(Condition c) {
+    @VisibleForTesting
+    protected boolean isCountdown(Condition c) {
         return c != null && ZenModeConfig.isValidCountdownConditionId(c.id);
     }
 
@@ -264,7 +294,8 @@
     }
 
     // Returns a time condition if the next alarm is within the next week.
-    private Condition getTimeUntilNextAlarmCondition() {
+    @VisibleForTesting
+    protected Condition getTimeUntilNextAlarmCondition() {
         GregorianCalendar weekRange = new GregorianCalendar();
         setToMidnight(weekRange);
         weekRange.add(Calendar.DATE, 6);
@@ -282,7 +313,8 @@
         return null;
     }
 
-    private void bindGenericCountdown() {
+    @VisibleForTesting
+    protected void bindGenericCountdown() {
         mBucketIndex = DEFAULT_BUCKET_INDEX;
         Condition countdown = ZenModeConfig.toTimeCondition(mContext,
                 MINUTE_BUCKETS[mBucketIndex], ActivityManager.getCurrentUser());
@@ -366,7 +398,8 @@
         }
     }
 
-    private void bindNextAlarm(Condition c) {
+    @VisibleForTesting
+    protected void bindNextAlarm(Condition c) {
         View alarmContent = mZenRadioGroupContent.getChildAt(COUNTDOWN_ALARM_CONDITION_INDEX);
         ConditionTag tag = (ConditionTag) alarmContent.getTag();
 
@@ -415,6 +448,7 @@
                     MINUTE_BUCKETS[mBucketIndex], ActivityManager.getCurrentUser());
         }
         bind(newCondition, row, rowId);
+        updateAlarmWarningText(tag.condition);
         tag.rb.setChecked(true);
         announceConditionSelection(tag);
     }
@@ -428,8 +462,57 @@
         }
     }
 
+    private void updateAlarmWarningText(Condition condition) {
+        String warningText = computeAlarmWarningText(condition);
+        mZenAlarmWarning.setText(warningText);
+        mZenAlarmWarning.setVisibility(warningText == null ? View.GONE : View.VISIBLE);
+    }
+
+    @VisibleForTesting
+    protected String computeAlarmWarningText(Condition condition) {
+        boolean allowAlarms = (mNotificationManager.getNotificationPolicy().priorityCategories
+                & NotificationManager.Policy.PRIORITY_CATEGORY_ALARMS) != 0;
+
+        // don't show alarm warning if alarms are allowed to bypass dnd
+        if (allowAlarms) {
+            return null;
+        }
+
+        final long now = System.currentTimeMillis();
+        final long nextAlarm = getNextAlarm();
+        if (nextAlarm < now) {
+            return null;
+        }
+        int warningRes = 0;
+        if (condition == null || isForever(condition)) {
+            warningRes = R.string.zen_alarm_warning_indef;
+        } else {
+            final long time = ZenModeConfig.tryParseCountdownConditionId(condition.id);
+            if (time > now && nextAlarm < time) {
+                warningRes = R.string.zen_alarm_warning;
+            }
+        }
+        if (warningRes == 0) {
+            return null;
+        }
+
+        return mContext.getResources().getString(warningRes, getTime(nextAlarm, now));
+    }
+
+    @VisibleForTesting
+    protected String getTime(long nextAlarm, long now) {
+        final boolean soon = (nextAlarm - now) < 24 * 60 * 60 * 1000;
+        final boolean is24 = DateFormat.is24HourFormat(mContext, ActivityManager.getCurrentUser());
+        final String skeleton = soon ? (is24 ? "Hm" : "hma") : (is24 ? "EEEHm" : "EEEhma");
+        final String pattern = DateFormat.getBestDateTimePattern(Locale.getDefault(), skeleton);
+        final CharSequence formattedTime = DateFormat.format(pattern, nextAlarm);
+        final int templateRes = soon ? R.string.alarm_template : R.string.alarm_template_far;
+        return mContext.getResources().getString(templateRes, formattedTime);
+    }
+
     // used as the view tag on condition rows
-    private static class ConditionTag {
+    @VisibleForTesting
+    protected static class ConditionTag {
         public RadioButton rb;
         public View lines;
         public TextView line1;
diff --git a/packages/SettingsLib/src/com/android/settingslib/utils/PowerUtil.java b/packages/SettingsLib/src/com/android/settingslib/utils/PowerUtil.java
new file mode 100644
index 0000000..346ca66
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/utils/PowerUtil.java
@@ -0,0 +1,143 @@
+/*
+ * 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.settingslib.utils;
+
+import android.content.Context;
+import android.icu.text.MeasureFormat;
+import android.icu.text.MeasureFormat.FormatWidth;
+import android.icu.util.Measure;
+import android.icu.util.MeasureUnit;
+import android.support.annotation.Nullable;
+import android.text.TextUtils;
+import com.android.settingslib.R;
+import com.android.settingslib.utils.StringUtil;
+import java.util.Locale;
+import java.util.concurrent.TimeUnit;
+
+/** Utility class for keeping power related strings consistent**/
+public class PowerUtil {
+    private static final long SEVEN_MINUTES_MILLIS = TimeUnit.MINUTES.toMillis(7);
+    private static final long FIFTEEN_MINUTES_MILLIS = TimeUnit.MINUTES.toMillis(15);
+    private static final long ONE_DAY_MILLIS = TimeUnit.DAYS.toMillis(1);
+
+    /**
+     * This method produces the text used in various places throughout the system to describe the
+     * remaining battery life of the phone in a consistent manner.
+     *
+     * @param context
+     * @param drainTimeMs The estimated time remaining before the phone dies in milliseconds.
+     * @param percentageString An optional percentage of battery remaining string.
+     * @param basedOnUsage Whether this estimate is based on usage or simple extrapolation.
+     * @return a properly formatted and localized string describing how much time remains
+     * before the battery runs out.
+     */
+    public static String getBatteryRemainingStringFormatted(Context context, long drainTimeMs,
+            @Nullable String percentageString, boolean basedOnUsage) {
+        if (drainTimeMs > 0) {
+            if (drainTimeMs <= SEVEN_MINUTES_MILLIS) {
+                // show a imminent shutdown warning if less than 7 minutes remain
+                return getShutdownImminentString(context, percentageString);
+            } else if (drainTimeMs <= FIFTEEN_MINUTES_MILLIS) {
+                // show a less than 15 min remaining warning if appropriate
+                CharSequence timeString = StringUtil.formatElapsedTime(context,
+                        FIFTEEN_MINUTES_MILLIS,
+                        false /* withSeconds */);
+                return getUnderFifteenString(context, timeString, percentageString);
+            } else if (drainTimeMs >= ONE_DAY_MILLIS) {
+                // just say more than one day if over 24 hours
+                return getMoreThanOneDayString(context, percentageString);
+            } else {
+                // show a regular time remaining string
+                return getRegularTimeRemainingString(context, drainTimeMs,
+                        percentageString, basedOnUsage);
+            }
+        }
+        return null;
+    }
+
+    private static String getShutdownImminentString(Context context, String percentageString) {
+        return TextUtils.isEmpty(percentageString)
+                ? context.getString(R.string.power_remaining_duration_only_shutdown_imminent)
+                : context.getString(
+                        R.string.power_remaining_duration_shutdown_imminent,
+                        percentageString);
+    }
+
+    private static String getUnderFifteenString(Context context, CharSequence timeString,
+            String percentageString) {
+        return TextUtils.isEmpty(percentageString)
+                ? context.getString(R.string.power_remaining_less_than_duration_only, timeString)
+                : context.getString(
+                        R.string.power_remaining_less_than_duration,
+                        percentageString,
+                        timeString);
+
+    }
+
+    private static String getMoreThanOneDayString(Context context, String percentageString) {
+        final Locale currentLocale = context.getResources().getConfiguration().getLocales().get(0);
+        final MeasureFormat frmt = MeasureFormat.getInstance(currentLocale, FormatWidth.SHORT);
+
+        final Measure daysMeasure = new Measure(1, MeasureUnit.DAY);
+
+        return TextUtils.isEmpty(percentageString)
+                ? context.getString(R.string.power_remaining_only_more_than_subtext,
+                        frmt.formatMeasures(daysMeasure))
+                : context.getString(
+                        R.string.power_remaining_more_than_subtext,
+                        percentageString,
+                        frmt.formatMeasures(daysMeasure));
+    }
+
+    private static String getRegularTimeRemainingString(Context context, long drainTimeMs,
+            String percentageString, boolean basedOnUsage) {
+        // round to the nearest 15 min to not appear oversly precise
+        final long roundedTimeMs = roundToNearestThreshold(drainTimeMs,
+                FIFTEEN_MINUTES_MILLIS);
+        CharSequence timeString = StringUtil.formatElapsedTime(context,
+                roundedTimeMs,
+                false /* withSeconds */);
+        if (TextUtils.isEmpty(percentageString)) {
+            int id = basedOnUsage
+                    ? R.string.power_remaining_duration_only_enhanced
+                    : R.string.power_remaining_duration_only;
+            return context.getString(id, timeString);
+        } else {
+            int id = basedOnUsage
+                    ? R.string.power_discharging_duration_enhanced
+                    : R.string.power_discharging_duration;
+            return context.getString(id, percentageString, timeString);
+        }
+    }
+
+    public static long convertUsToMs(long timeUs) {
+        return timeUs / 1000;
+    }
+
+    public static long convertMsToUs(long timeMs) {
+        return timeMs * 1000;
+    }
+
+    private static long roundToNearestThreshold(long drainTime, long threshold) {
+        final long remainder = drainTime % threshold;
+        if (remainder < threshold / 2) {
+            return drainTime - remainder;
+        } else {
+            return drainTime - remainder + threshold;
+        }
+    }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/utils/StringUtil.java b/packages/SettingsLib/src/com/android/settingslib/utils/StringUtil.java
new file mode 100644
index 0000000..45fdd78
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/utils/StringUtil.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.utils;
+
+import android.content.Context;
+import android.icu.text.MeasureFormat;
+import android.icu.text.MeasureFormat.FormatWidth;
+import android.icu.text.RelativeDateTimeFormatter;
+import android.icu.text.RelativeDateTimeFormatter.RelativeUnit;
+import android.icu.util.Measure;
+import android.icu.util.MeasureUnit;
+import android.icu.util.ULocale;
+import android.text.SpannableStringBuilder;
+import android.text.Spanned;
+import android.text.style.TtsSpan;
+import java.util.ArrayList;
+import java.util.Locale;
+
+/** Utility class for generally useful string methods **/
+public class StringUtil {
+
+  public static final int SECONDS_PER_MINUTE = 60;
+  public static final int SECONDS_PER_HOUR = 60 * 60;
+  public static final int SECONDS_PER_DAY = 24 * 60 * 60;
+
+  /**
+   * Returns elapsed time for the given millis, in the following format:
+   * 2d 5h 40m 29s
+   * @param context the application context
+   * @param millis the elapsed time in milli seconds
+   * @param withSeconds include seconds?
+   * @return the formatted elapsed time
+   */
+  public static CharSequence formatElapsedTime(Context context, double millis,
+          boolean withSeconds) {
+      SpannableStringBuilder sb = new SpannableStringBuilder();
+      int seconds = (int) Math.floor(millis / 1000);
+      if (!withSeconds) {
+          // Round up.
+          seconds += 30;
+      }
+
+      int days = 0, hours = 0, minutes = 0;
+      if (seconds >= SECONDS_PER_DAY) {
+          days = seconds / SECONDS_PER_DAY;
+          seconds -= days * SECONDS_PER_DAY;
+      }
+      if (seconds >= SECONDS_PER_HOUR) {
+          hours = seconds / SECONDS_PER_HOUR;
+          seconds -= hours * SECONDS_PER_HOUR;
+      }
+      if (seconds >= SECONDS_PER_MINUTE) {
+          minutes = seconds / SECONDS_PER_MINUTE;
+          seconds -= minutes * SECONDS_PER_MINUTE;
+      }
+
+      final ArrayList<Measure> measureList = new ArrayList(4);
+      if (days > 0) {
+          measureList.add(new Measure(days, MeasureUnit.DAY));
+      }
+      if (hours > 0) {
+          measureList.add(new Measure(hours, MeasureUnit.HOUR));
+      }
+      if (minutes > 0) {
+          measureList.add(new Measure(minutes, MeasureUnit.MINUTE));
+      }
+      if (withSeconds && seconds > 0) {
+          measureList.add(new Measure(seconds, MeasureUnit.SECOND));
+      }
+      if (measureList.size() == 0) {
+          // Everything addable was zero, so nothing was added. We add a zero.
+          measureList.add(new Measure(0, withSeconds ? MeasureUnit.SECOND : MeasureUnit.MINUTE));
+      }
+      final Measure[] measureArray = measureList.toArray(new Measure[measureList.size()]);
+
+      final Locale locale = context.getResources().getConfiguration().locale;
+      final MeasureFormat measureFormat = MeasureFormat.getInstance(
+              locale, FormatWidth.NARROW);
+      sb.append(measureFormat.formatMeasures(measureArray));
+
+      if (measureArray.length == 1 && MeasureUnit.MINUTE.equals(measureArray[0].getUnit())) {
+          // Add ttsSpan if it only have minute value, because it will be read as "meters"
+          final TtsSpan ttsSpan = new TtsSpan.MeasureBuilder().setNumber(minutes)
+                  .setUnit("minute").build();
+          sb.setSpan(ttsSpan, 0, sb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+      }
+
+      return sb;
+  }
+
+    /**
+     * Returns relative time for the given millis in the past, in a short format such as "2 days
+     * ago", "5 hr. ago", "40 min. ago", or "29 sec. ago".
+     *
+     * <p>The unit is chosen to have good information value while only using one unit. So 27 hours
+     * and 50 minutes would be formatted as "28 hr. ago", while 50 hours would be formatted as
+     * "2 days ago".
+     *
+     * @param context the application context
+     * @param millis the elapsed time in milli seconds
+     * @param withSeconds include seconds?
+     * @return the formatted elapsed time
+     */
+    public static CharSequence formatRelativeTime(Context context, double millis,
+            boolean withSeconds) {
+        final int seconds = (int) Math.floor(millis / 1000);
+        final RelativeUnit unit;
+        final int value;
+        if (withSeconds && seconds < 2 * SECONDS_PER_MINUTE) {
+            unit = RelativeUnit.SECONDS;
+            value = seconds;
+        } else if (seconds < 2 * SECONDS_PER_HOUR) {
+            unit = RelativeUnit.MINUTES;
+            value = (seconds + SECONDS_PER_MINUTE / 2)
+                    / SECONDS_PER_MINUTE;
+        } else if (seconds < 2 * SECONDS_PER_DAY) {
+            unit = RelativeUnit.HOURS;
+            value = (seconds + SECONDS_PER_HOUR / 2)
+                    / SECONDS_PER_HOUR;
+        } else {
+            unit = RelativeUnit.DAYS;
+            value = (seconds + SECONDS_PER_DAY / 2)
+                    / SECONDS_PER_DAY;
+        }
+
+        final Locale locale = context.getResources().getConfiguration().locale;
+        final RelativeDateTimeFormatter formatter = RelativeDateTimeFormatter.getInstance(
+                ULocale.forLocale(locale),
+                null /* default NumberFormat */,
+                RelativeDateTimeFormatter.Style.SHORT,
+                android.icu.text.DisplayContext.CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE);
+
+        return formatter.format(value, RelativeDateTimeFormatter.Direction.LAST, unit);
+    }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
index f699440..c5c1169 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
@@ -17,6 +17,7 @@
 package com.android.settingslib.wifi;
 
 import android.annotation.IntDef;
+import android.annotation.MainThread;
 import android.annotation.Nullable;
 import android.app.AppGlobals;
 import android.content.Context;
@@ -42,6 +43,8 @@
 import android.net.wifi.WifiNetworkScoreCache;
 import android.net.wifi.hotspot2.PasspointConfiguration;
 import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
 import android.os.Parcelable;
 import android.os.RemoteException;
 import android.os.ServiceManager;
@@ -57,6 +60,7 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.settingslib.R;
+import com.android.settingslib.utils.ThreadUtils;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -68,7 +72,14 @@
 import java.util.Set;
 import java.util.concurrent.atomic.AtomicInteger;
 
-
+/**
+ * Represents a selectable Wifi Network for use in various wifi selection menus backed by
+ * {@link WifiTracker}.
+ *
+ * <p>An AccessPoint, which would be more fittingly named "WifiNetwork", is an aggregation of
+ * {@link ScanResult ScanResults} along with pertinent metadata (e.g. current connection info,
+ * network scores) required to successfully render the network to the user.
+ */
 public class AccessPoint implements Comparable<AccessPoint> {
     static final String TAG = "SettingsLib.AccessPoint";
 
@@ -288,11 +299,6 @@
         mId = sLastId.incrementAndGet();
     }
 
-    AccessPoint(Context context, AccessPoint other) {
-        mContext = context;
-        copyFrom(other);
-    }
-
     AccessPoint(Context context, Collection<ScanResult> results) {
         mContext = context;
 
@@ -346,33 +352,6 @@
     }
 
     /**
-     * Copy accesspoint information. NOTE: We do not copy tag information because that is never
-     * set on the internal copy.
-     */
-    void copyFrom(AccessPoint that) {
-        this.ssid = that.ssid;
-        this.bssid = that.bssid;
-        this.security = that.security;
-        this.mKey = that.mKey;
-        this.networkId = that.networkId;
-        this.pskType = that.pskType;
-        this.mConfig = that.mConfig; //TODO: Watch out, this object is mutated.
-        this.mRssi = that.mRssi;
-        this.mInfo = that.mInfo;
-        this.mNetworkInfo = that.mNetworkInfo;
-        this.mScanResults.clear();
-        this.mScanResults.addAll(that.mScanResults);
-        this.mScoredNetworkCache.clear();
-        this.mScoredNetworkCache.putAll(that.mScoredNetworkCache);
-        this.mId = that.mId;
-        this.mSpeed = that.mSpeed;
-        this.mIsScoredNetworkMetered = that.mIsScoredNetworkMetered;
-        this.mIsCarrierAp = that.mIsCarrierAp;
-        this.mCarrierApEapType = that.mCarrierApEapType;
-        this.mCarrierName = that.mCarrierName;
-    }
-
-    /**
     * Returns a negative integer, zero, or a positive integer if this AccessPoint is less than,
     * equal to, or greater than the other AccessPoint.
     *
@@ -467,7 +446,7 @@
         }
         builder.append(",metered=").append(isMetered());
 
-        if (WifiTracker.sVerboseLogging) {
+        if (isVerboseLoggingEnabled()) {
             builder.append(",rssi=").append(mRssi);
             builder.append(",scan cache size=").append(mScanResults.size());
         }
@@ -546,7 +525,7 @@
         mSpeed = generateAverageSpeedForSsid();
 
         boolean changed = oldSpeed != mSpeed;
-        if(WifiTracker.sVerboseLogging && changed) {
+        if(isVerboseLoggingEnabled() && changed) {
             Log.i(TAG, String.format("%s: Set speed to %d", ssid, mSpeed));
         }
         return changed;
@@ -577,7 +556,7 @@
             }
         }
         int speed = count == 0 ? Speed.NONE : totalSpeed / count;
-        if (WifiTracker.sVerboseLogging) {
+        if (isVerboseLoggingEnabled()) {
             Log.i(TAG, String.format("%s generated fallback speed is: %d", getSsidStr(), speed));
         }
         return roundToClosestSpeedEnum(speed);
@@ -913,7 +892,7 @@
             }
         }
 
-        if (WifiTracker.sVerboseLogging) {
+        if (isVerboseLoggingEnabled()) {
             summary.append(WifiUtils.buildLoggingSummary(this, config));
         }
 
@@ -1069,14 +1048,19 @@
         if (newLevel > 0 && newLevel != oldLevel) {
             // Only update labels on visible rssi changes
             updateSpeed();
-            if (mAccessPointListener != null) {
-                mAccessPointListener.onLevelChanged(this);
-            }
+            ThreadUtils.postOnMainThread(() -> {
+                if (mAccessPointListener != null) {
+                    mAccessPointListener.onLevelChanged(this);
+                }
+            });
+
         }
 
-        if (mAccessPointListener != null) {
-            mAccessPointListener.onAccessPointChanged(this);
-        }
+        ThreadUtils.postOnMainThread(() -> {
+            if (mAccessPointListener != null) {
+                mAccessPointListener.onAccessPointChanged(this);
+            }
+        });
 
         if (!scanResults.isEmpty()) {
             ScanResult result = scanResults.iterator().next();
@@ -1123,10 +1107,18 @@
             mNetworkInfo = null;
         }
         if (updated && mAccessPointListener != null) {
-            mAccessPointListener.onAccessPointChanged(this);
+            ThreadUtils.postOnMainThread(() -> {
+                if (mAccessPointListener != null) {
+                    mAccessPointListener.onAccessPointChanged(this);
+                }
+            });
 
             if (oldLevel != getLevel() /* current level */) {
-                mAccessPointListener.onLevelChanged(this);
+                ThreadUtils.postOnMainThread(() -> {
+                    if (mAccessPointListener != null) {
+                        mAccessPointListener.onLevelChanged(this);
+                    }
+                });
             }
         }
 
@@ -1136,9 +1128,11 @@
     void update(@Nullable WifiConfiguration config) {
         mConfig = config;
         networkId = config != null ? config.networkId : WifiConfiguration.INVALID_NETWORK_ID;
-        if (mAccessPointListener != null) {
-            mAccessPointListener.onAccessPointChanged(this);
-        }
+        ThreadUtils.postOnMainThread(() -> {
+            if (mAccessPointListener != null) {
+                mAccessPointListener.onAccessPointChanged(this);
+            }
+        });
     }
 
     @VisibleForTesting
@@ -1333,8 +1327,44 @@
         return string;
     }
 
+    /**
+     * Callbacks relaying changes to the AccessPoint representation.
+     *
+     * <p>All methods are invoked on the Main Thread.
+     */
     public interface AccessPointListener {
-        void onAccessPointChanged(AccessPoint accessPoint);
-        void onLevelChanged(AccessPoint accessPoint);
+        /**
+         * Indicates a change to the externally visible state of the AccessPoint trigger by an
+         * update of ScanResults, saved configuration state, connection state, or score
+         * (labels/metered) state.
+         *
+         * <p>Clients should refresh their view of the AccessPoint to match the updated state when
+         * this is invoked. Overall this method is extraneous if clients are listening to
+         * {@link WifiTracker.WifiListener#onAccessPointsChanged()} callbacks.
+         *
+         * <p>Examples of changes include signal strength, connection state, speed label, and
+         * generally anything that would impact the summary string.
+         *
+         * @param accessPoint The accessPoint object the listener was registered on which has
+         *                    changed
+         */
+        @MainThread void onAccessPointChanged(AccessPoint accessPoint);
+
+        /**
+         * Indicates the "wifi pie signal level" has changed, retrieved via calls to
+         * {@link AccessPoint#getLevel()}.
+         *
+         * <p>This call is a subset of {@link #onAccessPointChanged(AccessPoint)} , hence is also
+         * extraneous if the client is already reacting to that or the
+         * {@link WifiTracker.WifiListener#onAccessPointsChanged()} callbacks.
+         *
+         * @param accessPoint The accessPoint object the listener was registered on whose level has
+         *                    changed
+         */
+        @MainThread void onLevelChanged(AccessPoint accessPoint);
+    }
+
+    private static boolean isVerboseLoggingEnabled() {
+        return WifiTracker.sVerboseLogging || Log.isLoggable(TAG, Log.VERBOSE);
     }
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java
index 109eb97..8115ede2 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java
@@ -41,7 +41,7 @@
 import com.android.settingslib.Utils;
 import com.android.settingslib.wifi.AccessPoint.Speed;
 
-public class AccessPointPreference extends TwoTargetPreference {
+public class AccessPointPreference extends Preference {
 
     private static final int[] STATE_SECURED = {
             R.attr.state_encrypted
@@ -115,6 +115,7 @@
                           int iconResId, boolean forSavedNetworks, StateListDrawable frictionSld,
                           int level, IconInjector iconInjector) {
         super(context);
+        setWidgetLayoutResource(R.layout.access_point_friction_widget);
         mBadgeCache = cache;
         mAccessPoint = accessPoint;
         mForSavedNetworks = forSavedNetworks;
@@ -153,20 +154,6 @@
 
         ImageView frictionImageView = (ImageView) view.findViewById(R.id.friction_icon);
         bindFrictionImage(frictionImageView);
-        setDividerVisibility(view, View.GONE);
-    }
-
-    protected void setDividerVisibility(final PreferenceViewHolder view,
-            @View.Visibility int visibility) {
-        final View divider = view.findViewById(R.id.two_target_divider);
-        if (divider != null) {
-            divider.setVisibility(visibility);
-        }
-    }
-
-    @Override
-    protected int getSecondTargetResId() {
-        return R.layout.access_point_friction_widget;
     }
 
     protected void updateIcon(int level, Context context) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
index fac585e..ae544dd 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
@@ -15,6 +15,7 @@
  */
 package com.android.settingslib.wifi;
 
+import android.annotation.AnyThread;
 import android.annotation.MainThread;
 import android.content.BroadcastReceiver;
 import android.content.Context;
@@ -48,8 +49,6 @@
 import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.Log;
-import android.util.SparseArray;
-import android.util.SparseIntArray;
 import android.widget.Toast;
 
 import com.android.settingslib.R;
@@ -58,6 +57,7 @@
 import com.android.settingslib.core.lifecycle.events.OnDestroy;
 import com.android.settingslib.core.lifecycle.events.OnStart;
 import com.android.settingslib.core.lifecycle.events.OnStop;
+import com.android.settingslib.utils.ThreadUtils;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
@@ -88,8 +88,17 @@
         return Log.isLoggable(TAG, Log.DEBUG);
     }
 
-    /** verbose logging flag. this flag is set thru developer debugging options
-     * and used so as to assist with in-the-field WiFi connectivity debugging  */
+    private static boolean isVerboseLoggingEnabled() {
+        return WifiTracker.sVerboseLogging || Log.isLoggable(TAG, Log.VERBOSE);
+    }
+
+    /**
+     * Verbose logging flag set thru developer debugging options and used so as to assist with
+     * in-the-field WiFi connectivity debugging.
+     *
+     * <p>{@link #isVerboseLoggingEnabled()} should be read rather than referencing this value
+     * directly, to ensure adb TAG level verbose settings are respected.
+     */
     public static boolean sVerboseLogging;
 
     // TODO: Allow control of this?
@@ -104,7 +113,6 @@
     private final NetworkRequest mNetworkRequest;
     private final AtomicBoolean mConnected = new AtomicBoolean(false);
     private final WifiListener mListener;
-    @VisibleForTesting MainHandler mMainHandler;
     @VisibleForTesting WorkHandler mWorkHandler;
     private HandlerThread mWorkThread;
 
@@ -113,35 +121,17 @@
     @GuardedBy("mLock")
     private boolean mRegistered;
 
-    /**
-     * The externally visible access point list.
-     *
-     * Updated using main handler. Clone of this collection is returned from
-     * {@link #getAccessPoints()}
-     */
-    private final List<AccessPoint> mAccessPoints = new ArrayList<>();
-
-    /**
-     * The internal list of access points, synchronized on itself.
-     *
-     * Never exposed outside this class.
-     */
+    /** The list of AccessPoints, aggregated visible ScanResults with metadata. */
     @GuardedBy("mLock")
     private final List<AccessPoint> mInternalAccessPoints = new ArrayList<>();
 
     /**
     * Synchronization lock for managing concurrency between main and worker threads.
     *
-    * <p>This lock should be held for all background work.
-    * TODO(b/37674366): Remove the worker thread so synchronization is no longer necessary.
+    * <p>This lock should be held for all modifications to {@link #mInternalAccessPoints}.
     */
     private final Object mLock = new Object();
 
-    //visible to both worker and main thread.
-    @GuardedBy("mLock")
-    private final AccessPointListenerAdapter mAccessPointListenerAdapter
-            = new AccessPointListenerAdapter();
-
     private final HashMap<String, Integer> mSeenBssids = new HashMap<>();
 
     // TODO(sghuman): Change this to be keyed on AccessPoint.getKey
@@ -161,6 +151,12 @@
     @VisibleForTesting
     Scanner mScanner;
 
+    /**
+     * Tracks whether fresh scan results have been received since scanning start.
+     *
+     * <p>If this variable is false, we will not evict the scan result cache or invoke callbacks
+     * so that we do not update the UI with stale data / clear out existing UI elements prematurely.
+     */
     @GuardedBy("mLock")
     private boolean mStaleScanResults = true;
 
@@ -209,12 +205,11 @@
             NetworkScoreManager networkScoreManager,
             IntentFilter filter) {
         mContext = context;
-        mMainHandler = new MainHandler(Looper.getMainLooper());
         mWifiManager = wifiManager;
         mListener = new WifiListenerWrapper(wifiListener);
         mConnectivityManager = connectivityManager;
 
-        // check if verbose logging has been turned on or off
+        // check if verbose logging developer option has been turned on or off
         sVerboseLogging = (mWifiManager.getVerboseLoggingLevel() > 0);
 
         mFilter = filter;
@@ -226,6 +221,7 @@
 
         mNetworkScoreManager = networkScoreManager;
 
+        // TODO(sghuman): Remove this and create less hacky solution for testing
         final HandlerThread workThread = new HandlerThread(TAG
                 + "{" + Integer.toHexString(System.identityHashCode(this)) + "}",
                 Process.THREAD_PRIORITY_BACKGROUND);
@@ -238,6 +234,8 @@
      * @param workThread substitute Handler thread, for testing purposes only
      */
     @VisibleForTesting
+    // TODO(sghuman): Remove this method, this needs to happen in a factory method and be passed in
+    // during construction
     void setWorkThread(HandlerThread workThread) {
         mWorkThread = workThread;
         mWorkHandler = new WorkHandler(workThread.getLooper());
@@ -270,32 +268,29 @@
             mLastNetworkInfo = mConnectivityManager.getNetworkInfo(mWifiManager.getCurrentNetwork());
 
             final List<ScanResult> newScanResults = mWifiManager.getScanResults();
-            if (sVerboseLogging) {
+            if (isVerboseLoggingEnabled()) {
                 Log.i(TAG, "Fetched scan results: " + newScanResults);
             }
 
             List<WifiConfiguration> configs = mWifiManager.getConfiguredNetworks();
             mInternalAccessPoints.clear();
             updateAccessPointsLocked(newScanResults, configs);
-
-            // Synchronously copy access points
-            mMainHandler.removeMessages(MainHandler.MSG_ACCESS_POINT_CHANGED);
-            mMainHandler.handleMessage(
-                    Message.obtain(mMainHandler, MainHandler.MSG_ACCESS_POINT_CHANGED));
-            if (sVerboseLogging) {
-                Log.i(TAG, "force update - external access point list:\n" + mAccessPoints);
-            }
         }
     }
 
     /**
      * Temporarily stop scanning for wifi networks.
+     *
+     * <p>Sets {@link #mStaleScanResults} to true.
      */
-    public void pauseScanning() {
+    private void pauseScanning() {
         if (mScanner != null) {
             mScanner.pause();
             mScanner = null;
         }
+        synchronized (mLock) {
+            mStaleScanResults = true;
+        }
     }
 
     /**
@@ -387,11 +382,9 @@
                 mRegistered = false;
             }
             unregisterScoreCache();
-            pauseScanning();
+            pauseScanning(); // and set mStaleScanResults
 
             mWorkHandler.removePendingMessages();
-            mMainHandler.removePendingMessages();
-            mStaleScanResults = true;
         }
     }
 
@@ -409,12 +402,19 @@
     }
 
     /**
-     * Gets the current list of access points. Should be called from main thread, otherwise
-     * expect inconsistencies
+     * Gets the current list of access points.
+     *
+     * <p>This method is can be called on an abitrary thread by clients, but is normally called on
+     * the UI Thread by the rendering App.
      */
-    @MainThread
+    @AnyThread
     public List<AccessPoint> getAccessPoints() {
-        return new ArrayList<>(mAccessPoints);
+        // TODO(sghuman): Investigate how to eliminate or reduce the need for locking now that we
+        // have transitioned to a single worker thread model.
+
+        synchronized (mLock) {
+            return new ArrayList<>(mInternalAccessPoints);
+        }
     }
 
     public WifiManager getManager() {
@@ -447,6 +447,8 @@
     }
 
     private void handleResume() {
+        // TODO(sghuman): Investigate removing this and replacing it with a cache eviction call
+        // instead.
         mScanResultCache.clear();
         mSeenBssids.clear();
     }
@@ -509,7 +511,7 @@
     private void updateAccessPoints() {
         List<WifiConfiguration> configs = mWifiManager.getConfiguredNetworks();
         final List<ScanResult> newScanResults = mWifiManager.getScanResults();
-        if (sVerboseLogging) {
+        if (isVerboseLoggingEnabled()) {
             Log.i(TAG, "Fetched scan results: " + newScanResults);
         }
 
@@ -524,11 +526,15 @@
      * Update the internal list of access points.
      *
      * <p>Do not call directly (except for forceUpdate), use {@link #updateAccessPoints()} which
-     * respects {@link #mStaleScanResults}.
+     * acquires the lock first.
      */
     @GuardedBy("mLock")
     private void updateAccessPointsLocked(final List<ScanResult> newScanResults,
             List<WifiConfiguration> configs) {
+        // TODO(sghuman): Reduce the synchronization time by only holding the lock when
+        // modifying lists exposed to operations on the MainThread (getAccessPoints, stopTracking,
+        // startTracking, etc).
+
         WifiConfiguration connectionConfig = null;
         if (mLastInfo != null) {
             connectionConfig = getWifiConfigurationForNetworkId(
@@ -634,7 +640,7 @@
         mInternalAccessPoints.clear();
         mInternalAccessPoints.addAll(accessPoints);
 
-        mMainHandler.sendEmptyMessage(MainHandler.MSG_ACCESS_POINT_CHANGED);
+        conditionallyNotifyListeners();
     }
 
     @VisibleForTesting
@@ -650,7 +656,6 @@
             }
         }
         final AccessPoint accessPoint = new AccessPoint(mContext, scanResults);
-        accessPoint.setListener(mAccessPointListenerAdapter);
         return accessPoint;
     }
 
@@ -661,16 +666,17 @@
             if (cache.get(i).matches(config)) {
                 AccessPoint ret = cache.remove(i);
                 ret.loadConfig(config);
+
                 return ret;
             }
         }
         final AccessPoint accessPoint = new AccessPoint(mContext, config);
-        accessPoint.setListener(mAccessPointListenerAdapter);
         return accessPoint;
     }
 
     private void updateNetworkInfo(NetworkInfo networkInfo) {
-        /* sticky broadcasts can call this when wifi is disabled */
+
+        /* Sticky broadcasts can call this when wifi is disabled */
         if (!mWifiManager.isWifiEnabled()) {
             clearAccessPointsAndConditionallyUpdate();
             return;
@@ -681,6 +687,10 @@
             if (DBG()) {
                 Log.d(TAG, "mLastNetworkInfo set: " + mLastNetworkInfo);
             }
+
+            if(networkInfo.isConnected() != mConnected.getAndSet(networkInfo.isConnected())) {
+                mListener.onConnectedChanged();
+            }
         }
 
         WifiConfiguration connectionConfig = null;
@@ -711,18 +721,25 @@
                 }
             }
 
-            if (reorder) Collections.sort(mInternalAccessPoints);
-            if (updated) mMainHandler.sendEmptyMessage(MainHandler.MSG_ACCESS_POINT_CHANGED);
+            if (reorder) {
+                Collections.sort(mInternalAccessPoints);
+            }
+            if (updated) {
+                conditionallyNotifyListeners();
+            }
         }
     }
 
+    /**
+     * Clears the access point list and conditionally invokes
+     * {@link WifiListener#onAccessPointsChanged()} if required (i.e. the list was not already
+     * empty).
+     */
     private void clearAccessPointsAndConditionallyUpdate() {
         synchronized (mLock) {
             if (!mInternalAccessPoints.isEmpty()) {
                 mInternalAccessPoints.clear();
-                if (!mMainHandler.hasMessages(MainHandler.MSG_ACCESS_POINT_CHANGED)) {
-                    mMainHandler.sendEmptyMessage(MainHandler.MSG_ACCESS_POINT_CHANGED);
-                }
+                mListener.onAccessPointsChanged();
             }
         }
     }
@@ -745,27 +762,26 @@
             }
             if (updated) {
                 Collections.sort(mInternalAccessPoints);
-                mMainHandler.sendEmptyMessage(MainHandler.MSG_ACCESS_POINT_CHANGED);
+                conditionallyNotifyListeners();
             }
         }
     }
 
-    private void updateWifiState(int state) {
-        mWorkHandler.obtainMessage(WorkHandler.MSG_UPDATE_WIFI_STATE, state, 0).sendToTarget();
-        if (!mWifiManager.isWifiEnabled()) {
-            clearAccessPointsAndConditionallyUpdate();
-        }
-    }
-
     @VisibleForTesting
     final BroadcastReceiver mReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
+            // No work should be performed in this Receiver, instead all operations should be passed
+            // off to the WorkHandler to avoid concurrent modification exceptions.
+
             String action = intent.getAction();
 
             if (WifiManager.WIFI_STATE_CHANGED_ACTION.equals(action)) {
-                updateWifiState(intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
-                        WifiManager.WIFI_STATE_UNKNOWN));
+                mWorkHandler.obtainMessage(
+                        WorkHandler.MSG_UPDATE_WIFI_STATE,
+                        intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
+                            WifiManager.WIFI_STATE_UNKNOWN),
+                        0).sendToTarget();
             } else if (WifiManager.SCAN_RESULTS_AVAILABLE_ACTION.equals(action)) {
                 mWorkHandler
                         .obtainMessage(
@@ -778,12 +794,6 @@
                 mWorkHandler.sendEmptyMessage(WorkHandler.MSG_UPDATE_ACCESS_POINTS);
             } else if (WifiManager.NETWORK_STATE_CHANGED_ACTION.equals(action)) {
                 NetworkInfo info = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
-
-                if(mConnected.get() != info.isConnected()) {
-                    mConnected.set(info.isConnected());
-                    mMainHandler.sendEmptyMessage(MainHandler.MSG_CONNECTED_CHANGED);
-                }
-
                 mWorkHandler.obtainMessage(WorkHandler.MSG_UPDATE_NETWORK_INFO, info)
                         .sendToTarget();
                 mWorkHandler.sendEmptyMessage(WorkHandler.MSG_UPDATE_ACCESS_POINTS);
@@ -808,68 +818,8 @@
     }
 
     @VisibleForTesting
-    final class MainHandler extends Handler {
-        @VisibleForTesting static final int MSG_CONNECTED_CHANGED = 0;
-        @VisibleForTesting static final int MSG_WIFI_STATE_CHANGED = 1;
-        @VisibleForTesting static final int MSG_ACCESS_POINT_CHANGED = 2;
-        private static final int MSG_RESUME_SCANNING = 3;
-        private static final int MSG_PAUSE_SCANNING = 4;
-
-        public MainHandler(Looper looper) {
-            super(looper);
-        }
-
-        @Override
-        public void handleMessage(Message msg) {
-            if (mListener == null) {
-                return;
-            }
-            switch (msg.what) {
-                case MSG_CONNECTED_CHANGED:
-                    mListener.onConnectedChanged();
-                    break;
-                case MSG_WIFI_STATE_CHANGED:
-                    mListener.onWifiStateChanged(msg.arg1);
-                    break;
-                case MSG_ACCESS_POINT_CHANGED:
-                    // Only notify listeners of changes if we have fresh scan results, otherwise the
-                    // UI will be updated with stale results. We want to copy the APs regardless,
-                    // for instances where forceUpdate was invoked by the caller.
-                    if (mStaleScanResults) {
-                        copyAndNotifyListeners(false /*notifyListeners*/);
-                    } else {
-                        copyAndNotifyListeners(true /*notifyListeners*/);
-                        mListener.onAccessPointsChanged();
-                    }
-                    break;
-                case MSG_RESUME_SCANNING:
-                    if (mScanner != null) {
-                        mScanner.resume();
-                    }
-                    break;
-                case MSG_PAUSE_SCANNING:
-                    if (mScanner != null) {
-                        mScanner.pause();
-                    }
-                    synchronized (mLock) {
-                        mStaleScanResults = true;
-                    }
-                    break;
-            }
-        }
-
-        void removePendingMessages() {
-            removeMessages(MSG_ACCESS_POINT_CHANGED);
-            removeMessages(MSG_CONNECTED_CHANGED);
-            removeMessages(MSG_WIFI_STATE_CHANGED);
-            removeMessages(MSG_PAUSE_SCANNING);
-            removeMessages(MSG_RESUME_SCANNING);
-        }
-    }
-
-    @VisibleForTesting
     final class WorkHandler extends Handler {
-        private static final int MSG_UPDATE_ACCESS_POINTS = 0;
+        @VisibleForTesting static final int MSG_UPDATE_ACCESS_POINTS = 0;
         private static final int MSG_UPDATE_NETWORK_INFO = 1;
         private static final int MSG_RESUME = 2;
         private static final int MSG_UPDATE_WIFI_STATE = 3;
@@ -882,6 +832,8 @@
 
         @Override
         public void handleMessage(Message msg) {
+            // TODO(sghuman): Clean up synchronization to only be used when modifying collections
+            // exposed to the MainThread (through onStart, onStop, forceUpdate).
             synchronized (mLock) {
                 processMessage(msg);
             }
@@ -911,6 +863,7 @@
                             mScanner.resume();
                         }
                     } else {
+                        clearAccessPointsAndConditionallyUpdate();
                         mLastInfo = null;
                         mLastNetworkInfo = null;
                         if (mScanner != null) {
@@ -920,8 +873,7 @@
                             mStaleScanResults = true;
                         }
                     }
-                    mMainHandler.obtainMessage(MainHandler.MSG_WIFI_STATE_CHANGED, msg.arg1, 0)
-                            .sendToTarget();
+                    mListener.onWifiStateChanged(msg.arg1);
                     break;
             }
         }
@@ -1010,16 +962,26 @@
 
         @Override
         public void onWifiStateChanged(int state) {
+            if (isVerboseLoggingEnabled()) {
+                Log.i(TAG,
+                        String.format("Invoking onWifiStateChanged callback with state %d", state));
+            }
             mHandler.post(() -> mDelegatee.onWifiStateChanged(state));
         }
 
         @Override
         public void onConnectedChanged() {
+            if (isVerboseLoggingEnabled()) {
+                Log.i(TAG, "Invoking onConnectedChanged callback");
+            }
             mHandler.post(() -> mDelegatee.onConnectedChanged());
         }
 
         @Override
         public void onAccessPointsChanged() {
+            if (isVerboseLoggingEnabled()) {
+                Log.i(TAG, "Invoking onAccessPointsChanged callback");
+            }
             mHandler.post(() -> mDelegatee.onAccessPointsChanged());
         }
     }
@@ -1041,101 +1003,27 @@
         void onWifiStateChanged(int state);
 
         /**
-         * Called when the connection state of wifi has changed and isConnected
-         * should be called to get the updated state.
+         * Called when the connection state of wifi has changed and
+         * {@link WifiTracker#isConnected()} should be called to get the updated state.
          */
         void onConnectedChanged();
 
         /**
          * Called to indicate the list of AccessPoints has been updated and
-         * getAccessPoints should be called to get the latest information.
+         * {@link WifiTracker#getAccessPoints()} should be called to get the updated list.
          */
         void onAccessPointsChanged();
     }
 
     /**
-     * Helps capture notifications that were generated during AccessPoint modification. Used later
-     * on by {@link #copyAndNotifyListeners(boolean)} to send notifications.
+     * Invokes {@link WifiListenerWrapper#onAccessPointsChanged()} if {@link #mStaleScanResults}
+     * is false.
      */
-    private static class AccessPointListenerAdapter implements AccessPoint.AccessPointListener {
-        static final int AP_CHANGED = 1;
-        static final int LEVEL_CHANGED = 2;
-
-        final SparseIntArray mPendingNotifications = new SparseIntArray();
-
-        @Override
-        public void onAccessPointChanged(AccessPoint accessPoint) {
-            int type = mPendingNotifications.get(accessPoint.mId);
-            mPendingNotifications.put(accessPoint.mId, type | AP_CHANGED);
+    private void conditionallyNotifyListeners() {
+        if (mStaleScanResults) {
+            return;
         }
 
-        @Override
-        public void onLevelChanged(AccessPoint accessPoint) {
-            int type = mPendingNotifications.get(accessPoint.mId);
-            mPendingNotifications.put(accessPoint.mId, type | LEVEL_CHANGED);
-        }
-    }
-
-    /**
-     * Responsible for copying access points from {@link #mInternalAccessPoints} and notifying
-     * accesspoint listeners.
-     *
-     * @param notifyListeners if true, accesspoint listeners are notified, otherwise notifications
-     *                        dropped.
-     */
-    @MainThread
-    private void copyAndNotifyListeners(boolean notifyListeners) {
-        // Need to watch out for memory allocations on main thread.
-        SparseArray<AccessPoint> oldAccessPoints = new SparseArray<>();
-        SparseIntArray notificationMap = null;
-        List<AccessPoint> updatedAccessPoints = new ArrayList<>();
-
-        for (AccessPoint accessPoint : mAccessPoints) {
-            oldAccessPoints.put(accessPoint.mId, accessPoint);
-        }
-
-        synchronized (mLock) {
-            if (DBG()) {
-                Log.d(TAG, "Starting to copy AP items on the MainHandler. Internal APs: "
-                        + mInternalAccessPoints);
-            }
-
-            if (notifyListeners) {
-                notificationMap = mAccessPointListenerAdapter.mPendingNotifications.clone();
-            }
-
-            mAccessPointListenerAdapter.mPendingNotifications.clear();
-
-            for (AccessPoint internalAccessPoint : mInternalAccessPoints) {
-                AccessPoint accessPoint = oldAccessPoints.get(internalAccessPoint.mId);
-                if (accessPoint == null) {
-                    accessPoint = new AccessPoint(mContext, internalAccessPoint);
-                } else {
-                    accessPoint.copyFrom(internalAccessPoint);
-                }
-                updatedAccessPoints.add(accessPoint);
-            }
-        }
-
-        mAccessPoints.clear();
-        mAccessPoints.addAll(updatedAccessPoints);
-
-        if (notificationMap != null && notificationMap.size() > 0) {
-            for (AccessPoint accessPoint : updatedAccessPoints) {
-                int notificationType = notificationMap.get(accessPoint.mId);
-                AccessPoint.AccessPointListener listener = accessPoint.mAccessPointListener;
-                if (notificationType == 0 || listener == null) {
-                    continue;
-                }
-
-                if ((notificationType & AccessPointListenerAdapter.AP_CHANGED) != 0) {
-                    listener.onAccessPointChanged(accessPoint);
-                }
-
-                if ((notificationType & AccessPointListenerAdapter.LEVEL_CHANGED) != 0) {
-                    listener.onLevelChanged(accessPoint);
-                }
-            }
-        }
+        ThreadUtils.postOnMainThread(() -> mListener.onAccessPointsChanged());
     }
 }
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/drawer/SettingsDrawerActivityTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/drawer/SettingsDrawerActivityTest.java
index 003f905..2f417ad 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/drawer/SettingsDrawerActivityTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/drawer/SettingsDrawerActivityTest.java
@@ -18,8 +18,6 @@
 
 import static android.support.test.espresso.Espresso.onView;
 import static android.support.test.espresso.assertion.ViewAssertions.doesNotExist;
-import static android.support.test.espresso.assertion.ViewAssertions.matches;
-import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
 import static android.support.test.espresso.matcher.ViewMatchers.withContentDescription;
 
 import android.app.Instrumentation;
@@ -49,42 +47,22 @@
     }
 
     @Test
-    public void startActivityWithNoExtra_showNoNavUp() {
-        Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
-        instrumentation.startActivitySync(new Intent(instrumentation.getTargetContext(),
-                TestActivity.class));
-
-        onView(withContentDescription(com.android.internal.R.string.action_bar_up_description))
-                .check(doesNotExist());
-    }
-
-    @Test
-    public void startActivityWithExtraToHideMenu_showNavUp() {
-        Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
-        Intent intent = new Intent(instrumentation.getTargetContext(), TestActivity.class)
-                .putExtra(TestActivity.EXTRA_SHOW_MENU, false);
+    public void startActivity_doNotShowNavUp() {
+        final Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
+        final Intent intent = new Intent(instrumentation.getTargetContext(), TestActivity.class)
+                .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
         instrumentation.startActivitySync(intent);
 
         onView(withContentDescription(com.android.internal.R.string.action_bar_up_description))
                 .check(doesNotExist());
     }
 
-    @Test
-    public void startActivityWithExtraToShowMenu_showNavUp() {
-        Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
-        Intent intent = new Intent(instrumentation.getTargetContext(), TestActivity.class)
-                .putExtra(TestActivity.EXTRA_SHOW_MENU, true);
-        instrumentation.startActivitySync(intent);
-
-        onView(withContentDescription(com.android.internal.R.string.action_bar_up_description))
-                .check(matches(isDisplayed()));
-    }
-
     /**
      * Test Activity in this test.
      *
      * Use this activity because SettingsDrawerActivity hasn't been registered in its
      * AndroidManifest.xml
      */
-    public static class TestActivity extends SettingsDrawerActivity {}
+    public static class TestActivity extends SettingsDrawerActivity {
+    }
 }
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
index 1440311..54c02a2 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
@@ -113,38 +113,6 @@
     }
 
     @Test
-    public void testCopyAccessPoint_dataShouldMatch() {
-        WifiConfiguration configuration = createWifiConfiguration();
-        configuration.meteredHint = true;
-
-        NetworkInfo networkInfo =
-                new NetworkInfo(ConnectivityManager.TYPE_WIFI, 2, "WIFI", "WIFI_SUBTYPE");
-        AccessPoint originalAccessPoint = new AccessPoint(mContext, configuration);
-        WifiInfo wifiInfo = new WifiInfo();
-        wifiInfo.setSSID(WifiSsid.createFromAsciiEncoded(configuration.SSID));
-        wifiInfo.setBSSID(configuration.BSSID);
-        originalAccessPoint.update(configuration, wifiInfo, networkInfo);
-        AccessPoint copy = new AccessPoint(mContext, originalAccessPoint);
-
-        assertThat(originalAccessPoint.getSsid().toString()).isEqualTo(copy.getSsid().toString());
-        assertThat(originalAccessPoint.getBssid()).isEqualTo(copy.getBssid());
-        assertThat(originalAccessPoint.getConfig()).isEqualTo(copy.getConfig());
-        assertThat(originalAccessPoint.getSecurity()).isEqualTo(copy.getSecurity());
-        assertThat(originalAccessPoint.isMetered()).isEqualTo(copy.isMetered());
-        assertThat(originalAccessPoint.compareTo(copy) == 0).isTrue();
-    }
-
-    @Test
-    public void testThatCopyAccessPoint_scanCacheShouldMatch() {
-        AccessPoint original = createAccessPointWithScanResultCache();
-        assertThat(original.getRssi()).isEqualTo(4);
-        AccessPoint copy = new AccessPoint(mContext, createWifiConfiguration());
-        assertThat(copy.getRssi()).isEqualTo(AccessPoint.UNREACHABLE_RSSI);
-        copy.copyFrom(original);
-        assertThat(original.getRssi()).isEqualTo(copy.getRssi());
-    }
-
-    @Test
     public void testCompareTo_GivesActiveBeforeInactive() {
         AccessPoint activeAp = new TestAccessPointBuilder(mContext).setActive(true).build();
         AccessPoint inactiveAp = new TestAccessPointBuilder(mContext).setActive(false).build();
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
index 6be4936..0c49bb6 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
@@ -356,19 +356,14 @@
 
     private void waitForHandlersToProcessCurrentlyEnqueuedMessages(WifiTracker tracker)
             throws InterruptedException {
+        // TODO(sghuman): This should no longer be necessary in a single work handler model
+
         CountDownLatch workerLatch = new CountDownLatch(1);
         tracker.mWorkHandler.post(() -> {
             workerLatch.countDown();
         });
         assertTrue("Latch timed out while waiting for WorkerHandler",
                 workerLatch.await(LATCH_TIMEOUT, TimeUnit.MILLISECONDS));
-
-        CountDownLatch mainLatch = new CountDownLatch(1);
-        tracker.mMainHandler.post(() -> {
-            mainLatch.countDown();
-        });
-        assertTrue("Latch timed out while waiting for MainHandler",
-                mainLatch.await(LATCH_TIMEOUT, TimeUnit.MILLISECONDS));
     }
 
     private void switchToNetwork2(WifiTracker tracker) throws InterruptedException {
@@ -390,38 +385,6 @@
     }
 
     @Test
-    public void testAccessPointListenerSetWhenLookingUpUsingScanResults() {
-        ScanResult scanResult = new ScanResult();
-        scanResult.level = 123;
-        scanResult.BSSID = "bssid-" + 111;
-        scanResult.timestamp = SystemClock.elapsedRealtime() * 1000;
-        scanResult.capabilities = "";
-
-        WifiTracker tracker = new WifiTracker(
-                InstrumentationRegistry.getTargetContext(), null, true, true);
-
-        AccessPoint result = tracker.getCachedOrCreate(
-                Collections.singletonList(scanResult), new ArrayList<AccessPoint>());
-        assertTrue(result.mAccessPointListener != null);
-    }
-
-    @Test
-    public void testAccessPointListenerSetWhenLookingUpUsingWifiConfiguration() {
-        WifiConfiguration configuration = new WifiConfiguration();
-        configuration.SSID = "test123";
-        configuration.BSSID="bssid";
-        configuration.networkId = 123;
-        configuration.allowedKeyManagement = new BitSet();
-        configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
-
-        WifiTracker tracker = new WifiTracker(
-                InstrumentationRegistry.getTargetContext(), null, true, true);
-
-        AccessPoint result = tracker.getCachedOrCreate(configuration, new ArrayList<AccessPoint>());
-        assertTrue(result.mAccessPointListener != null);
-    }
-
-    @Test
     public void startAndStopTrackingShouldRegisterAndUnregisterScoreCache()
             throws InterruptedException {
         WifiTracker tracker = createMockedWifiTracker();
@@ -534,7 +497,6 @@
         waitForHandlersToProcessCurrentlyEnqueuedMessages(tracker);
     }
 
-    @FlakyTest
     @Test
     public void scoreCacheUpdateScoresShouldChangeSortOrder() throws InterruptedException {
         WifiTracker tracker =  createTrackerWithImmediateBroadcastsAndInjectInitialScanResults();
@@ -634,9 +596,9 @@
     public void scoresShouldBeRequestedForNewScanResultOnly()  throws InterruptedException {
         // Scores can be requested together or serially depending on how the scan results are
         // processed.
-        mRequestScoresLatch = new CountDownLatch(2);
+        mRequestScoresLatch = new CountDownLatch(1);
         WifiTracker tracker = createTrackerWithImmediateBroadcastsAndInjectInitialScanResults();
-        mRequestScoresLatch.await(LATCH_TIMEOUT, TimeUnit.MILLISECONDS);
+        assertTrue(mRequestScoresLatch.await(LATCH_TIMEOUT, TimeUnit.MILLISECONDS));
         mRequestedKeys.clear();
 
         String ssid = "ssid3";
@@ -770,7 +732,7 @@
         CountDownLatch ready = new CountDownLatch(1);
         CountDownLatch latch = new CountDownLatch(1);
         CountDownLatch lock = new CountDownLatch(1);
-        tracker.mMainHandler.post(() -> {
+        tracker.mWorkHandler.post(() -> {
             try {
                 ready.countDown();
                 lock.await();
@@ -781,12 +743,7 @@
         });
 
         // Enqueue messages
-        tracker.mMainHandler.sendEmptyMessage(
-                WifiTracker.MainHandler.MSG_ACCESS_POINT_CHANGED);
-        tracker.mMainHandler.sendEmptyMessage(
-                WifiTracker.MainHandler.MSG_CONNECTED_CHANGED);
-        tracker.mMainHandler.sendEmptyMessage(
-                WifiTracker.MainHandler.MSG_WIFI_STATE_CHANGED);
+        tracker.mWorkHandler.sendEmptyMessage(WifiTracker.WorkHandler.MSG_UPDATE_ACCESS_POINTS);
 
         try {
             ready.await(); // Make sure we have entered the first message handler
@@ -800,12 +757,9 @@
         lock.countDown();
         assertTrue("Latch timed out", latch.await(LATCH_TIMEOUT, TimeUnit.MILLISECONDS));
 
-        assertThat(tracker.mMainHandler.hasMessages(
-                WifiTracker.MainHandler.MSG_ACCESS_POINT_CHANGED)).isFalse();
-        assertThat(tracker.mMainHandler.hasMessages(
-                WifiTracker.MainHandler.MSG_CONNECTED_CHANGED)).isFalse();
-        assertThat(tracker.mMainHandler.hasMessages(
-                WifiTracker.MainHandler.MSG_WIFI_STATE_CHANGED)).isFalse();
+        assertThat(tracker.mWorkHandler.hasMessages(
+                WifiTracker.WorkHandler.MSG_UPDATE_ACCESS_POINTS)).isFalse();
+        waitForHandlersToProcessCurrentlyEnqueuedMessages(tracker);
 
         verifyNoMoreInteractions(mockWifiListener);
     }
@@ -862,7 +816,7 @@
         mAccessPointsChangedLatch = new CountDownLatch(1);
         tracker.mReceiver.onReceive(mContext, new Intent(WifiManager.WIFI_STATE_CHANGED_ACTION));
 
-        mAccessPointsChangedLatch.await(LATCH_TIMEOUT, TimeUnit.MILLISECONDS);
+        assertTrue(mAccessPointsChangedLatch.await(LATCH_TIMEOUT, TimeUnit.MILLISECONDS));
         waitForHandlersToProcessCurrentlyEnqueuedMessages(tracker);
 
         assertThat(tracker.getAccessPoints()).isEmpty();
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..706d0c0 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/UtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/UtilsTest.java
@@ -16,6 +16,9 @@
 package com.android.settingslib;
 
 import static android.Manifest.permission.WRITE_SECURE_SETTINGS;
+
+import static com.android.settingslib.Utils.STORAGE_MANAGER_SHOW_OPT_IN_PROPERTY;
+
 import static com.google.common.truth.Truth.assertThat;
 import static org.mockito.ArgumentMatchers.argThat;
 import static org.mockito.Matchers.eq;
@@ -30,13 +33,14 @@
 import android.content.Intent;
 import android.content.res.Resources;
 import android.location.LocationManager;
+import android.os.SystemProperties;
 import android.os.UserHandle;
 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 +54,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 {
@@ -136,7 +140,7 @@
     }
 
     @Test
-    public void testStorageManagerDaysToRetainUsesResources() {
+    public void testGetDefaultStorageManagerDaysToRetain_storageManagerDaysToRetainUsesResources() {
         Resources resources = mock(Resources.class);
         when(resources.getInteger(
                         eq(
@@ -149,6 +153,12 @@
         assertThat(Utils.getDefaultStorageManagerDaysToRetain(resources)).isEqualTo(60);
     }
 
+    @Test
+    public void testIsStorageManagerEnabled_UsesSystemProperties() {
+        SystemProperties.set(STORAGE_MANAGER_SHOW_OPT_IN_PROPERTY, "false");
+        assertThat(Utils.isStorageManagerEnabled(mContext)).isTrue();
+    }
+
     private static ArgumentMatcher<Intent> actionMatches(String expected) {
         return intent -> TextUtils.equals(expected, intent.getAction());
     }
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 4091ce1..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";
@@ -80,22 +75,12 @@
         doAnswer((invocation) -> mBatteryLevel).when(mCachedDevice).getBatteryLevel();
     }
 
-    /**
-     * Test to verify the current test context object works so that we are not checking null
-     * against null
-     */
-    @Test
-    public void testContextMock() {
-        assertThat(mContext.getString(R.string.bluetooth_connected)).isEqualTo("Connected");
-    }
-
     @Test
     public void testGetConnectionSummary_testSingleProfileConnectDisconnect() {
         // Test without battery level
         // Set PAN profile to be connected and test connection state summary
         mCachedDevice.onProfileStateChanged(mPanProfile, BluetoothProfile.STATE_CONNECTED);
-        assertThat(mCachedDevice.getConnectionSummary()).isEqualTo(mContext.getString(
-                R.string.bluetooth_connected));
+        assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Connected");
 
         // Set PAN profile to be disconnected and test connection state summary
         mCachedDevice.onProfileStateChanged(mPanProfile, BluetoothProfile.STATE_DISCONNECTED);
@@ -105,9 +90,7 @@
         mBatteryLevel = 10;
         // Set PAN profile to be connected and test connection state summary
         mCachedDevice.onProfileStateChanged(mPanProfile, BluetoothProfile.STATE_CONNECTED);
-        assertThat(mCachedDevice.getConnectionSummary()).isEqualTo(mContext.getString(
-                R.string.bluetooth_connected_battery_level,
-                com.android.settingslib.Utils.formatPercentage(mBatteryLevel)));
+        assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Connected, battery 10%");
 
         // Set PAN profile to be disconnected and test connection state summary
         mCachedDevice.onProfileStateChanged(mPanProfile, BluetoothProfile.STATE_DISCONNECTED);
@@ -118,8 +101,7 @@
 
         // Set PAN profile to be connected and test connection state summary
         mCachedDevice.onProfileStateChanged(mPanProfile, BluetoothProfile.STATE_CONNECTED);
-        assertThat(mCachedDevice.getConnectionSummary()).isEqualTo(mContext.getString(
-                R.string.bluetooth_connected));
+        assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Connected");
 
         // Set PAN profile to be disconnected and test connection state summary
         mCachedDevice.onProfileStateChanged(mPanProfile, BluetoothProfile.STATE_DISCONNECTED);
@@ -134,28 +116,23 @@
         mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
         mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
         mCachedDevice.onProfileStateChanged(mPanProfile, BluetoothProfile.STATE_CONNECTED);
-        assertThat(mCachedDevice.getConnectionSummary()).isEqualTo(mContext.getString(
-                R.string.bluetooth_connected_battery_level,
-                com.android.settingslib.Utils.formatPercentage(mBatteryLevel)));
+        assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Connected, battery 10%");
 
         // Disconnect HFP only and test connection state summary
         mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_DISCONNECTED);
-        assertThat(mCachedDevice.getConnectionSummary()).isEqualTo(mContext.getString(
-                R.string.bluetooth_connected_no_headset_battery_level,
-                com.android.settingslib.Utils.formatPercentage(mBatteryLevel)));
+        assertThat(mCachedDevice.getConnectionSummary()).isEqualTo(
+                "Connected (no phone), battery 10%");
 
         // Disconnect A2DP only and test connection state summary
         mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
         mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_DISCONNECTED);
-        assertThat(mCachedDevice.getConnectionSummary()).isEqualTo(mContext.getString(
-                R.string.bluetooth_connected_no_a2dp_battery_level,
-                com.android.settingslib.Utils.formatPercentage(mBatteryLevel)));
+        assertThat(mCachedDevice.getConnectionSummary()).isEqualTo(
+                "Connected (no media), battery 10%");
 
         // Disconnect both HFP and A2DP and test connection state summary
         mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_DISCONNECTED);
-        assertThat(mCachedDevice.getConnectionSummary()).isEqualTo(mContext.getString(
-                R.string.bluetooth_connected_no_headset_no_a2dp_battery_level,
-                com.android.settingslib.Utils.formatPercentage(mBatteryLevel)));
+        assertThat(mCachedDevice.getConnectionSummary()).isEqualTo(
+                "Connected (no phone or media), battery 10%");
 
         // Disconnect all profiles and test connection state summary
         mCachedDevice.onProfileStateChanged(mPanProfile, BluetoothProfile.STATE_DISCONNECTED);
@@ -163,6 +140,117 @@
     }
 
     @Test
+    public void testGetConnectionSummary_testSingleProfileActiveDeviceA2dp() {
+        // Test without battery level
+        // Set A2DP profile to be connected and test connection state summary
+        mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
+        assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Connected");
+
+        // Set device as Active for A2DP and test connection state summary
+        mCachedDevice.setActiveDevice(true, BluetoothProfile.A2DP);
+        assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Connected, active(media)");
+
+        // Test with battery level
+        mBatteryLevel = 10;
+        assertThat(mCachedDevice.getConnectionSummary()).isEqualTo(
+                "Connected, battery 10%, active(media)");
+
+        // Set A2DP profile to be disconnected and test connection state summary
+        mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_DISCONNECTED);
+        assertThat(mCachedDevice.getConnectionSummary()).isNull();
+
+        // Test with BluetoothDevice.BATTERY_LEVEL_UNKNOWN battery level
+        mBatteryLevel = BluetoothDevice.BATTERY_LEVEL_UNKNOWN;
+        // Set A2DP profile to be connected, Active and test connection state summary
+        mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
+        mCachedDevice.setActiveDevice(true, BluetoothProfile.A2DP);
+        assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Connected, active(media)");
+
+        // Set A2DP profile to be disconnected and test connection state summary
+        mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_DISCONNECTED);
+        assertThat(mCachedDevice.getConnectionSummary()).isNull();
+    }
+
+    @Test
+    public void testGetConnectionSummary_testSingleProfileActiveDeviceHfp() {
+        // Test without battery level
+        // Set HFP profile to be connected and test connection state summary
+        mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
+        assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Connected");
+
+        // Set device as Active for HFP and test connection state summary
+        mCachedDevice.setActiveDevice(true, BluetoothProfile.HEADSET);
+        assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Connected, active(phone)");
+
+        // Test with battery level
+        mBatteryLevel = 10;
+        assertThat(mCachedDevice.getConnectionSummary()).isEqualTo(
+                "Connected, battery 10%, active(phone)");
+
+        // Set HFP profile to be disconnected and test connection state summary
+        mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_DISCONNECTED);
+        assertThat(mCachedDevice.getConnectionSummary()).isNull();
+
+        // Test with BluetoothDevice.BATTERY_LEVEL_UNKNOWN battery level
+        mBatteryLevel = BluetoothDevice.BATTERY_LEVEL_UNKNOWN;
+        // Set HFP profile to be connected, Active and test connection state summary
+        mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
+        mCachedDevice.setActiveDevice(true, BluetoothProfile.HEADSET);
+        assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Connected, active(phone)");
+
+        // Set HFP profile to be disconnected and test connection state summary
+        mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_DISCONNECTED);
+        assertThat(mCachedDevice.getConnectionSummary()).isNull();
+    }
+
+    @Test
+    public void testGetConnectionSummary_testMultipleProfilesActiveDevice() {
+        // Test without battery level
+        // Set A2DP and HFP profiles to be connected and test connection state summary
+        mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
+        mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
+        assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Connected");
+
+        // Set device as Active for A2DP and HFP and test connection state summary
+        mCachedDevice.setActiveDevice(true, BluetoothProfile.A2DP);
+        mCachedDevice.setActiveDevice(true, BluetoothProfile.HEADSET);
+        assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Connected, active");
+
+        // Test with battery level
+        mBatteryLevel = 10;
+        assertThat(mCachedDevice.getConnectionSummary()).isEqualTo(
+                "Connected, battery 10%, active");
+
+        // Disconnect A2DP only and test connection state summary
+        mCachedDevice.setActiveDevice(false, BluetoothProfile.A2DP);
+        mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_DISCONNECTED);
+        assertThat(mCachedDevice.getConnectionSummary()).isEqualTo(
+                "Connected (no media), battery 10%, active(phone)");
+
+        // Disconnect HFP only and test connection state summary
+        mCachedDevice.setActiveDevice(false, BluetoothProfile.HEADSET);
+        mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_DISCONNECTED);
+        mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
+        mCachedDevice.setActiveDevice(true, BluetoothProfile.A2DP);
+        assertThat(mCachedDevice.getConnectionSummary()).isEqualTo(
+                "Connected (no phone), battery 10%, active(media)");
+
+        // Test with BluetoothDevice.BATTERY_LEVEL_UNKNOWN battery level
+        mBatteryLevel = BluetoothDevice.BATTERY_LEVEL_UNKNOWN;
+        // Set A2DP and HFP profiles to be connected, Active and test connection state summary
+        mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
+        mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
+        mCachedDevice.setActiveDevice(true, BluetoothProfile.A2DP);
+        mCachedDevice.setActiveDevice(true, BluetoothProfile.HEADSET);
+        assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Connected, active");
+
+        // Set A2DP and HFP profiles to be disconnected and test connection state summary
+        mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_DISCONNECTED);
+        mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_DISCONNECTED);
+        assertThat(mCachedDevice.getConnectionSummary()).isNull();
+    }
+
+    @Test
     public void testDeviceName_testAliasNameAvailable() {
         when(mDevice.getAliasName()).thenReturn(DEVICE_ALIAS);
         when(mDevice.getName()).thenReturn(DEVICE_NAME);
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..017d373 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,11 +30,8 @@
 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;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -42,10 +39,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";
@@ -164,18 +159,23 @@
     }
 
     private ArgumentMatcher<Pair<Integer, Object>> pairMatches(int tag, Class clazz) {
-        return pair -> pair.first == tag && Platform.isInstanceOfType(pair.second, clazz);
+        return pair -> pair.first == tag && isInstanceOfType(pair.second, clazz);
     }
 
     private ArgumentMatcher<Pair<Integer, Object>> pairMatches(int tag, boolean bool) {
         return pair -> pair.first == tag
-                && Platform.isInstanceOfType(pair.second, Integer.class)
+                && isInstanceOfType(pair.second, Integer.class)
                 && pair.second.equals((bool ? 1 : 0));
     }
 
     private ArgumentMatcher<Pair<Integer, Object>> pairMatches(int tag, int val) {
         return pair -> pair.first == tag
-                && Platform.isInstanceOfType(pair.second, Integer.class)
+                && isInstanceOfType(pair.second, Integer.class)
                 && pair.second.equals(val);
     }
+
+    /** Returns true if the instance is assignable to the type Clazz. */
+    private static boolean isInstanceOfType(Object instance, Class<?> clazz) {
+        return clazz.isInstance(instance);
+    }
 }
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 d19d19a..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,8 +22,9 @@
 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;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -31,7 +32,7 @@
 import org.robolectric.annotation.Config;
 
 @RunWith(SettingsLibRobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+@Config(shadows = ShadowUserManager.class)
 public class DevelopmentSettingsEnablerTest {
 
     private Context mContext;
@@ -39,10 +40,16 @@
     @Before
     public void setUp() {
         mContext = RuntimeEnvironment.application;
+        ShadowUserManager.getShadow().setIsAdminUser(true);
+    }
+
+    @After
+    public void tearDown() {
+        ShadowUserManager.getShadow().reset();
     }
 
     @Test
-    public void testEnabling() {
+    public void isEnabled_settingsOn_noRestriction_isAdmin_shouldReturnTrue() {
         Settings.Global.putInt(mContext.getContentResolver(),
                 Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 0);
 
@@ -54,7 +61,7 @@
     }
 
     @Test
-    public void testDisabling() {
+    public void isEnabled_settingsOff_noRestriction_isAdmin_shouldReturnFalse() {
         Settings.Global.putInt(mContext.getContentResolver(),
                 Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 1);
 
@@ -64,4 +71,13 @@
 
         assertThat(DevelopmentSettingsEnabler.isDevelopmentSettingsEnabled(mContext)).isFalse();
     }
+
+    @Test
+    public void isEnabled_settingsOn_noRestriction_notAdmin_shouldReturnFalse() {
+        Settings.Global.putInt(mContext.getContentResolver(),
+                Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 1);
+        ShadowUserManager.getShadow().setIsAdminUser(false);
+
+        assertThat(DevelopmentSettingsEnabler.isDevelopmentSettingsEnabled(mContext)).isFalse();
+    }
 }
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..72c8d1a 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
new file mode 100644
index 0000000..ccd2f53
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/EnableZenModeDialogTest.java
@@ -0,0 +1,194 @@
+/*
+ * 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.settingslib.notification;
+
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.assertNull;
+import static junit.framework.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.anyString;
+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.Fragment;
+import android.app.NotificationManager;
+import android.content.Context;
+import android.content.res.Resources;
+import android.net.Uri;
+import android.service.notification.Condition;
+import android.view.LayoutInflater;
+
+import com.android.settingslib.SettingsLibRobolectricTestRunner;
+
+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;
+
+@RunWith(SettingsLibRobolectricTestRunner.class)
+public class EnableZenModeDialogTest {
+    private EnableZenModeDialog mController;
+
+    @Mock
+    private Context mContext;
+    @Mock
+    private Resources mResources;
+    @Mock
+    private Fragment mFragment;
+    @Mock
+    private NotificationManager mNotificationManager;
+
+    private Context mShadowContext;
+    private LayoutInflater mLayoutInflater;
+    private Condition mCountdownCondition;
+    private Condition mAlarmCondition;
+
+    @Before
+    public void setup() {
+        MockitoAnnotations.initMocks(this);
+        mShadowContext = RuntimeEnvironment.application;
+        when(mContext.getApplicationContext()).thenReturn(mContext);
+        when(mContext.getResources()).thenReturn(mResources);
+        when(mFragment.getContext()).thenReturn(mShadowContext);
+        mLayoutInflater = LayoutInflater.from(mShadowContext);
+
+        mController = spy(new EnableZenModeDialog(mContext));
+        mController.mContext = mContext;
+        mController.mLayoutInflater = mLayoutInflater;
+        mController.mForeverId =  Condition.newId(mContext).appendPath("forever").build();
+        when(mContext.getString(com.android.internal.R.string.zen_mode_forever))
+                .thenReturn("testSummary");
+        NotificationManager.Policy alarmsEnabledPolicy = new NotificationManager.Policy(
+                NotificationManager.Policy.PRIORITY_CATEGORY_ALARMS, 0, 0, 0);
+        doReturn(alarmsEnabledPolicy).when(mNotificationManager).getNotificationPolicy();
+        mController.mNotificationManager = mNotificationManager;
+        mController.getContentView();
+
+        // these methods use static calls to ZenModeConfig which would normally fail in robotests,
+        // so instead do nothing:
+        doNothing().when(mController).bindGenericCountdown();
+        doReturn(null).when(mController).getTimeUntilNextAlarmCondition();
+        doReturn(0L).when(mController).getNextAlarm();
+        doNothing().when(mController).bindNextAlarm(any());
+
+        // as a result of doing nothing above, must bind manually:
+        Uri alarm =  Condition.newId(mContext).appendPath("alarm").build();
+        mAlarmCondition = new Condition(alarm, "alarm", "", "", 0, 0, 0);
+        Uri countdown =  Condition.newId(mContext).appendPath("countdown").build();
+        mCountdownCondition = new Condition(countdown, "countdown", "", "", 0, 0, 0);
+        mController.bind(mCountdownCondition,
+                mController.mZenRadioGroupContent.getChildAt(
+                        EnableZenModeDialog.COUNTDOWN_CONDITION_INDEX),
+                EnableZenModeDialog.COUNTDOWN_CONDITION_INDEX);
+        mController.bind(mAlarmCondition,
+                mController.mZenRadioGroupContent.getChildAt(
+                        EnableZenModeDialog.COUNTDOWN_ALARM_CONDITION_INDEX),
+                EnableZenModeDialog.COUNTDOWN_ALARM_CONDITION_INDEX);
+    }
+
+    @Test
+    public void testForeverChecked() {
+        mController.bindConditions(mController.forever());
+
+        assertTrue(mController.getConditionTagAt(EnableZenModeDialog.FOREVER_CONDITION_INDEX).rb
+                .isChecked());
+        assertFalse(mController.getConditionTagAt(EnableZenModeDialog.COUNTDOWN_CONDITION_INDEX).rb
+                .isChecked());
+        assertFalse(mController.getConditionTagAt(
+                EnableZenModeDialog.COUNTDOWN_ALARM_CONDITION_INDEX).rb.isChecked());
+    }
+
+    @Test
+    public void testNoneChecked() {
+        mController.bindConditions(null);
+        assertFalse(mController.getConditionTagAt(EnableZenModeDialog.FOREVER_CONDITION_INDEX).rb
+                .isChecked());
+        assertFalse(mController.getConditionTagAt(EnableZenModeDialog.COUNTDOWN_CONDITION_INDEX).rb
+                .isChecked());
+        assertFalse(mController.getConditionTagAt(
+                EnableZenModeDialog.COUNTDOWN_ALARM_CONDITION_INDEX).rb.isChecked());
+    }
+
+    @Test
+    public void testAlarmChecked() {
+        doReturn(false).when(mController).isCountdown(mAlarmCondition);
+        doReturn(true).when(mController).isAlarm(mAlarmCondition);
+
+        mController.bindConditions(mAlarmCondition);
+        assertFalse(mController.getConditionTagAt(EnableZenModeDialog.FOREVER_CONDITION_INDEX).rb
+                .isChecked());
+        assertFalse(mController.getConditionTagAt(EnableZenModeDialog.COUNTDOWN_CONDITION_INDEX).rb
+                .isChecked());
+        assertTrue(mController.getConditionTagAt(
+                EnableZenModeDialog.COUNTDOWN_ALARM_CONDITION_INDEX).rb.isChecked());
+    }
+
+    @Test
+    public void testCountdownChecked() {
+        doReturn(false).when(mController).isAlarm(mCountdownCondition);
+        doReturn(true).when(mController).isCountdown(mCountdownCondition);
+
+        mController.bindConditions(mCountdownCondition);
+        assertFalse(mController.getConditionTagAt(EnableZenModeDialog.FOREVER_CONDITION_INDEX).rb
+                .isChecked());
+        assertTrue(mController.getConditionTagAt(EnableZenModeDialog.COUNTDOWN_CONDITION_INDEX).rb
+                .isChecked());
+        assertFalse(mController.getConditionTagAt(
+                EnableZenModeDialog.COUNTDOWN_ALARM_CONDITION_INDEX).rb.isChecked());
+    }
+
+    @Test
+    public void testNoAlarmWarning() {
+        // setup alarm
+        long now = System.currentTimeMillis();
+        doReturn(now + 100000).when(mController).getNextAlarm();
+        doReturn("").when(mController).getTime(anyLong(), anyLong());
+
+        // allow alarms
+        when(mNotificationManager.getNotificationPolicy()).thenReturn(
+                new NotificationManager.Policy(
+                        NotificationManager.Policy.PRIORITY_CATEGORY_ALARMS, 0, 0, 0));
+
+        // alarm warning should be null
+        assertNull(mController.computeAlarmWarningText(null));
+    }
+
+    @Test
+    public void testAlarmWarning() {
+        // setup alarm
+        long now = System.currentTimeMillis();
+        doReturn(now + 1000000).when(mController).getNextAlarm();
+        doReturn("").when(mController).getTime(anyLong(), anyLong());
+
+        // don't allow alarms to bypass dnd
+        when(mNotificationManager.getNotificationPolicy()).thenReturn(
+                new NotificationManager.Policy(0, 0, 0, 0));
+
+        // return a string if mResources is asked to retrieve a string
+        when(mResources.getString(anyInt(), anyString())).thenReturn("");
+
+        // alarm warning should NOT be null
+        assertNotNull(mController.computeAlarmWarningText(null));
+    }
+}
\ No newline at end of file
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
new file mode 100644
index 0000000..a3e1bc8
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/testutils/shadow/ShadowUserManager.java
@@ -0,0 +1,56 @@
+/*
+ * 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.settingslib.testutils.shadow;
+
+import android.content.Context;
+import android.os.UserManager;
+
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+import org.robolectric.annotation.Resetter;
+import org.robolectric.shadow.api.Shadow;
+
+@Implements(value = UserManager.class, inheritImplementationMethods = true)
+public class ShadowUserManager extends org.robolectric.shadows.ShadowUserManager {
+
+    private boolean mAdminUser;
+
+    public void setIsAdminUser(boolean isAdminUser) {
+        mAdminUser = isAdminUser;
+    }
+
+    @Resetter
+    public void reset() {
+        mAdminUser = false;
+    }
+
+    @Implementation
+    public boolean isAdminUser() {
+        return mAdminUser;
+    }
+
+    @Implementation
+    public static UserManager get(Context context) {
+        return (UserManager) context.getSystemService(Context.USER_SERVICE);
+    }
+
+    public static ShadowUserManager getShadow() {
+        return (ShadowUserManager) Shadow.extract(
+                RuntimeEnvironment.application.getSystemService(UserManager.class));
+    }
+}
\ No newline at end of file
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
new file mode 100644
index 0000000..9285148f
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/PowerUtilTest.java
@@ -0,0 +1,161 @@
+/*
+ * 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.settingslib.utils;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.spy;
+
+import android.content.Context;
+
+import com.android.settingslib.R;
+import com.android.settingslib.SettingsLibRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+
+import java.time.Duration;
+
+@RunWith(SettingsLibRobolectricTestRunner.class)
+public class PowerUtilTest {
+    public static final String TEST_BATTERY_LEVEL_10 = "10%";
+    public static final String FIFTEEN_MIN_FORMATTED = "15m";
+    public static final long SEVENTEEN_MIN_MILLIS = Duration.ofMinutes(17).toMillis();
+    public static final long FIVE_MINUTES_MILLIS = Duration.ofMinutes(5).toMillis();
+    public static final long TEN_MINUTES_MILLIS = Duration.ofMinutes(10).toMillis();
+    public static final long TWO_DAYS_MILLIS = Duration.ofDays(2).toMillis();
+    public static final String ONE_DAY_FORMATTED = "1 day";
+
+    private Context mContext;
+
+    @Before
+    public void setup() {
+        MockitoAnnotations.initMocks(this);
+        mContext = spy(RuntimeEnvironment.application);
+    }
+
+    @Test
+    public void testGetBatteryRemainingStringFormatted_moreThanFifteenMinutes_withPercentage() {
+        String info = PowerUtil.getBatteryRemainingStringFormatted(mContext,
+                SEVENTEEN_MIN_MILLIS,
+                TEST_BATTERY_LEVEL_10,
+                true /* basedOnUsage */);
+        String info2 = PowerUtil.getBatteryRemainingStringFormatted(mContext,
+                SEVENTEEN_MIN_MILLIS,
+                TEST_BATTERY_LEVEL_10,
+                false /* basedOnUsage */);
+
+        // We only add special mention for the long string
+        assertThat(info).isEqualTo(mContext.getString(
+                R.string.power_discharging_duration_enhanced,
+                TEST_BATTERY_LEVEL_10,
+                FIFTEEN_MIN_FORMATTED));
+        // shortened string should not have extra text
+        assertThat(info2).isEqualTo(mContext.getString(
+                R.string.power_discharging_duration,
+                TEST_BATTERY_LEVEL_10,
+                FIFTEEN_MIN_FORMATTED));
+    }
+
+    @Test
+    public void testGetBatteryRemainingStringFormatted_moreThanFifteenMinutes_noPercentage() {
+        String info = PowerUtil.getBatteryRemainingStringFormatted(mContext,
+                SEVENTEEN_MIN_MILLIS,
+                null /* percentageString */,
+                true /* basedOnUsage */);
+        String info2 = PowerUtil.getBatteryRemainingStringFormatted(mContext,
+                SEVENTEEN_MIN_MILLIS,
+                null /* percentageString */,
+                false /* basedOnUsage */);
+
+        // We only add special mention for the long string
+        assertThat(info).isEqualTo(mContext.getString(
+                R.string.power_remaining_duration_only_enhanced,
+                FIFTEEN_MIN_FORMATTED));
+        // shortened string should not have extra text
+        assertThat(info2).isEqualTo(mContext.getString(
+                R.string.power_remaining_duration_only,
+                FIFTEEN_MIN_FORMATTED));
+    }
+
+
+    @Test
+    public void testGetBatteryRemainingStringFormatted_lessThanSevenMinutes_usesCorrectString() {
+        String info = PowerUtil.getBatteryRemainingStringFormatted(mContext,
+                FIVE_MINUTES_MILLIS,
+                TEST_BATTERY_LEVEL_10 /* percentageString */,
+                true /* basedOnUsage */);
+        String info2 = PowerUtil.getBatteryRemainingStringFormatted(mContext,
+                FIVE_MINUTES_MILLIS,
+                null /* percentageString */,
+                true /* basedOnUsage */);
+
+        // additional battery percentage in this string
+        assertThat(info).isEqualTo(mContext.getString(
+                R.string.power_remaining_duration_shutdown_imminent,
+                TEST_BATTERY_LEVEL_10));
+        // shortened string should not have percentage
+        assertThat(info2).isEqualTo(mContext.getString(
+                R.string.power_remaining_duration_only_shutdown_imminent));
+    }
+
+    @Test
+    public void testGetBatteryRemainingStringFormatted_betweenSevenAndFifteenMinutes_usesCorrectString() {
+        String info = PowerUtil.getBatteryRemainingStringFormatted(mContext,
+                TEN_MINUTES_MILLIS,
+                null /* percentageString */,
+                true /* basedOnUsage */);
+        String info2 = PowerUtil.getBatteryRemainingStringFormatted(mContext,
+                TEN_MINUTES_MILLIS,
+                TEST_BATTERY_LEVEL_10 /* percentageString */,
+                true /* basedOnUsage */);
+
+        // shortened string should not have percentage
+        assertThat(info).isEqualTo(mContext.getString(
+                R.string.power_remaining_less_than_duration_only,
+                FIFTEEN_MIN_FORMATTED));
+        // Add percentage to string when provided
+        assertThat(info2).isEqualTo(mContext.getString(
+                R.string.power_remaining_less_than_duration,
+                TEST_BATTERY_LEVEL_10,
+                FIFTEEN_MIN_FORMATTED));
+    }
+
+    @Test
+    public void testGetBatteryRemainingStringFormatted_moreThanOneDay_usesCorrectString() {
+        String info = PowerUtil.getBatteryRemainingStringFormatted(mContext,
+                TWO_DAYS_MILLIS,
+                null /* percentageString */,
+                true /* basedOnUsage */);
+        String info2 = PowerUtil.getBatteryRemainingStringFormatted(mContext,
+                TWO_DAYS_MILLIS,
+                TEST_BATTERY_LEVEL_10 /* percentageString */,
+                true /* basedOnUsage */);
+
+        // shortened string should not have percentage
+        assertThat(info).isEqualTo(mContext.getString(
+                R.string.power_remaining_only_more_than_subtext,
+                ONE_DAY_FORMATTED));
+        // Add percentage to string when provided
+        assertThat(info2).isEqualTo(mContext.getString(
+                R.string.power_remaining_more_than_subtext,
+                TEST_BATTERY_LEVEL_10,
+                ONE_DAY_FORMATTED));
+    }
+}
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
new file mode 100644
index 0000000..47dd022
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/StringUtilTest.java
@@ -0,0 +1,212 @@
+/*
+ * 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.settingslib.utils;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.spy;
+
+import android.content.Context;
+import android.text.SpannableStringBuilder;
+import android.text.format.DateUtils;
+import android.text.style.TtsSpan;
+
+import com.android.settingslib.SettingsLibRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(SettingsLibRobolectricTestRunner.class)
+public class StringUtilTest {
+    private Context mContext;
+
+    @Before
+    public void setUp() {
+        mContext = spy(RuntimeEnvironment.application);
+    }
+
+    @Test
+    public void testFormatElapsedTime_WithSeconds_ShowSeconds() {
+        final double testMillis = 5 * DateUtils.MINUTE_IN_MILLIS + 30 * DateUtils.SECOND_IN_MILLIS;
+        final String expectedTime = "5m 30s";
+
+        assertThat(StringUtil.formatElapsedTime(mContext, testMillis, true).toString())
+                .isEqualTo(expectedTime);
+    }
+
+    @Test
+    public void testFormatElapsedTime_NoSeconds_DoNotShowSeconds() {
+        final double testMillis = 5 * DateUtils.MINUTE_IN_MILLIS + 30 * DateUtils.SECOND_IN_MILLIS;
+        final String expectedTime = "6m";
+
+        assertThat(StringUtil.formatElapsedTime(mContext, testMillis, false).toString())
+                .isEqualTo(expectedTime);
+    }
+
+    @Test
+    public void testFormatElapsedTime_TimeMoreThanOneDay_ShowCorrectly() {
+        final double testMillis = 2 * DateUtils.DAY_IN_MILLIS
+                + 4 * DateUtils.HOUR_IN_MILLIS + 15 * DateUtils.MINUTE_IN_MILLIS;
+        final String expectedTime = "2d 4h 15m";
+
+        assertThat(StringUtil.formatElapsedTime(mContext, testMillis, false).toString())
+                .isEqualTo(expectedTime);
+    }
+
+    @Test
+    public void testFormatElapsedTime_ZeroFieldsInTheMiddleDontShow() {
+        final double testMillis = 2 * DateUtils.DAY_IN_MILLIS + 15 * DateUtils.MINUTE_IN_MILLIS;
+        final String expectedTime = "2d 15m";
+
+        assertThat(StringUtil.formatElapsedTime(mContext, testMillis, false).toString())
+                .isEqualTo(expectedTime);
+    }
+
+    @Test
+    public void testFormatElapsedTime_FormatZero_WithSeconds() {
+        final double testMillis = 0;
+        final String expectedTime = "0s";
+
+        assertThat(StringUtil.formatElapsedTime(mContext, testMillis, true).toString())
+                .isEqualTo(expectedTime);
+    }
+
+    @Test
+    public void testFormatElapsedTime_FormatZero_NoSeconds() {
+        final double testMillis = 0;
+        final String expectedTime = "0m";
+
+        assertThat(StringUtil.formatElapsedTime(mContext, testMillis, false).toString())
+                .isEqualTo(expectedTime);
+    }
+
+    @Test
+    public void testFormatElapsedTime_onlyContainsMinute_hasTtsSpan() {
+        final double testMillis = 15 * DateUtils.MINUTE_IN_MILLIS;
+
+        final CharSequence charSequence =
+                StringUtil.formatElapsedTime(mContext, testMillis, false);
+        assertThat(charSequence).isInstanceOf(SpannableStringBuilder.class);
+
+        final SpannableStringBuilder expectedString = (SpannableStringBuilder) charSequence;
+        final TtsSpan[] ttsSpans = expectedString.getSpans(0, expectedString.length(),
+                TtsSpan.class);
+
+        assertThat(ttsSpans).asList().hasSize(1);
+        assertThat(ttsSpans[0].getType()).isEqualTo(TtsSpan.TYPE_MEASURE);
+    }
+
+    @Test
+    public void testFormatRelativeTime_WithSeconds_ShowSeconds() {
+        final double testMillis = 40 * DateUtils.SECOND_IN_MILLIS;
+        final String expectedTime = "40 sec. ago";
+
+        assertThat(StringUtil.formatRelativeTime(mContext, testMillis, true).toString()).isEqualTo(
+                expectedTime);
+    }
+
+    @Test
+    public void testFormatRelativeTime_NoSeconds_DoNotShowSeconds() {
+        final double testMillis = 40 * DateUtils.SECOND_IN_MILLIS;
+        final String expectedTime = "1 min. ago";
+
+        assertThat(StringUtil.formatRelativeTime(mContext, testMillis, false).toString()).isEqualTo(
+                expectedTime);
+    }
+
+    @Test
+    public void testFormatRelativeTime_LessThanTwoMinutes_withSeconds() {
+        final double testMillis = 119 * DateUtils.SECOND_IN_MILLIS;
+        final String expectedTime = "119 sec. ago";
+
+        assertThat(StringUtil.formatRelativeTime(mContext, testMillis, true).toString()).isEqualTo(
+                expectedTime);
+    }
+
+    @Test
+    public void testFormatRelativeTime_LessThanTwoMinutes_NoSeconds() {
+        final double testMillis = 119 * DateUtils.SECOND_IN_MILLIS;
+        final String expectedTime = "2 min. ago";
+
+        assertThat(StringUtil.formatRelativeTime(mContext, testMillis, false).toString()).isEqualTo(
+                expectedTime);
+    }
+
+    @Test
+    public void testFormatRelativeTime_TwoMinutes_withSeconds() {
+        final double testMillis = 2 * DateUtils.MINUTE_IN_MILLIS;
+        final String expectedTime = "2 min. ago";
+
+        assertThat(StringUtil.formatRelativeTime(mContext, testMillis, true).toString()).isEqualTo(
+                expectedTime);
+    }
+
+    @Test
+    public void testFormatRelativeTime_LessThanTwoHours_withSeconds() {
+        final double testMillis = 119 * DateUtils.MINUTE_IN_MILLIS;
+        final String expectedTime = "119 min. ago";
+
+        assertThat(StringUtil.formatRelativeTime(mContext, testMillis, true).toString()).isEqualTo(
+                expectedTime);
+    }
+
+    @Test
+    public void testFormatRelativeTime_TwoHours_withSeconds() {
+        final double testMillis = 2 * DateUtils.HOUR_IN_MILLIS;
+        final String expectedTime = "2 hr. ago";
+
+        assertThat(StringUtil.formatRelativeTime(mContext, testMillis, true).toString()).isEqualTo(
+                expectedTime);
+    }
+
+    @Test
+    public void testFormatRelativeTime_LessThanTwoDays_withSeconds() {
+        final double testMillis = 47 * DateUtils.HOUR_IN_MILLIS;
+        final String expectedTime = "47 hr. ago";
+
+        assertThat(StringUtil.formatRelativeTime(mContext, testMillis, true).toString()).isEqualTo(
+                expectedTime);
+    }
+
+    @Test
+    public void testFormatRelativeTime_TwoDays_withSeconds() {
+        final double testMillis = 2 * DateUtils.DAY_IN_MILLIS;
+        final String expectedTime = "2 days ago";
+
+        assertThat(StringUtil.formatRelativeTime(mContext, testMillis, true).toString()).isEqualTo(
+                expectedTime);
+    }
+
+    @Test
+    public void testFormatRelativeTime_FormatZero_WithSeconds() {
+        final double testMillis = 0;
+        final String expectedTime = "0 sec. ago";
+
+        assertThat(StringUtil.formatRelativeTime(mContext, testMillis, true).toString()).isEqualTo(
+                expectedTime);
+    }
+
+    @Test
+    public void testFormatRelativeTime_FormatZero_NoSeconds() {
+        final double testMillis = 0;
+        final String expectedTime = "0 min. ago";
+
+        assertThat(StringUtil.formatRelativeTime(mContext, testMillis, false).toString()).isEqualTo(
+                expectedTime);
+    }
+}
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/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml
index 48a3a30..d59df6c 100644
--- a/packages/SettingsProvider/res/values/defaults.xml
+++ b/packages/SettingsProvider/res/values/defaults.xml
@@ -196,4 +196,7 @@
 
     <!-- Default setting for Settings.Global.MOBILE_DATA_ALWAYS_ON -->
     <bool name="def_mobile_data_always_on">true</bool>
+
+    <!-- Default for Settings.Secure.BACKUP_LOCAL_TRANSPORT_PARAMETERS -->
+    <string name="def_backup_local_transport_parameters"></string>
 </resources>
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index 1dc8e46..cfcfb95 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -43,7 +43,6 @@
 import android.text.TextUtils;
 import android.util.Log;
 
-import com.android.ims.ImsConfig;
 import com.android.internal.content.PackageHelper;
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.RILConstants;
@@ -1504,7 +1503,7 @@
                 try {
                     stmt = db.compileStatement("INSERT OR REPLACE INTO global(name,value)"
                             + " VALUES(?,?);");
-                    loadStringSetting(stmt, Settings.Global.WIRELESS_CHARGING_STARTED_SOUND,
+                    loadStringSetting(stmt, Settings.Global.CHARGING_STARTED_SOUND,
                             R.string.def_wireless_charging_started_sound);
                     db.setTransactionSuccessful();
                 } finally {
@@ -2578,7 +2577,7 @@
                     R.string.def_car_dock_sound);
             loadStringSetting(stmt, Settings.Global.CAR_UNDOCK_SOUND,
                     R.string.def_car_undock_sound);
-            loadStringSetting(stmt, Settings.Global.WIRELESS_CHARGING_STARTED_SOUND,
+            loadStringSetting(stmt, Settings.Global.CHARGING_STARTED_SOUND,
                     R.string.def_wireless_charging_started_sound);
 
             loadIntegerSetting(stmt, Settings.Global.DOCK_AUDIO_MEDIA_ENABLED,
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
index 91957e1..ad422d8 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
@@ -76,11 +76,10 @@
      */
     private static final ArraySet<String> sBroadcastOnRestore;
     static {
-        sBroadcastOnRestore = new ArraySet<String>(5);
+        sBroadcastOnRestore = new ArraySet<String>(4);
         sBroadcastOnRestore.add(Settings.Secure.ENABLED_NOTIFICATION_LISTENERS);
         sBroadcastOnRestore.add(Settings.Secure.ENABLED_VR_LISTENERS);
         sBroadcastOnRestore.add(Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
-        sBroadcastOnRestore.add(Settings.Secure.ENABLED_INPUT_METHODS);
         sBroadcastOnRestore.add(Settings.Global.BLUETOOTH_ON);
     }
 
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index 537e8dc..0fee81be 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -160,7 +160,7 @@
                 Settings.Global.POWER_SOUNDS_ENABLED,
                 GlobalSettingsProto.POWER_SOUNDS_ENABLED);
         dumpSetting(s, p,
-                Settings.Global.WIRELESS_CHARGING_STARTED_SOUND,
+                Settings.Global.CHARGING_STARTED_SOUND,
                 GlobalSettingsProto.WIRELESS_CHARGING_STARTED_SOUND);
         dumpSetting(s, p,
                 Settings.Global.CHARGING_SOUNDS_ENABLED,
@@ -870,6 +870,12 @@
         dumpSetting(s, p,
                 Settings.Global.ENABLE_GNSS_RAW_MEAS_FULL_TRACKING,
                 GlobalSettingsProto.ENABLE_GNSS_RAW_MEAS_FULL_TRACKING);
+        dumpSetting(s, p,
+                Settings.Global.INSTALL_CARRIER_APP_NOTIFICATION_PERSISTENT,
+                GlobalSettingsProto.INSTALL_CARRIER_APP_NOTIFICATION_PERSISTENT);
+        dumpSetting(s, p,
+                Settings.Global.INSTALL_CARRIER_APP_NOTIFICATION_SLEEP_MILLIS,
+                GlobalSettingsProto.INSTALL_CARRIER_APP_NOTIFICATION_SLEEP_MILLIS);
         // Settings.Global.SHOW_PROCESSES intentionally excluded since it's deprecated.
         dumpSetting(s, p,
                 Settings.Global.LOW_POWER_MODE,
@@ -1055,6 +1061,9 @@
                 Global.CHAINED_BATTERY_ATTRIBUTION_ENABLED,
                 GlobalSettingsProto.CHAINED_BATTERY_ATTRIBUTION_ENABLED);
         dumpSetting(s, p,
+                Global.HIDDEN_API_BLACKLIST_EXEMPTIONS,
+                GlobalSettingsProto.HIDDEN_API_BLACKLIST_EXEMPTIONS);
+        dumpSetting(s, p,
                 Settings.Global.MULTI_SIM_VOICE_CALL_SUBSCRIPTION,
                 GlobalSettingsProto.MULTI_SIM_VOICE_CALL_SUBSCRIPTION);
         dumpSetting(s, p,
@@ -1112,8 +1121,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);
@@ -1123,6 +1132,9 @@
         dumpSetting(s, p,
                 Settings.Global.SHOW_MUTE_IN_CRASH_DIALOG,
                 GlobalSettingsProto.SHOW_MUTE_IN_CRASH_DIALOG);
+        dumpSetting(s, p,
+                Settings.Global.SHOW_ZEN_UPGRADE_NOTIFICATION,
+                GlobalSettingsProto.SHOW_ZEN_UPGRADE_NOTIFICATION);
 
         // Please insert new settings using the same order as in Settings.Global.
     }
@@ -1750,6 +1762,9 @@
                 Settings.Secure.BACKUP_MANAGER_CONSTANTS,
                 SecureSettingsProto.BACKUP_MANAGER_CONSTANTS);
         dumpSetting(s, p,
+                Settings.Secure.BACKUP_LOCAL_TRANSPORT_PARAMETERS,
+                SecureSettingsProto.BACKUP_LOCAL_TRANSPORT_PARAMETERS);
+        dumpSetting(s, p,
                 Settings.Secure.BLUETOOTH_ON_WHILE_DRIVING,
                 SecureSettingsProto.BLUETOOTH_ON_WHILE_DRIVING);
 
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 85a579d..bbb4fc8 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -1591,6 +1591,7 @@
     private boolean isGlobalOrSecureSettingRestrictedForUser(String setting, int userId,
             String value, int callingUid) {
         String restriction;
+        boolean checkAllUser = false;
         switch (setting) {
             case Settings.Secure.LOCATION_MODE:
                 // Note LOCATION_MODE will be converted into LOCATION_PROVIDERS_ALLOWED
@@ -1656,6 +1657,12 @@
                 restriction = UserManager.DISALLOW_AMBIENT_DISPLAY;
                 break;
 
+            case Global.LOCATION_GLOBAL_KILL_SWITCH:
+                if ("0".equals(value)) return false;
+                restriction = UserManager.DISALLOW_CONFIG_LOCATION;
+                checkAllUser = true;
+                break;
+
             default:
                 if (setting != null && setting.startsWith(Settings.Global.DATA_ROAMING)) {
                     if ("0".equals(value)) return false;
@@ -1665,7 +1672,11 @@
                 return false;
         }
 
-        return mUserManager.hasUserRestriction(restriction, UserHandle.of(userId));
+        if (checkAllUser) {
+            return mUserManager.hasUserRestrictionOnAnyUser(restriction);
+        } else {
+            return mUserManager.hasUserRestriction(restriction, UserHandle.of(userId));
+        }
     }
 
     private int resolveOwningUserIdForSecureSettingLocked(int userId, String setting) {
@@ -3017,7 +3028,7 @@
         }
 
         private final class UpgradeController {
-            private static final int SETTINGS_VERSION = 154;
+            private static final int SETTINGS_VERSION = 155;
 
             private final int mUserId;
 
@@ -3644,6 +3655,24 @@
                     currentVersion = 154;
                 }
 
+                if (currentVersion == 154) {
+                    // Version 155: Set the default value for BACKUP_LOCAL_TRANSPORT_PARAMETERS.
+                    final SettingsState systemSecureSettings = getSecureSettingsLocked(userId);
+                    final String oldValue = systemSecureSettings.getSettingLocked(
+                            Settings.Secure.BACKUP_LOCAL_TRANSPORT_PARAMETERS).getValue();
+                    if (TextUtils.equals(null, oldValue)) {
+                        final String defaultValue = getContext().getResources().getString(
+                                R.string.def_backup_local_transport_parameters);
+                        if (!TextUtils.isEmpty(defaultValue)) {
+                            systemSecureSettings.insertSettingLocked(
+                                    Settings.Secure.BACKUP_LOCAL_TRANSPORT_PARAMETERS, defaultValue,
+                                    null, true, SettingsState.SYSTEM_PACKAGE_NAME);
+                        }
+
+                    }
+                    currentVersion = 155;
+                }
+
                 // vXXX: Add new settings above this point.
 
                 if (currentVersion != newVersion) {
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 64b2ae6..5c8d745 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -138,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/SimAppDialog/Android.mk b/packages/SimAppDialog/Android.mk
new file mode 100644
index 0000000..00a2e60
--- /dev/null
+++ b/packages/SimAppDialog/Android.mk
@@ -0,0 +1,18 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := SimAppDialog
+LOCAL_CERTIFICATE := platform
+
+
+LOCAL_STATIC_ANDROID_LIBRARIES := \
+    android-support-v4
+
+LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
+include frameworks/opt/setupwizard/library/common-platform-deprecated.mk
+
+include $(BUILD_PACKAGE)
diff --git a/packages/SimAppDialog/AndroidManifest.xml b/packages/SimAppDialog/AndroidManifest.xml
new file mode 100644
index 0000000..873f6c5
--- /dev/null
+++ b/packages/SimAppDialog/AndroidManifest.xml
@@ -0,0 +1,29 @@
+<?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.simappdialog">
+    <application android:label="@string/app_name">
+        <activity
+            android:name=".InstallCarrierAppActivity"
+            android:exported="true"
+            android:permission="android.permission.NETWORK_SETTINGS"
+            android:theme="@style/SuwThemeGlif.Light">
+        </activity>
+    </application>
+</manifest>
diff --git a/packages/SimAppDialog/res/drawable/ic_signal_cellular_alt_rounded_24px.xml b/packages/SimAppDialog/res/drawable/ic_signal_cellular_alt_rounded_24px.xml
new file mode 100644
index 0000000..85896e8
--- /dev/null
+++ b/packages/SimAppDialog/res/drawable/ic_signal_cellular_alt_rounded_24px.xml
@@ -0,0 +1,51 @@
+<?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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="21dp"
+        android:height="22dp"
+        android:viewportWidth="21"
+        android:viewportHeight="22">
+
+    <group
+        android:translateX="-196.000000"
+        android:translateY="-77.000000">
+        <group
+            android:translateX="190.000000"
+            android:translateY="72.000000">
+            <path
+                android:fillType="evenOdd"
+                android:strokeWidth="1"
+                android:pathData="M 0 0 H 32 V 32 H 0 V 0 Z"/>
+            <group
+                android:translateX="6.666667"
+                android:translateY="5.333333">
+                <path
+                    android:fillColor="#4285F4"
+                    android:strokeWidth="1"
+                    android:pathData="M 17 0 L 19 0 Q 20 0 20 1 L 20 20.3333333 Q 20 21.3333333 19 21.3333333 L 17 21.3333333 Q 16 21.3333333 16 20.3333333 L 16 1 Q 16 0 17 0 Z"/>
+                <path
+                    android:fillColor="#4285F4"
+                    android:strokeWidth="1"
+                    android:pathData="M 1 13.3333333 L 3 13.3333333 Q 4 13.3333333 4 14.3333333 L 4 20.3333333 Q 4 21.3333333 3 21.3333333 L 1 21.3333333 Q 0 21.3333333 0 20.3333333 L 0 14.3333333 Q 0 13.3333333 1 13.3333333 Z"/>
+                <path
+                    android:fillColor="#4285F4"
+                    android:strokeWidth="1"
+                    android:pathData="M 9 6.66666667 L 11 6.66666667 Q 12 6.66666667 12 7.66666667 L 12 20.33333337 Q 12 21.33333337 11 21.33333337 L 9 21.33333337 Q 8 21.33333337 8 20.33333337 L 8 7.66666667 Q 8 6.66666667 9 6.66666667 Z"/>
+            </group>
+        </group>
+    </group>
+</vector>
\ No newline at end of file
diff --git a/packages/SimAppDialog/res/drawable/placeholder.xml b/packages/SimAppDialog/res/drawable/placeholder.xml
new file mode 100644
index 0000000..53eee74
--- /dev/null
+++ b/packages/SimAppDialog/res/drawable/placeholder.xml
@@ -0,0 +1,44 @@
+<?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.
+-->
+<!-- TODO(b/72511181): replace when illustration is finished -->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="270dp"
+        android:height="270dp"
+        android:viewportHeight="270.0"
+        android:viewportWidth="270.0">
+    <path android:fillColor="#E8EAED"
+          android:pathData="M183.54,265H84.88c-7.63,0 -13.81,-6.18 -13.81,-13.81V18.81C71.07,11.18 77.25,5 84.88,5h98.66c7.63,0 13.81,6.18 13.81,13.81v232.38C197.35,258.82 191.17,265 183.54,265z"/>
+    <path android:fillColor="#BDC1C6"
+          android:pathData="M183.54,6.63c6.72,0 12.18,5.46 12.18,12.18v232.38c0,6.72 -5.46,12.18 -12.18,12.18H84.88c-6.72,0 -12.18,-5.46 -12.18,-12.18V18.81c0,-6.72 5.46,-12.18 12.18,-12.18H183.54M183.54,5H84.88c-7.63,0 -13.81,6.18 -13.81,13.81v232.38c0,7.63 6.18,13.81 13.81,13.81h98.66c7.63,0 13.81,-6.18 13.81,-13.81V18.81C197.35,11.18 191.17,5 183.54,5L183.54,5z"/>
+    <path android:fillColor="#FFFFFF"
+          android:pathData="M186.34,243.74H82.08c-2.41,0 -4.36,-1.95 -4.36,-4.36V30.61c0,-2.41 1.95,-4.36 4.36,-4.36h104.26c2.41,0 4.36,1.95 4.36,4.36v208.78C190.7,241.79 188.75,243.74 186.34,243.74z"/>
+    <path android:fillColor="#BDC1C6"
+          android:pathData="M156.07,254.78h-43.72c-0.65,0 -1.18,-0.53 -1.18,-1.18v-0.08c0,-0.65 0.53,-1.18 1.18,-1.18h43.72c0.65,0 1.18,0.53 1.18,1.18v0.08C157.25,254.25 156.72,254.78 156.07,254.78z"/>
+    <path android:fillColor="#BDC1C6"
+          android:pathData="M156.07,17.67h-43.72c-0.65,0 -1.18,-0.53 -1.18,-1.18V16.4c0,-0.65 0.53,-1.18 1.18,-1.18l43.72,0c0.65,0 1.18,0.53 1.18,1.18v0.08C157.25,17.14 156.72,17.67 156.07,17.67z"/>
+    <path android:fillColor="#BDC1C6"
+          android:pathData="M197.85,84.16h-0.5V67.51h0.5c0.6,0 1.08,0.48 1.08,1.08v14.5C198.93,83.68 198.45,84.16 197.85,84.16z"/>
+    <path android:fillColor="#BDC1C6"
+          android:pathData="M197.41,136.45h-0.06v-32.87h0.06c0.84,0 1.52,0.68 1.52,1.52v29.84C198.93,135.77 198.25,136.45 197.41,136.45z"/>
+    <path android:fillColor="#BDC1C6"
+          android:pathData="M119.3,74.73l2.71,2.71c6.74,-6.74 17.67,-6.74 24.4,0l2.71,-2.71C140.89,66.49 127.54,66.49 119.3,74.73zM130.15,85.57l4.07,4.07l4.07,-4.07C136.04,83.33 132.39,83.33 130.15,85.57zM124.72,80.15l2.71,2.71c3.74,-3.74 9.82,-3.74 13.56,0l2.71,-2.71C138.46,74.91 129.96,74.91 124.72,80.15z"/>
+    <path android:fillColor="#BDC1C6"
+          android:pathData="M143.7,179h-1.36v-2.71h-2.71V179h-10.85v-2.71h-2.71V179h-1.36c-1.5,0 -2.7,1.21 -2.7,2.71l-0.01,18.98c0,1.5 1.21,2.71 2.71,2.71h18.98c1.5,0 2.71,-1.21 2.71,-2.71v-18.98C146.41,180.22 145.2,179 143.7,179zM143.7,200.7h-18.98v-14.91h18.98V200.7zM127.43,188.49h6.78v6.78h-6.78V188.49z"/>
+    <path android:fillColor="#BDC1C6"
+          android:pathData="M146.41,144.49v-18.98c0,-1.5 -1.21,-2.71 -2.71,-2.71h-18.98c-1.5,0 -2.71,1.21 -2.71,2.71v18.98c0,1.5 1.21,2.71 2.71,2.71h18.98C145.2,147.2 146.41,145.99 146.41,144.49zM129.47,137.03l3.39,4.07l4.75,-6.11l6.1,8.13h-18.98L129.47,137.03z"/>
+</vector>
diff --git a/packages/SimAppDialog/res/layout/install_carrier_app_activity.xml b/packages/SimAppDialog/res/layout/install_carrier_app_activity.xml
new file mode 100644
index 0000000..0462a93
--- /dev/null
+++ b/packages/SimAppDialog/res/layout/install_carrier_app_activity.xml
@@ -0,0 +1,57 @@
+<?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.
+-->
+<com.android.setupwizardlib.GlifLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:id="@+id/setup_wizard_layout"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:icon="@drawable/ic_signal_cellular_alt_rounded_24px"
+    app:suwHeaderText="@string/install_carrier_app_title"
+    app:suwFooter="@layout/install_carrier_app_footer">
+
+    <LinearLayout
+        style="@style/SuwContentFrame"
+        android:id="@+id/content_frame"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="vertical">
+
+        <TextView
+            android:id="@+id/install_carrier_app_description"
+            style="@style/SuwDescription.Glif"
+            android:text="@string/install_carrier_app_description_default"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"/>
+
+        <com.android.setupwizardlib.view.FillContentLayout
+            android:layout_width="match_parent"
+            android:layout_height="0dp"
+            android:layout_weight="1">
+
+            <!-- TODO(b/72511181): final illo and content description update -->
+            <ImageView
+                android:src="@drawable/placeholder"
+                style="@style/SuwContentIllustration"
+                android:contentDescription="@null"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"/>
+
+        </com.android.setupwizardlib.view.FillContentLayout>
+    </LinearLayout>
+
+</com.android.setupwizardlib.GlifLayout>
diff --git a/packages/SimAppDialog/res/layout/install_carrier_app_footer.xml b/packages/SimAppDialog/res/layout/install_carrier_app_footer.xml
new file mode 100644
index 0000000..10dcb77
--- /dev/null
+++ b/packages/SimAppDialog/res/layout/install_carrier_app_footer.xml
@@ -0,0 +1,43 @@
+<?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.
+-->
+
+<com.android.setupwizardlib.view.ButtonBarLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/footer"
+    style="@style/SuwGlifButtonBar.Stackable"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content">
+
+    <Button
+        android:id="@+id/skip_button"
+        style="@style/SuwGlifButton.Secondary"
+        android:text="@string/install_carrier_app_defer_action"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"/>
+
+    <Space
+        android:layout_width="0dp"
+        android:layout_height="0dp"
+        android:layout_weight="1"/>
+
+    <Button
+        android:id="@+id/download_button"
+        style="@style/SuwGlifButton.Primary"
+        android:text="@string/install_carrier_app_download_action"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"/>
+</com.android.setupwizardlib.view.ButtonBarLayout>
diff --git a/packages/SimAppDialog/res/values/strings.xml b/packages/SimAppDialog/res/values/strings.xml
new file mode 100644
index 0000000..0c3930d
--- /dev/null
+++ b/packages/SimAppDialog/res/values/strings.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    Copyright (C) 2018 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+        http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- TODO character limits -->
+    <!-- The name of this application -->
+    <string name="app_name">Sim App Dialog</string>
+    <!-- Install Carrier App Activity -->
+    <!-- Title of screen asking user to download the carrier app to match the inserted SIM card -->
+    <string name="install_carrier_app_title">Activate mobile service</string>
+    <!-- Description of screen asking user to download the carrier app to match the inserted SIM card if we know the name of the carrier-->
+    <string name="install_carrier_app_description">To get your new SIM working properly, you\'ll
+        need to install the <xliff:g name="carrier_name" example="Project Fi">%1$s</xliff:g> app
+    </string>
+    <!-- Description of screen asking user to download the carrier app to match the inserted SIM card if we don't know the name of the carrier-->
+    <string name="install_carrier_app_description_default">To get your new SIM working properly,
+        you\'ll need to install the carrier app
+    </string>
+    <!-- Name of the button used to defer downloading the carrier app -->
+    <string name="install_carrier_app_defer_action">Not now</string>
+    <!-- Name of the button for downloading the carrier app -->
+    <string name="install_carrier_app_download_action">Download app</string>
+</resources>
\ No newline at end of file
diff --git a/packages/SimAppDialog/src/com/android/simappdialog/InstallCarrierAppActivity.java b/packages/SimAppDialog/src/com/android/simappdialog/InstallCarrierAppActivity.java
new file mode 100644
index 0000000..9e9b80d
--- /dev/null
+++ b/packages/SimAppDialog/src/com/android/simappdialog/InstallCarrierAppActivity.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.simappdialog;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.SystemProperties;
+import android.text.TextUtils;
+import android.view.View;
+import android.widget.Button;
+import android.widget.TextView;
+
+import com.android.setupwizardlib.util.WizardManagerHelper;
+
+/**
+ * Activity that gives a user the choice to download the SIM app or defer until a later time
+ *
+ * Will finish with result {@link #DEFER_RESULT} on defer button press or {@link #DOWNLOAD_RESULT}
+ * if the download button is pressed
+ *
+ * Can display the carrier app name if its passed into the intent with key
+ * {@link #BUNDLE_KEY_CARRIER_NAME}
+ */
+public class InstallCarrierAppActivity extends Activity implements View.OnClickListener {
+    /**
+     * Key for the carrier app name that will be displayed as the app to download.  If unset, a
+     * default description will be used
+     */
+    public static final String BUNDLE_KEY_CARRIER_NAME = "carrier_name";
+    /** Result code when the defer button is pressed */
+    public static final int DEFER_RESULT = 1;
+    /** Result code when the download button is pressed */
+    public static final int DOWNLOAD_RESULT = 2;
+
+    @Override
+    protected void onCreate(Bundle icicle) {
+        // Setup theme for aosp/pixel
+        setTheme(
+                WizardManagerHelper.getThemeRes(
+                        SystemProperties.get("setupwizard.theme"),
+                        R.style.SuwThemeGlif_Light
+                )
+        );
+
+        super.onCreate(icicle);
+        setContentView(R.layout.install_carrier_app_activity);
+
+        Button notNowButton = findViewById(R.id.skip_button);
+        notNowButton.setOnClickListener(this);
+
+        Button downloadButton = findViewById(R.id.download_button);
+        downloadButton.setOnClickListener(this);
+
+        // Include carrier name in description text if its present in the intent
+        Intent intent = getIntent();
+        if (intent != null) {
+            String carrierName = intent.getStringExtra(BUNDLE_KEY_CARRIER_NAME);
+            if (!TextUtils.isEmpty(carrierName)) {
+                TextView subtitle = findViewById(R.id.install_carrier_app_description);
+                subtitle.setText(getString(R.string.install_carrier_app_description, carrierName));
+            }
+        }
+    }
+
+    @Override
+    public void onClick(View v) {
+        switch (v.getId()) {
+            case R.id.skip_button:
+                finish(DEFER_RESULT);
+                break;
+            case R.id.download_button:
+                finish(DOWNLOAD_RESULT);
+                break;
+        }
+    }
+
+    private void finish(int resultCode) {
+        setResult(resultCode);
+        finish();
+    }
+}
diff --git a/packages/SystemUI/Android.mk b/packages/SystemUI/Android.mk
index 2bcf4ef..1e48213 100644
--- a/packages/SystemUI/Android.mk
+++ b/packages/SystemUI/Android.mk
@@ -56,7 +56,6 @@
     SystemUI-proto
 
 LOCAL_JAVA_LIBRARIES := telephony-common
-LOCAL_JAVA_LIBRARIES += android.car
 
 LOCAL_PACKAGE_NAME := SystemUI
 LOCAL_CERTIFICATE := platform
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 9613a6a..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" />
@@ -176,9 +176,6 @@
     <!-- It's like, reality, but, you know, virtual -->
     <uses-permission android:name="android.permission.ACCESS_VR_MANAGER" />
 
-    <!-- To control car audio module volume -->
-    <uses-permission android:name="android.car.permission.CAR_CONTROL_AUDIO_VOLUME" />
-
     <!-- the ability to rename notifications posted by other apps -->
     <uses-permission android:name="android.permission.SUBSTITUTE_NOTIFICATION_APP_NAME" />
 
@@ -384,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/OWNERS b/packages/SystemUI/OWNERS
index af6dd77..7c97ca61 100644
--- a/packages/SystemUI/OWNERS
+++ b/packages/SystemUI/OWNERS
@@ -2,19 +2,23 @@
 
 dsandler@google.com
 
+adamcohen@google.com
 asc@google.com
 ashaikh@google.com
 beverlyt@google.com
 cinek@google.com
 cwren@google.com
+dupin@google.com
 evanlaird@google.com
 jmonk@google.com
 jaggies@google.com
 jjaggi@google.com
 juliacr@google.com
-dupin@google.com
 madym@google.com
+ngmatthew@google.com
 roosa@google.com
 shahrk@google.com
+sunnygoyal@google.com
+twickham@google.com
 winsonc@google.com
 
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_status_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_status_view.xml
index faa2c17..31635a5 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_status_view.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_status_view.xml
@@ -33,6 +33,23 @@
         android:layout_height="wrap_content"
         android:layout_marginBottom="@dimen/widget_vertical_padding"
         android:orientation="vertical">
+        <TextView
+            android:id="@+id/logout"
+            android:layout_height="@dimen/logout_button_layout_height"
+            android:layout_width="wrap_content"
+            android:layout_gravity="center_horizontal"
+            android:layout_centerHorizontal="true"
+            android:layout_marginBottom="@dimen/logout_button_margin_bottom"
+            android:gravity="center"
+            android:paddingLeft="@dimen/logout_button_padding_horizontal"
+            android:paddingRight="@dimen/logout_button_padding_horizontal"
+            android:background="@drawable/logout_button_background"
+            android:fontFamily="roboto-medium"
+            android:textAllCaps="true"
+            android:textColor="?android:attr/textColorPrimary"
+            android:textSize="13sp"
+            android:text="@*android:string/global_action_logout" />
+
         <RelativeLayout
             android:id="@+id/keyguard_clock_container"
             android:layout_width="match_parent"
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-hdpi/ic_sysbar_back_ime_quick_step.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_ime_quick_step.png
new file mode 100644
index 0000000..d7f9449
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_ime_quick_step.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_ime_quick_step_dark.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_ime_quick_step_dark.png
new file mode 100644
index 0000000..7c65703
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_ime_quick_step_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_quick_step.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_quick_step.png
new file mode 100644
index 0000000..eea819a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_quick_step.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_quick_step_dark.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_quick_step_dark.png
new file mode 100644
index 0000000..504ceb7
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_quick_step_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_quick_step.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_quick_step.png
new file mode 100644
index 0000000..8e7d8cb
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_quick_step.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_quick_step_dark.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_quick_step_dark.png
new file mode 100644
index 0000000..456a68f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_quick_step_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-land-hdpi/ic_sysbar_home_quick_step.png b/packages/SystemUI/res/drawable-land-hdpi/ic_sysbar_home_quick_step.png
new file mode 100644
index 0000000..fb854ec
--- /dev/null
+++ b/packages/SystemUI/res/drawable-land-hdpi/ic_sysbar_home_quick_step.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-land-hdpi/ic_sysbar_home_quick_step_dark.png b/packages/SystemUI/res/drawable-land-hdpi/ic_sysbar_home_quick_step_dark.png
new file mode 100644
index 0000000..75d184a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-land-hdpi/ic_sysbar_home_quick_step_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-land-xhdpi/ic_sysbar_home_quick_step.png b/packages/SystemUI/res/drawable-land-xhdpi/ic_sysbar_home_quick_step.png
new file mode 100644
index 0000000..9e0af28
--- /dev/null
+++ b/packages/SystemUI/res/drawable-land-xhdpi/ic_sysbar_home_quick_step.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-land-xhdpi/ic_sysbar_home_quick_step_dark.png b/packages/SystemUI/res/drawable-land-xhdpi/ic_sysbar_home_quick_step_dark.png
new file mode 100644
index 0000000..7c00bd5d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-land-xhdpi/ic_sysbar_home_quick_step_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-land-xxhdpi/ic_sysbar_home_quick_step.png b/packages/SystemUI/res/drawable-land-xxhdpi/ic_sysbar_home_quick_step.png
new file mode 100644
index 0000000..81b4466
--- /dev/null
+++ b/packages/SystemUI/res/drawable-land-xxhdpi/ic_sysbar_home_quick_step.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-land-xxhdpi/ic_sysbar_home_quick_step_dark.png b/packages/SystemUI/res/drawable-land-xxhdpi/ic_sysbar_home_quick_step_dark.png
new file mode 100644
index 0000000..724aa9e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-land-xxhdpi/ic_sysbar_home_quick_step_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-land-xxxhdpi/ic_sysbar_home_quick_step.png b/packages/SystemUI/res/drawable-land-xxxhdpi/ic_sysbar_home_quick_step.png
new file mode 100644
index 0000000..7ba0d1b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-land-xxxhdpi/ic_sysbar_home_quick_step.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-land-xxxhdpi/ic_sysbar_home_quick_step_dark.png b/packages/SystemUI/res/drawable-land-xxxhdpi/ic_sysbar_home_quick_step_dark.png
new file mode 100644
index 0000000..a175ccb
--- /dev/null
+++ b/packages/SystemUI/res/drawable-land-xxxhdpi/ic_sysbar_home_quick_step_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_sysbar_back_quick_step.png b/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_sysbar_back_quick_step.png
new file mode 100644
index 0000000..45ce1d4
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_sysbar_back_quick_step.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_sysbar_back_quick_step_dark.png b/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_sysbar_back_quick_step_dark.png
new file mode 100644
index 0000000..6da0c9e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_sysbar_back_quick_step_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_sysbar_back_quick_step.png b/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_sysbar_back_quick_step.png
new file mode 100644
index 0000000..71e8959
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_sysbar_back_quick_step.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_sysbar_back_quick_step_dark.png b/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_sysbar_back_quick_step_dark.png
new file mode 100644
index 0000000..bb7ae26
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_sysbar_back_quick_step_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_sysbar_back_quick_step.png b/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_sysbar_back_quick_step.png
new file mode 100644
index 0000000..32b9ded
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_sysbar_back_quick_step.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_sysbar_back_quick_step_dark.png b/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_sysbar_back_quick_step_dark.png
new file mode 100644
index 0000000..ed1949c7
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_sysbar_back_quick_step_dark.png
Binary files differ
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-mdpi/ic_sysbar_back_ime_quick_step.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_quick_step.png
new file mode 100644
index 0000000..d888869
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_quick_step.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_quick_step_dark.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_quick_step_dark.png
new file mode 100644
index 0000000..dc3b25c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_quick_step_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_quick_step.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_quick_step.png
new file mode 100644
index 0000000..d4e5a94
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_quick_step.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_quick_step_dark.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_quick_step_dark.png
new file mode 100644
index 0000000..0e693f7
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_quick_step_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_quick_step.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_quick_step.png
new file mode 100644
index 0000000..0757799
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_quick_step.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_quick_step_dark.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_quick_step_dark.png
new file mode 100644
index 0000000..4f07ec1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_quick_step_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime_quick_step.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime_quick_step.png
new file mode 100644
index 0000000..ba5b457
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime_quick_step.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime_quick_step_dark.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime_quick_step_dark.png
new file mode 100644
index 0000000..a55ea1d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime_quick_step_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_quick_step.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_quick_step.png
new file mode 100644
index 0000000..407ef28
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_quick_step.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_quick_step_dark.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_quick_step_dark.png
new file mode 100644
index 0000000..39cfbf2
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_quick_step_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_quick_step.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_quick_step.png
new file mode 100644
index 0000000..a7fd3a6
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_quick_step.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_quick_step_dark.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_quick_step_dark.png
new file mode 100644
index 0000000..f2a1255
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_quick_step_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_ime_quick_step.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_ime_quick_step.png
new file mode 100644
index 0000000..5a7eec6
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_ime_quick_step.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_ime_quick_step_dark.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_ime_quick_step_dark.png
new file mode 100644
index 0000000..f7abb54
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_ime_quick_step_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_quick_step.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_quick_step.png
new file mode 100644
index 0000000..a1f44dc
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_quick_step.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_quick_step_dark.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_quick_step_dark.png
new file mode 100644
index 0000000..175a9ae
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_quick_step_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_home_quick_step.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_home_quick_step.png
new file mode 100644
index 0000000..0fb93ca
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_home_quick_step.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_home_quick_step_dark.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_home_quick_step_dark.png
new file mode 100644
index 0000000..1052940
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_home_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/drawable/car_ic_hvac.xml b/packages/SystemUI/res/drawable/car_ic_hvac.xml
new file mode 100644
index 0000000..bdc44b3
--- /dev/null
+++ b/packages/SystemUI/res/drawable/car_ic_hvac.xml
@@ -0,0 +1,51 @@
+<!--
+    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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="37dp"
+    android:height="31dp"
+    android:viewportWidth="37"
+    android:viewportHeight="31">
+
+    <group
+            android:translateX="-4.000000"
+            android:translateY="-6.000000">
+        <group
+                android:translateX="5.000000"
+                android:translateY="5.000000">
+            <path
+                android:fillType="evenOdd"
+                android:strokeColor="#FAFAFA"
+                android:strokeWidth="3.5"
+                android:pathData="M0.320769938,6.07518051 C6.46754647,1.46509811 12.4222362,1.46509811
+18.1848392,6.07518051 C23.9474422,10.6852629 29.3258717,10.4931761
+34.3201276,5.49892021" />
+            <path
+                android:fillType="evenOdd"
+                android:strokeColor="#FAFAFA"
+                android:strokeWidth="3.5"
+                android:pathData="M0.320769938,17.0751805 C6.46754647,12.4650981 12.4222362,12.4650981
+18.1848392,17.0751805 C23.9474422,21.6852629 29.3258717,21.4931761
+34.3201276,16.4989202" />
+            <path
+                android:fillType="evenOdd"
+                android:strokeColor="#FAFAFA"
+                android:strokeWidth="3.5"
+                android:pathData="M0.320769938,28.0751805 C6.46754647,23.4650981 12.4222362,23.4650981
+18.1848392,28.0751805 C23.9474422,32.6852629 29.3258717,32.4931761
+34.3201276,27.4989202" />
+        </group>
+    </group>
+</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/car_ic_notification.xml b/packages/SystemUI/res/drawable/car_ic_notification.xml
new file mode 100644
index 0000000..61d937b90
--- /dev/null
+++ b/packages/SystemUI/res/drawable/car_ic_notification.xml
@@ -0,0 +1,28 @@
+<!--
+    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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="56dp"
+    android:height="56dp"
+    android:viewportWidth="48"
+    android:viewportHeight="48">
+
+    <path
+        android:fillColor="#FFFFFF"
+        android:pathData="M24 44c2.21 0 4-1.79 4-4h-8c0 2.21 1.79 4 4
+4zm12-12V22c0-6.15-3.27-11.28-9-12.64V8c0-1.66-1.34-3-3-3s-3 1.34-3 3v1.36c-5.73
+1.36-9 6.49-9 12.64v10l-4 4v2h32v-2l-4-4zm-4 2H16V22c0-4.97 3.03-9 8-9s8 4.03 8
+9v12z" />
+</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/car_ic_overview.xml b/packages/SystemUI/res/drawable/car_ic_overview.xml
new file mode 100644
index 0000000..4651dcb
--- /dev/null
+++ b/packages/SystemUI/res/drawable/car_ic_overview.xml
@@ -0,0 +1,28 @@
+<!--
+    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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="56dp"
+    android:height="56dp"
+    android:viewportWidth="48"
+    android:viewportHeight="48">
+
+    <path
+        android:pathData="M0 0h48v48H0z" />
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M24 4C12.95 4 4 12.95 4 24s8.95 20 20 20 20-8.95 20-20S35.05 4 24 4zm0 36c-8.82
+0-16-7.18-16-16S15.18 8 24 8s16 7.18 16 16-7.18 16-16 16z" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_lock_lockdown.xml b/packages/SystemUI/res/drawable/ic_lock_lockdown.xml
new file mode 100644
index 0000000..b517fc8
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_lock_lockdown.xml
@@ -0,0 +1,25 @@
+<!--
+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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24.0dp"
+        android:height="24.0dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+
+    <path
+        android:fillColor="#757575"
+        android:pathData="M18.0,8.0l-1.0,0.0L17.0,6.0c0.0,-2.8 -2.2,-5.0 -5.0,-5.0C9.2,1.0 7.0,3.2 7.0,6.0l0.0,2.0L6.0,8.0c-1.1,0.0 -2.0,0.9 -2.0,2.0l0.0,10.0c0.0,1.1 0.9,2.0 2.0,2.0l12.0,0.0c1.1,0.0 2.0,-0.9 2.0,-2.0L20.0,10.0C20.0,8.9 19.1,8.0 18.0,8.0zM12.0,17.0c-1.1,0.0 -2.0,-0.9 -2.0,-2.0s0.9,-2.0 2.0,-2.0c1.1,0.0 2.0,0.9 2.0,2.0S13.1,17.0 12.0,17.0zM15.1,8.0L8.9,8.0L8.9,6.0c0.0,-1.7 1.4,-3.1 3.1,-3.1c1.7,0.0 3.1,1.4 3.1,3.1L15.1,8.0z"/>
+</vector>
diff --git a/core/res/res/layout/notification_template_messaging_message.xml b/packages/SystemUI/res/drawable/logout_button_background.xml
similarity index 67%
copy from core/res/res/layout/notification_template_messaging_message.xml
copy to packages/SystemUI/res/drawable/logout_button_background.xml
index ab6466c..eafd663 100644
--- a/core/res/res/layout/notification_template_messaging_message.xml
+++ b/packages/SystemUI/res/drawable/logout_button_background.xml
@@ -1,6 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
+
 <!--
-  ~ Copyright (C) 2017 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.
@@ -14,8 +15,9 @@
   ~ See the License for the specific language governing permissions and
   ~ limitations under the License
   -->
-<com.android.internal.widget.MessagingMessage
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/message_text"
-    style="@style/Widget.Material.Notification.MessagingText"
-/>
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+       android:shape="rectangle">
+    <solid android:color="@color/logout_button_bg_color"/>
+    <corners android:radius="@dimen/logout_button_corner_radius"/>
+</shape>
diff --git a/packages/SystemUI/res/drawable/smart_reply_button_background.xml b/packages/SystemUI/res/drawable/smart_reply_button_background.xml
index 1cd1451..c5ac67b 100644
--- a/packages/SystemUI/res/drawable/smart_reply_button_background.xml
+++ b/packages/SystemUI/res/drawable/smart_reply_button_background.xml
@@ -20,7 +20,9 @@
         android:color="@color/notification_ripple_untinted_color">
     <item>
         <shape android:shape="rectangle">
-            <corners android:radius="@dimen/smart_reply_button_corner_radius"/>
+            <!-- Use non-zero corner radius to work around b/73285195. The actual corner radius is
+                 set dynamically at runtime in SmartReplyView. -->
+            <corners android:radius="1dp"/>
             <solid android:color="@color/smart_reply_button_background"/>
         </shape>
     </item>
diff --git a/packages/SystemUI/res/layout/car_facet_button.xml b/packages/SystemUI/res/layout/car_facet_button.xml
new file mode 100644
index 0000000..f432d36
--- /dev/null
+++ b/packages/SystemUI/res/layout/car_facet_button.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 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.
+*/
+-->
+
+<merge xmlns:android="http://schemas.android.com/apk/res/android">
+    <LinearLayout
+        xmlns:android="http://schemas.android.com/apk/res/android"
+        android:id="@+id/car_facet_button"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_weight="1"
+        android:gravity="center"
+        android:animateLayoutChanges="true"
+        android:orientation="vertical">
+
+        <com.android.keyguard.AlphaOptimizedImageButton
+            android:id="@+id/car_nav_button_icon"
+            android:layout_height="wrap_content"
+            android:layout_width="match_parent"
+            android:animateLayoutChanges="true"
+            android:background="@android:color/transparent"
+            android:scaleType="fitCenter">
+        </com.android.keyguard.AlphaOptimizedImageButton>
+
+        <com.android.keyguard.AlphaOptimizedImageButton
+            android:id="@+id/car_nav_button_more_icon"
+            android:layout_height="wrap_content"
+            android:layout_width="match_parent"
+            android:animateLayoutChanges="true"
+            android:background="@android:color/transparent"
+            android:scaleType="fitCenter">
+        </com.android.keyguard.AlphaOptimizedImageButton>
+
+    </LinearLayout>
+</merge>
diff --git a/packages/SystemUI/res/layout/car_left_navigation_bar.xml b/packages/SystemUI/res/layout/car_left_navigation_bar.xml
new file mode 100644
index 0000000..866b5a5
--- /dev/null
+++ b/packages/SystemUI/res/layout/car_left_navigation_bar.xml
@@ -0,0 +1,99 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 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.
+*/
+-->
+
+<com.android.systemui.statusbar.car.CarNavigationBarView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:systemui="http://schemas.android.com/apk/res-auto"
+    android:layout_height="match_parent"
+    android:layout_width="match_parent"
+    android:orientation="vertical"
+    android:background="@drawable/system_bar_background">
+
+    <LinearLayout
+        android:layout_height="match_parent"
+        android:layout_width="match_parent"
+        android:id="@+id/nav_buttons"
+        android:orientation="vertical"
+        android:gravity="top"
+        android:paddingTop="30dp"
+        android:layout_weight="1"
+        android:background="@drawable/system_bar_background"
+        android:animateLayoutChanges="true">
+
+        <com.android.systemui.statusbar.car.CarNavigationButton
+            android:id="@+id/home"
+            android:layout_height="wrap_content"
+            android:layout_width="match_parent"
+            systemui:intent="intent:#Intent;action=android.intent.action.MAIN;category=android.intent.category.HOME;end"
+            android:src="@drawable/car_ic_overview"
+            android:background="?android:attr/selectableItemBackground"
+            android:paddingTop="30dp"
+            android:paddingBottom="30dp"
+        />
+
+        <com.android.systemui.statusbar.car.CarNavigationButton
+            android:id="@+id/hvac"
+            android:layout_height="wrap_content"
+            android:layout_width="match_parent"
+            systemui:intent="intent:#Intent;action=android.car.intent.action.SHOW_HVAC_CONTROLS;end"
+            systemui:broadcast="true"
+            android:src="@drawable/car_ic_hvac"
+            android:background="?android:attr/selectableItemBackground"
+            android:paddingTop="30dp"
+            android:paddingBottom="30dp"
+        />
+    </LinearLayout>
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_weight="1"
+        android:gravity="bottom"
+        android:orientation="vertical">
+
+        <com.android.keyguard.AlphaOptimizedImageButton
+            android:id="@+id/notifications"
+            android:layout_height="wrap_content"
+            android:layout_width="match_parent"
+            android:src="@drawable/car_ic_notification"
+            android:background="?android:attr/selectableItemBackground"
+            android:paddingTop="20dp"
+            android:paddingBottom="20dp"
+            android:alpha="0.7"
+        />
+
+        <com.android.systemui.statusbar.policy.Clock
+            android:id="@+id/clock"
+            android:textAppearance="@style/TextAppearance.StatusBar.Clock"
+            android:layout_height="wrap_content"
+            android:layout_width="match_parent"
+            android:singleLine="true"
+            android:paddingStart="@dimen/status_bar_clock_starting_padding"
+            android:paddingEnd="@dimen/status_bar_clock_end_padding"
+            android:gravity="center_horizontal"
+            android:paddingBottom="20dp"
+        />
+
+        <Space
+            android:layout_height="10dp"
+            android:layout_width="match_parent"/>
+
+    </LinearLayout>
+
+</com.android.systemui.statusbar.car.CarNavigationBarView>
diff --git a/packages/SystemUI/res/layout/car_navigation_bar.xml b/packages/SystemUI/res/layout/car_navigation_bar.xml
index 999dbac..4666c60 100644
--- a/packages/SystemUI/res/layout/car_navigation_bar.xml
+++ b/packages/SystemUI/res/layout/car_navigation_bar.xml
@@ -19,34 +19,80 @@
 
 <com.android.systemui.statusbar.car.CarNavigationBarView
     xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:systemui="http://schemas.android.com/apk/res-auto"
     android:layout_height="match_parent"
     android:layout_width="match_parent"
-    android:gravity="center"
     android:background="@drawable/system_bar_background">
 
-    <!-- phone.NavigationBarView has rot0 and rot90 but we expect the car head unit to have a fixed
-         rotation so skip this level of the heirarchy.
-    -->
     <LinearLayout
         android:layout_height="match_parent"
-        android:layout_width="@dimen/car_navigation_bar_width"
+        android:layout_width="wrap_content"
         android:orientation="horizontal"
-        android:clipChildren="false"
-        android:clipToPadding="false"
         android:id="@+id/nav_buttons"
+        android:gravity="left"
+        android:paddingLeft="30dp"
+        android:layout_weight="1"
         android:animateLayoutChanges="true">
 
-        <!-- Buttons get populated here from a car_arrays.xml. -->
+        <com.android.systemui.statusbar.car.CarNavigationButton
+            android:id="@+id/home"
+            android:layout_height="match_parent"
+            android:layout_width="wrap_content"
+            systemui:intent="intent:#Intent;action=android.intent.action.MAIN;category=android.intent.category.HOME;end"
+            android:src="@drawable/car_ic_overview"
+            android:background="?android:attr/selectableItemBackground"
+            android:paddingLeft="30dp"
+            android:paddingRight="30dp"
+        />
+
+        <com.android.systemui.statusbar.car.CarNavigationButton
+            android:id="@+id/hvac"
+            android:layout_height="match_parent"
+            android:layout_width="wrap_content"
+            systemui:intent="intent:#Intent;action=android.car.intent.action.SHOW_HVAC_CONTROLS;end"
+            systemui:broadcast="true"
+            android:src="@drawable/car_ic_hvac"
+            android:background="?android:attr/selectableItemBackground"
+            android:paddingLeft="30dp"
+            android:paddingRight="30dp"
+        />
     </LinearLayout>
 
-    <!-- lights out layout to match exactly -->
     <LinearLayout
+        android:layout_width="wrap_content"
         android:layout_height="match_parent"
-        android:layout_width="match_parent"
-        android:orientation="horizontal"
-        android:id="@+id/lights_out"
-        android:visibility="gone">
-        <!-- Must match nav_buttons. -->
+        android:layout_weight="1"
+        android:gravity="right"
+        android:orientation="horizontal">
+
+        <com.android.keyguard.AlphaOptimizedImageButton
+            android:id="@+id/notifications"
+            android:layout_height="match_parent"
+            android:layout_width="wrap_content"
+            android:src="@drawable/car_ic_notification"
+            android:background="?android:attr/selectableItemBackground"
+            android:paddingLeft="20dp"
+            android:paddingRight="20dp"
+            android:alpha="0.7"
+        />
+
+        <com.android.systemui.statusbar.policy.Clock
+            android:id="@+id/clock"
+            android:textAppearance="@style/TextAppearance.StatusBar.Clock"
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:singleLine="true"
+            android:paddingStart="@dimen/status_bar_clock_starting_padding"
+            android:paddingEnd="@dimen/status_bar_clock_end_padding"
+            android:gravity="center_vertical"
+            android:paddingRight="20dp"
+        />
+
+        <Space
+            android:layout_width="10dp"
+            android:layout_height="match_parent"/>
+
     </LinearLayout>
 
 </com.android.systemui.statusbar.car.CarNavigationBarView>
+
diff --git a/packages/SystemUI/res/layout/car_navigation_button.xml b/packages/SystemUI/res/layout/car_navigation_button.xml
index 7677646..4062eb8 100644
--- a/packages/SystemUI/res/layout/car_navigation_button.xml
+++ b/packages/SystemUI/res/layout/car_navigation_button.xml
@@ -17,28 +17,13 @@
 */
 -->
 
-<com.android.systemui.statusbar.car.CarNavigationButton
-        xmlns:android="http://schemas.android.com/apk/res/android"
-        android:layout_height="match_parent"
-        android:layout_width="wrap_content"
-        android:orientation="horizontal"
-        android:background="?android:attr/selectableItemBackground">
+<merge xmlns:android="http://schemas.android.com/apk/res/android">
     <com.android.keyguard.AlphaOptimizedImageButton
-            android:id="@+id/car_nav_button_icon"
-            android:layout_height="match_parent"
-            android:layout_width="@dimen/car_navigation_button_width"
-            android:layout_centerInParent="true"
-            android:animateLayoutChanges="true"
-            android:scaleType="fitCenter">
+        android:id="@+id/car_nav_button_icon"
+        android:layout_height="wrap_content"
+        android:layout_width="@dimen/car_navigation_button_width"
+        android:layout_centerInParent="true"
+        android:animateLayoutChanges="true"
+        android:scaleType="fitCenter">
     </com.android.keyguard.AlphaOptimizedImageButton>
-
-    <com.android.keyguard.AlphaOptimizedImageButton
-            android:id="@+id/car_nav_button_more_icon"
-            android:layout_height="match_parent"
-            android:layout_width="wrap_content"
-            android:layout_centerVertical="true"
-            android:layout_toRightOf="@+id/car_nav_button_icon"
-            android:animateLayoutChanges="true"
-            android:scaleType="fitCenter">
-    </com.android.keyguard.AlphaOptimizedImageButton>
-</com.android.systemui.statusbar.car.CarNavigationButton>
+</merge>
diff --git a/packages/SystemUI/res/layout/car_right_navigation_bar.xml b/packages/SystemUI/res/layout/car_right_navigation_bar.xml
new file mode 100644
index 0000000..99ab802
--- /dev/null
+++ b/packages/SystemUI/res/layout/car_right_navigation_bar.xml
@@ -0,0 +1,101 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 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.
+*/
+-->
+
+<com.android.systemui.statusbar.car.CarNavigationBarView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:systemui="http://schemas.android.com/apk/res-auto"
+    android:layout_height="match_parent"
+    android:layout_width="match_parent"
+    android:orientation="vertical"
+    android:background="@drawable/system_bar_background">
+
+    <LinearLayout
+        android:layout_height="match_parent"
+        android:layout_width="match_parent"
+        android:id="@+id/nav_buttons"
+        android:orientation="vertical"
+        android:gravity="top"
+        android:paddingTop="30dp"
+        android:layout_weight="1"
+        android:background="@drawable/system_bar_background"
+        android:animateLayoutChanges="true">
+
+        <com.android.systemui.statusbar.car.CarNavigationButton
+            android:id="@+id/home"
+            android:layout_height="wrap_content"
+            android:layout_width="match_parent"
+            systemui:intent="intent:#Intent;action=android.intent.action.MAIN;category=android.intent.category.HOME;end"
+            android:src="@drawable/car_ic_overview"
+            android:background="?android:attr/selectableItemBackground"
+            android:paddingTop="30dp"
+            android:paddingBottom="30dp"
+        />
+
+        <com.android.systemui.statusbar.car.CarNavigationButton
+            android:id="@+id/hvac"
+            android:layout_height="wrap_content"
+            android:layout_width="match_parent"
+            systemui:intent="intent:#Intent;action=android.car.intent.action.SHOW_HVAC_CONTROLS;end"
+            systemui:broadcast="true"
+            android:src="@drawable/car_ic_hvac"
+            android:background="?android:attr/selectableItemBackground"
+            android:paddingTop="30dp"
+            android:paddingBottom="30dp"
+        />
+
+    </LinearLayout>
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_weight="1"
+        android:gravity="bottom"
+        android:orientation="vertical">
+
+        <com.android.keyguard.AlphaOptimizedImageButton
+            android:id="@+id/notifications"
+            android:layout_height="wrap_content"
+            android:layout_width="match_parent"
+            android:src="@drawable/car_ic_notification"
+            android:background="?android:attr/selectableItemBackground"
+            android:paddingTop="20dp"
+            android:paddingBottom="20dp"
+            android:alpha="0.7"
+        />
+
+
+        <com.android.systemui.statusbar.policy.Clock
+            android:id="@+id/clock"
+            android:textAppearance="@style/TextAppearance.StatusBar.Clock"
+            android:layout_height="wrap_content"
+            android:layout_width="match_parent"
+            android:singleLine="true"
+            android:paddingStart="@dimen/status_bar_clock_starting_padding"
+            android:paddingEnd="@dimen/status_bar_clock_end_padding"
+            android:gravity="center_horizontal"
+            android:paddingBottom="20dp"
+        />
+
+        <Space
+            android:layout_height="10dp"
+            android:layout_width="match_parent"/>
+
+    </LinearLayout>
+
+</com.android.systemui.statusbar.car.CarNavigationBarView>
diff --git a/packages/SystemUI/res/layout/menu_ime.xml b/packages/SystemUI/res/layout/menu_ime.xml
index 8078c41..2470947 100644
--- a/packages/SystemUI/res/layout/menu_ime.xml
+++ b/packages/SystemUI/res/layout/menu_ime.xml
@@ -41,6 +41,15 @@
         android:scaleType="centerInside"
         />
     <com.android.systemui.statusbar.policy.KeyButtonView
+        android:id="@+id/rotate_suggestion"
+        android:layout_width="@dimen/navigation_extra_key_width"
+        android:layout_height="match_parent"
+        android:layout_marginEnd="2dp"
+        android:visibility="invisible"
+        android:scaleType="centerInside"
+        android:contentDescription="@string/accessibility_rotate_button"
+        />
+    <com.android.systemui.statusbar.policy.KeyButtonView
         android:id="@+id/accessibility_button"
         android:layout_width="@dimen/navigation_extra_key_width"
         android:layout_height="match_parent"
diff --git a/packages/SystemUI/res/layout/notification_info.xml b/packages/SystemUI/res/layout/notification_info.xml
index 6b5bd12..759d1ed 100644
--- a/packages/SystemUI/res/layout/notification_info.xml
+++ b/packages/SystemUI/res/layout/notification_info.xml
@@ -30,14 +30,15 @@
     <!-- Package Info -->
     <RelativeLayout
         android:layout_width="match_parent"
-        android:layout_height="@dimen/notification_guts_header_height"
+        android:layout_height="wrap_content"
         android:clipChildren="false"
         android:clipToPadding="false"
-        android:layout_marginTop="@*android:dimen/notification_header_padding_top" >
+        android:layout_marginTop="2dp" >
         <ImageView
             android:id="@+id/pkgicon"
             android:layout_width="@dimen/notification_guts_header_height"
             android:layout_height="@dimen/notification_guts_header_height"
+            android:layout_centerVertical="true"
             android:layout_marginEnd="3dp" />
         <TextView
             android:id="@+id/pkgname"
@@ -74,8 +75,11 @@
             android:id="@+id/info"
             android:src="@drawable/ic_info"
             android:tint="?android:attr/colorAccent"
-            android:layout_width="@dimen/notification_guts_header_height"
-            android:layout_height="@dimen/notification_guts_header_height"
+            android:layout_width="48dp"
+            android:layout_height="48dp"
+            android:padding="12dp"
+            android:layout_marginEnd="-12dp"
+            android:layout_centerVertical="true"
             android:contentDescription="@string/notification_more_settings"
             android:background="@drawable/ripple_drawable"
             android:layout_alignParentEnd="true" />
diff --git a/packages/SystemUI/res/layout/qs_footer_impl.xml b/packages/SystemUI/res/layout/qs_footer_impl.xml
index 97472a4..cf88ade 100644
--- a/packages/SystemUI/res/layout/qs_footer_impl.xml
+++ b/packages/SystemUI/res/layout/qs_footer_impl.xml
@@ -71,23 +71,19 @@
                 android:singleLine="true" />
         </LinearLayout>
 
-        <FrameLayout
+        <View
+            android:id="@+id/qs_drag_handle_view"
             android:layout_width="24dp"
-            android:layout_height="match_parent" >
-            <View
-                android:id="@+id/qs_drag_handle_view"
-                android:layout_width="match_parent"
-                android:layout_height="4dp"
-                android:layout_marginTop="28dp"
-                android:background="@drawable/qs_footer_drag_handle" />
-        </FrameLayout>
+            android:layout_height="4dp"
+            android:layout_gravity="center"
+            android:background="@drawable/qs_footer_drag_handle" />
 
-        <LinearLayout
+        <com.android.keyguard.AlphaOptimizedLinearLayout
             android:id="@+id/qs_footer_actions_container"
             android:layout_width="0dp"
             android:layout_height="match_parent"
             android:layout_weight="1"
-            android:gravity="end" >
+            android:gravity="center_vertical|end" >
             <com.android.systemui.statusbar.phone.MultiUserSwitch
                 android:id="@+id/multi_user_switch"
                 android:layout_width="48dp"
@@ -113,7 +109,7 @@
                 android:clipToPadding="false"
                 android:contentDescription="@string/accessibility_quick_settings_edit"
                 android:focusable="true"
-                android:padding="16dp"
+                android:padding="15dp"
                 android:src="@drawable/ic_mode_edit"
                 android:tint="?android:attr/colorForeground"/>
 
@@ -131,6 +127,7 @@
                     android:layout_height="match_parent"
                     android:background="@drawable/ripple_drawable"
                     android:contentDescription="@string/accessibility_quick_settings_settings"
+                    android:padding="15dp"
                     android:src="@drawable/ic_settings_16dp"
                     android:tint="?android:attr/colorForeground"/>
 
@@ -145,7 +142,7 @@
                     android:visibility="invisible"/>
 
             </com.android.systemui.statusbar.AlphaOptimizedFrameLayout>
-        </LinearLayout>
+        </com.android.keyguard.AlphaOptimizedLinearLayout>
     </LinearLayout>
 
 </com.android.systemui.qs.QSFooterImpl>
diff --git a/packages/SystemUI/res/layout/recents_swipe_up_onboarding.xml b/packages/SystemUI/res/layout/recents_onboarding.xml
similarity index 96%
rename from packages/SystemUI/res/layout/recents_swipe_up_onboarding.xml
rename to packages/SystemUI/res/layout/recents_onboarding.xml
index b3d5c90..12f278a 100644
--- a/packages/SystemUI/res/layout/recents_swipe_up_onboarding.xml
+++ b/packages/SystemUI/res/layout/recents_onboarding.xml
@@ -30,7 +30,6 @@
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_gravity="center"
-        android:text="@string/recents_swipe_up_onboarding"
         android:textColor="@android:color/white"
         android:textSize="16sp"
         android:drawableBottom="@drawable/ic_chevron_up"/>
diff --git a/packages/SystemUI/res/layout/screen_pinning_request_buttons.xml b/packages/SystemUI/res/layout/screen_pinning_request_buttons.xml
index a3118b0..25b117f 100644
--- a/packages/SystemUI/res/layout/screen_pinning_request_buttons.xml
+++ b/packages/SystemUI/res/layout/screen_pinning_request_buttons.xml
@@ -63,6 +63,7 @@
             android:src="@drawable/screen_pinning_bg_circ" />
 
         <ImageView
+            android:id="@+id/screen_pinning_back_icon"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
             android:paddingEnd="@dimen/screen_pinning_request_nav_side_padding"
@@ -105,6 +106,7 @@
             android:src="@drawable/screen_pinning_bg_circ" />
 
         <ImageView
+            android:id="@+id/screen_pinning_home_icon"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
             android:paddingEnd="@dimen/screen_pinning_request_nav_side_padding"
diff --git a/packages/SystemUI/res/layout/screen_pinning_request_buttons_land.xml b/packages/SystemUI/res/layout/screen_pinning_request_buttons_land.xml
index 61fe906..37a1a90 100644
--- a/packages/SystemUI/res/layout/screen_pinning_request_buttons_land.xml
+++ b/packages/SystemUI/res/layout/screen_pinning_request_buttons_land.xml
@@ -59,6 +59,7 @@
             android:src="@drawable/screen_pinning_bg_circ" />
 
         <ImageView
+            android:id="@+id/screen_pinning_back_icon"
             android:layout_height="match_parent"
             android:layout_width="match_parent"
             android:scaleType="center"
@@ -99,6 +100,7 @@
             android:src="@drawable/screen_pinning_bg_circ" />
 
         <ImageView
+            android:id="@+id/screen_pinning_home_icon"
             android:layout_height="match_parent"
             android:layout_width="match_parent"
             android:scaleType="center"
diff --git a/packages/SystemUI/res/layout/screen_pinning_request_buttons_sea.xml b/packages/SystemUI/res/layout/screen_pinning_request_buttons_sea.xml
index d1ca2ce..bac02aa 100644
--- a/packages/SystemUI/res/layout/screen_pinning_request_buttons_sea.xml
+++ b/packages/SystemUI/res/layout/screen_pinning_request_buttons_sea.xml
@@ -61,6 +61,7 @@
             android:src="@drawable/screen_pinning_bg_circ" />
 
         <ImageView
+            android:id="@+id/screen_pinning_back_icon"
             android:layout_height="match_parent"
             android:layout_width="match_parent"
             android:scaleType="center"
@@ -103,6 +104,7 @@
             android:src="@drawable/screen_pinning_bg_circ" />
 
         <ImageView
+            android:id="@+id/screen_pinning_home_icon"
             android:layout_height="match_parent"
             android:layout_width="match_parent"
             android:scaleType="center"
diff --git a/packages/SystemUI/res/layout/smart_reply_button.xml b/packages/SystemUI/res/layout/smart_reply_button.xml
index 4ac41d5..3c6edcd 100644
--- a/packages/SystemUI/res/layout/smart_reply_button.xml
+++ b/packages/SystemUI/res/layout/smart_reply_button.xml
@@ -16,17 +16,19 @@
   ~ limitations under the License
   -->
 
+<!-- android:paddingHorizontal is set dynamically in SmartReplyView. -->
 <Button xmlns:android="http://schemas.android.com/apk/res/android"
         style="@android:style/Widget.Material.Button.Borderless.Small"
         android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_marginStart="@dimen/smart_reply_button_spacing"
+        android:layout_height="match_parent"
+        android:minWidth="0dp"
+        android:minHeight="@dimen/smart_reply_button_min_height"
         android:paddingVertical="@dimen/smart_reply_button_padding_vertical"
-        android:paddingHorizontal="@dimen/smart_reply_button_corner_radius"
         android:background="@drawable/smart_reply_button_background"
         android:gravity="center"
         android:fontFamily="sans-serif"
         android:textSize="@dimen/smart_reply_button_font_size"
+        android:lineSpacingExtra="@dimen/smart_reply_button_line_spacing_extra"
         android:textColor="@color/smart_reply_button_text"
         android:textStyle="normal"
-        android:singleLine="true"/>
\ No newline at end of file
+        android:ellipsize="none"/>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/smart_reply_view.xml b/packages/SystemUI/res/layout/smart_reply_view.xml
index 6d53386..6f21787 100644
--- a/packages/SystemUI/res/layout/smart_reply_view.xml
+++ b/packages/SystemUI/res/layout/smart_reply_view.xml
@@ -19,9 +19,12 @@
 <!-- LinearLayout -->
 <com.android.systemui.statusbar.policy.SmartReplyView
     xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:systemui="http://schemas.android.com/apk/res-auto"
     android:id="@+id/smart_reply_view"
     android:layout_height="wrap_content"
     android:layout_width="wrap_content"
-    android:layout_gravity="end">
+    systemui:spacing="@dimen/smart_reply_button_spacing"
+    systemui:singleLineButtonPaddingHorizontal="@dimen/smart_reply_button_padding_horizontal_single_line"
+    systemui:doubleLineButtonPaddingHorizontal="@dimen/smart_reply_button_padding_horizontal_double_line">
     <!-- smart_reply_button(s) will be added here. -->
 </com.android.systemui.statusbar.policy.SmartReplyView>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/volume_dialog.xml b/packages/SystemUI/res/layout/volume_dialog.xml
index 36298ca..803659f 100644
--- a/packages/SystemUI/res/layout/volume_dialog.xml
+++ b/packages/SystemUI/res/layout/volume_dialog.xml
@@ -15,8 +15,8 @@
 -->
 <com.android.systemui.volume.VolumeUiLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
     android:background="@android:color/transparent"
     android:theme="@style/qs_theme"
     android:clipChildren="false" >
@@ -29,7 +29,6 @@
         android:minWidth="@dimen/volume_dialog_panel_width"
         android:background="@android:color/transparent"
         android:layout_margin="@dimen/volume_dialog_base_margin"
-        android:translationZ="8dp"
         android:orientation="vertical"
         android:clipChildren="false" >
 
@@ -39,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="8dp"
+            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="8dp"
-            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/arrays_tv.xml b/packages/SystemUI/res/values/arrays_tv.xml
index 7541b0e..9197bb5 100644
--- a/packages/SystemUI/res/values/arrays_tv.xml
+++ b/packages/SystemUI/res/values/arrays_tv.xml
@@ -30,7 +30,7 @@
         <item>com.google.android.apps.mediashell/.settings.CastSettingsActivity</item>
         <item>com.google.android.katniss.setting/.SpeechSettingsActivity</item>
         <item>com.google.android.katniss.setting/.SearchSettingsActivity</item>
-        <item>com.google.android.gsf.notouch/.UsageDiagnosticsSettingActivity</item>
+        <item>com.google.android.tungsten.setupwraith/.settings.usage.UsageDiagnosticsSettingActivity</item>
         <item>com.google.android.tvlauncher/.notifications.NotificationsSidePanelActivity</item>
     </string-array>
 </resources>
diff --git a/packages/SystemUI/res/values/attrs.xml b/packages/SystemUI/res/values/attrs.xml
index a923f0b..f0a5fe4 100644
--- a/packages/SystemUI/res/values/attrs.xml
+++ b/packages/SystemUI/res/values/attrs.xml
@@ -130,5 +130,11 @@
     <attr name="darkIconTheme" format="reference" />
     <attr name="wallpaperTextColor" format="reference|color" />
     <attr name="wallpaperTextColorSecondary" format="reference|color" />
+
+    <declare-styleable name="SmartReplyView">
+        <attr name="spacing" format="dimension" />
+        <attr name="singleLineButtonPaddingHorizontal" format="dimension" />
+        <attr name="doubleLineButtonPaddingHorizontal" format="dimension" />
+    </declare-styleable>
 </resources>
 
diff --git a/packages/SystemUI/res/values/attrs_car.xml b/packages/SystemUI/res/values/attrs_car.xml
new file mode 100644
index 0000000..b1097c3
--- /dev/null
+++ b/packages/SystemUI/res/values/attrs_car.xml
@@ -0,0 +1,42 @@
+<?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>
+    <!-- Allow for custom attribs to be added to a facet button -->
+    <declare-styleable name="CarFacetButton">
+        <!-- icon to be rendered (drawable) -->
+        <attr name="icon" format="reference"/>
+        <!-- intent to start when button is click -->
+        <attr name="intent" format="string"/>
+        <!-- intent to start when a long press has happened -->
+        <attr name="longIntent" format="string"/>
+        <!-- categories that will be added as extras to the fired intents -->
+        <attr name="categories" format="string"/>
+        <!-- package names that will be added as extras to the fired intents -->
+        <attr name="packages" format="string" />
+    </declare-styleable>
+
+
+    <!-- Allow for custom attribs to be added to a nav button -->
+    <declare-styleable name="CarNavigationButton">
+        <!-- intent to start when button is click -->
+        <attr name="intent" format="string"/>
+        <!-- intent to start when a long press has happened -->
+        <attr name="longIntent" format="string"/>
+        <!-- start the intent as a broad cast instead of an activity if true-->
+        <attr name="broadcast" format="boolean"/>
+    </declare-styleable>
+</resources>
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index 4fcfdf7..c054d16 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -156,9 +156,8 @@
 
     <color name="zen_introduction">#ffffffff</color>
 
-
-    <color name="smart_reply_button_text">#ff4285f4</color><!-- blue 500 -->
-    <color name="smart_reply_button_background">#fff7f7f7</color>
+    <color name="smart_reply_button_text">#de000000</color> <!-- 87% black -->
+    <color name="smart_reply_button_background">#fff2f2f2</color>
 
     <!-- Fingerprint dialog colors -->
     <color name="fingerprint_dialog_bg_color">#f4ffffff</color> <!-- 96% white -->
@@ -166,4 +165,6 @@
     <color name="fingerprint_dialog_dim_color">#80000000</color> <!-- 50% black -->
     <color name="fingerprint_error_message_color">#ff5722</color>
 
+    <!-- Logout button -->
+    <color name="logout_button_bg_color">#ccffffff</color>
 </resources>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 6b6171f..e2070a0 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -551,4 +551,10 @@
     <!-- Show indicator for Wifi on but not connected. -->
     <bool name="config_showWifiIndicatorWhenEnabled">false</bool>
 
+    <!-- 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/config_car.xml b/packages/SystemUI/res/values/config_car.xml
index 9c8dcb1..db829f2 100644
--- a/packages/SystemUI/res/values/config_car.xml
+++ b/packages/SystemUI/res/values/config_car.xml
@@ -22,4 +22,9 @@
          uri that will be launched into the docked window. -->
     <bool name="config_enablePersistentDockedActivity">false</bool>
     <string name="config_persistentDockedActivityIntentUri" translatable="false"></string>
+
+    <!-- configure which system ui bars should be displayed -->
+    <bool name="config_enableLeftNavigationBar">false</bool>
+    <bool name="config_enableRightNavigationBar">false</bool>
+    <bool name="config_enableBottomNavigationBar">true</bool>
 </resources>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index f101cfd..bdd89ca 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -230,7 +230,7 @@
 
     <!-- The height of the quick settings footer that holds the user switcher, settings icon,
          etc. -->
-    <dimen name="qs_footer_height">48dp</dimen>
+    <dimen name="qs_footer_height">56dp</dimen>
 
     <!-- The padding between the notifications and the quick settings container -->
     <dimen name="qs_notification_padding">@dimen/notification_side_paddings</dimen>
@@ -337,7 +337,7 @@
     <dimen name="qs_footer_padding_end">24dp</dimen>
     <dimen name="qs_footer_icon_size">16dp</dimen>
     <!-- Difference between drag handle margin in QQS and expanded QS -->
-    <dimen name="qs_footer_drag_handle_offset">6dp</dimen>
+    <dimen name="qs_footer_drag_handle_offset">10dp</dimen>
 
     <dimen name="qs_notif_collapsed_space">64dp</dimen>
 
@@ -513,7 +513,7 @@
     <dimen name="multi_user_avatar_keyguard_size">22dp</dimen>
 
     <!-- The width of user avatar when expanded -->
-    <dimen name="multi_user_avatar_expanded_size">16dp</dimen>
+    <dimen name="multi_user_avatar_expanded_size">18dp</dimen>
 
     <!-- The font size of the time when collapsed in QS -->
     <dimen name="qs_time_collapsed_size">14sp</dimen>
@@ -704,6 +704,8 @@
     <dimen name="volume_expander_margin_end">2dp</dimen>
     <dimen name="volume_expander_margin_top">6dp</dimen>
 
+    <dimen name="volume_panel_elevation">8dp</dimen>
+
     <!-- Padding between icon and text for managed profile toast -->
     <dimen name="managed_profile_toast_padding">4dp</dimen>
 
@@ -853,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>
@@ -883,36 +883,56 @@
     <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>
     <dimen name="smart_reply_button_spacing">8dp</dimen>
-    <dimen name="smart_reply_button_padding_vertical">4dp</dimen>
+    <dimen name="smart_reply_button_padding_vertical">10dp</dimen>
+    <dimen name="smart_reply_button_padding_horizontal_single_line">12dp</dimen>
+    <dimen name="smart_reply_button_padding_horizontal_double_line">16dp</dimen>
+    <dimen name="smart_reply_button_min_height">40dp</dimen>
     <dimen name="smart_reply_button_font_size">14sp</dimen>
+    <dimen name="smart_reply_button_line_spacing_extra">6sp</dimen> <!-- Total line height 20sp. -->
 
     <dimen name="fingerprint_dialog_icon_size">44dp</dimen>
     <dimen name="fingerprint_dialog_fp_icon_size">60dp</dimen>
     <dimen name="fingerprint_dialog_animation_translation_offset">350dp</dimen>
 
-    <!-- WirelessCharging Animation values -->
-    <!-- Starting text size of batteryLevel for wireless charging animation -->
-    <dimen name="config_batteryLevelTextSizeStart" format="float">5.0</dimen>
-    <!-- Ending text size of batteryLevel for wireless charging animation -->
-    <dimen name="config_batteryLevelTextSizeEnd" format="float">32.0</dimen>
-    <!-- Wireless Charging battery level text animation duration -->
-    <integer name="config_batteryLevelTextAnimationDuration">400</integer>
+    <!-- Wireless Charging Animation values -->
+    <dimen name="wireless_charging_dots_radius_start">0dp</dimen>
+    <dimen name="wireless_charging_dots_radius_end">4dp</dimen>
+    <dimen name="wireless_charging_circle_radius_start">28dp</dimen>
+    <dimen name="wireless_charging_circle_radius_end">92dp</dimen>
+    <integer name="wireless_charging_angle_offset">20</integer>
+    <integer name="wireless_charging_scale_dots_duration">83</integer>
+    <integer name="wireless_charging_num_dots">20</integer>
+    <!-- Starting text size in dp of batteryLevel for wireless charging animation -->
+    <dimen name="wireless_charging_anim_battery_level_text_size_start">0dp</dimen>
+    <!-- Ending text size in dp of batteryLevel for wireless charging animation -->
+    <dimen name="wireless_charging_anim_battery_level_text_size_end">14dp</dimen>
+    <!-- time until battery info is at full opacity-->
+    <integer name="wireless_charging_anim_opacity_offset">80</integer>
+    <!-- duration batteryLevel opacity goes from 0 to 1 duration -->
+    <integer name="wireless_charging_battery_level_text_opacity_duration">117</integer>
+    <!-- battery text scale animation duration -->
+    <integer name="wireless_charging_battery_level_text_scale_animation_duration">367</integer>
+    <!--time until wireless charging animation starts to fade-->
+    <integer name="wireless_charging_fade_offset">920</integer>
+    <!-- duration wireless charging animation takes to full fade to 0 opacity -->
+    <integer name="wireless_charging_fade_duration">200</integer>
 
     <!-- Wired charging on AOD, text animation duration -->
-    <integer name="wired_charging_aod_text_animation_duration_down">500</integer>
+    <integer name="wired_charging_keyguard_text_animation_duration_down">500</integer>
     <!-- Wired charging on AOD, text animation duration -->
-    <integer name="wired_charging_aod_text_animation_duration_up">300</integer>
+    <integer name="wired_charging_keyguard_text_animation_duration_up">300</integer>
     <!-- Wired charging on AOD, text animation distance -->
-    <integer name="wired_charging_aod_text_animation_distance">-30</integer>
+    <integer name="wired_charging_keyguard_text_animation_distance">-30</integer>
+
+    <!-- Logout button -->
+    <dimen name="logout_button_layout_height">32dp</dimen>
+    <dimen name="logout_button_padding_horizontal">16dp</dimen>
+    <dimen name="logout_button_margin_bottom">12dp</dimen>
+    <dimen name="logout_button_corner_radius">2dp</dimen>
+
 </resources>
diff --git a/packages/SystemUI/res/values/ids.xml b/packages/SystemUI/res/values/ids.xml
index f9aa821..2d30f4c 100644
--- a/packages/SystemUI/res/values/ids.xml
+++ b/packages/SystemUI/res/values/ids.xml
@@ -47,7 +47,6 @@
     <item type="id" name="qs_icon_tag"/>
     <item type="id" name="qs_slash_tag"/>
     <item type="id" name="scrim"/>
-    <item type="id" name="scrim_blanking"/>
     <item type="id" name="scrim_target"/>
     <item type="id" name="scrim_alpha_start"/>
     <item type="id" name="scrim_alpha_end"/>
@@ -58,6 +57,8 @@
     <item type="id" name="notification_plugin"/>
     <item type="id" name="transformation_start_x_tag"/>
     <item type="id" name="transformation_start_y_tag"/>
+    <item type="id" name="transformation_start_actual_width"/>
+    <item type="id" name="transformation_start_actual_height"/>
     <item type="id" name="transformation_start_scale_x_tag"/>
     <item type="id" name="transformation_start_scale_y_tag"/>
     <item type="id" name="continuous_clipping_tag"/>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 4ee55a4..b492acb 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -842,8 +842,6 @@
     <string name="recents_stack_action_button_label">Clear all</string>
     <!-- Recents: Hint text that shows on the drop targets to start multiwindow. [CHAR LIMIT=NONE] -->
     <string name="recents_drag_hint_message">Drag here to use split screen</string>
-    <!-- Recents: Text that shows above the nav bar after launching a few apps. [CHAR LIMIT=NONE] -->
-    <string name="recents_swipe_up_onboarding">Swipe up to switch apps</string>
 
     <!-- Recents: MultiStack add stack split horizontal radio button. [CHAR LIMIT=NONE] -->
     <string name="recents_multistack_add_stack_dialog_split_horizontal">Split Horizontal</string>
@@ -1342,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>
@@ -1754,15 +1751,13 @@
     <string-array name="nav_bar_buttons">
         <item>Clipboard</item>
         <item>Keycode</item>
-        <item>Keyboard switcher</item>
-        <item>Rotation suggestion</item>
+        <item>Rotate confirm, keyboard switcher</item>
         <item>None</item>
     </string-array>
     <string-array name="nav_bar_button_values" translatable="false">
         <item>clipboard</item>
         <item>key</item>
         <item>menu_ime</item>
-        <item>rotate</item>
         <item>space</item>
     </string-array>
 
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl
index 64fa9c6..e200a7f 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl
@@ -21,9 +21,48 @@
 
 oneway interface IOverviewProxy {
     void onBind(in ISystemUiProxy sysUiProxy);
+
+    /**
+     * Called once immediately prior to the first onMotionEvent() call, providing a hint to the
+     * target the initial source of the subsequent motion events.
+     *
+     * @param downHitTarget is one of the {@link NavigationBarCompat.HitTarget}s
+     */
+    void onPreMotionEvent(int downHitTarget);
+
+    /**
+     * Proxies motion events from the nav bar in SystemUI to the OverviewProxyService. The sender
+     * guarantees the following order of events:
+     *
+     * Normal gesture: DOWN, (MOVE/POINTER_DOWN/POINTER_UP)*, UP
+     * Quick switch: DOWN, (MOVE/POINTER_DOWN/POINTER_UP)*, SWITCH
+     * Quick scrub: DOWN, (MOVE/POINTER_DOWN/POINTER_UP)*, SCRUB_START, SCRUB_PROGRESS*, SCRUB_END
+     *
+     * Once quick switch/scrub is sent, then no further motion events will be provided.
+     */
     void onMotionEvent(in MotionEvent event);
+
+    /**
+     * Sent when a user has quickly flinged on the nav bar to switch tasks. Once this event is sent
+     * the caller will stop sending any motion events and will no longer preemptively cancel any
+     * recents animations started as a part of the motion event handling.
+     */
     void onQuickSwitch();
+
+    /**
+     * Sent when the user starts to actively scrub the nav bar to switch tasks. Once this event is
+     * sent the caller will stop sending any motion events and will no longer preemptively cancel
+     * any recents animations started as a part of the motion event handling.
+     */
     void onQuickScrubStart();
+
+    /**
+     * Sent when the user stops actively scrubbing the nav bar to switch tasks.
+     */
     void onQuickScrubEnd();
+
+    /**
+     * Sent for each movement over the nav bar while the user is scrubbing it to switch tasks.
+     */
     void onQuickScrubProgress(float progress);
 }
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl
index 98ede4e..b8319a8e 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl
@@ -39,4 +39,14 @@
      * Called when the overview service has started the recents animation.
      */
     void onRecentsAnimationStarted();
+
+    /**
+     * Specifies the text to be shown for onboarding the new swipe-up gesture to access recents.
+     */
+    void setRecentsOnboardingText(CharSequence text);
+
+    /**
+     * Enables/disables launcher/overview interaction features {@link InteractionType}.
+     */
+    void setInteractionState(int flags);
 }
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 90e3b1e..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
@@ -43,6 +43,7 @@
 import android.content.res.Resources;
 import android.content.res.Resources.NotFoundException;
 import android.graphics.Bitmap;
+import android.graphics.Rect;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
 import android.os.Bundle;
@@ -57,6 +58,7 @@
 import android.view.IRecentsAnimationRunner;
 
 import android.view.RemoteAnimationTarget;
+import android.view.WindowManagerGlobal;
 import com.android.systemui.shared.recents.model.Task;
 import com.android.systemui.shared.recents.model.Task.TaskKey;
 import com.android.systemui.shared.recents.model.ThumbnailData;
@@ -271,11 +273,20 @@
                 runner = new IRecentsAnimationRunner.Stub() {
                     public void onAnimationStart(IRecentsAnimationController controller,
                             RemoteAnimationTarget[] apps) {
+                        final Rect stableInsets = new Rect();
+                        WindowManagerWrapper.getInstance().getStableInsets(stableInsets);
+                        onAnimationStart_New(controller, apps, stableInsets, null);
+                    }
+
+                    public void onAnimationStart_New(IRecentsAnimationController controller,
+                            RemoteAnimationTarget[] apps, Rect homeContentInsets,
+                            Rect minimizedHomeBounds) {
                         final RecentsAnimationControllerCompat controllerCompat =
                                 new RecentsAnimationControllerCompat(controller);
                         final RemoteAnimationTargetCompat[] appsCompat =
                                 RemoteAnimationTargetCompat.wrap(apps);
-                        animationHandler.onAnimationStart(controllerCompat, appsCompat);
+                        animationHandler.onAnimationStart(controllerCompat, appsCompat,
+                                homeContentInsets, minimizedHomeBounds);
                     }
 
                     public void onAnimationCanceled() {
@@ -305,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/NavigationBarCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/NavigationBarCompat.java
new file mode 100644
index 0000000..17191868
--- /dev/null
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/NavigationBarCompat.java
@@ -0,0 +1,60 @@
+/*
+ * 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.shared.system;
+
+import android.annotation.IntDef;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+public class NavigationBarCompat {
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({HIT_TARGET_NONE, HIT_TARGET_BACK, HIT_TARGET_HOME})
+    public @interface HitTarget{}
+
+    public static final int HIT_TARGET_NONE = 0;
+    public static final int HIT_TARGET_BACK = 1;
+    public static final int HIT_TARGET_HOME = 2;
+
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({FLAG_DISABLE_SWIPE_UP,
+            FLAG_DISABLE_QUICK_SCRUB,
+            FLAG_SHOW_OVERVIEW_BUTTON,
+            FLAG_HIDE_BACK_BUTTON
+    })
+    public @interface InteractionType {}
+
+    /**
+     * Interaction type: whether the gesture to swipe up from the navigation bar will trigger
+     * launcher to show overview
+     */
+
+    public static final int FLAG_DISABLE_SWIPE_UP = 0x1;
+    /**
+     * Interaction type: enable quick scrub and switch interaction on the home button
+     */
+    public static final int FLAG_DISABLE_QUICK_SCRUB = 0x2;
+
+    /**
+     * Interaction type: show/hide the overview button while this service is connected to launcher
+     */
+    public static final int FLAG_SHOW_OVERVIEW_BUTTON = 0x4;
+
+    /**
+     * Interaction type: show/hide the back button while this service is connected to launcher
+     */
+    public static final int FLAG_HIDE_BACK_BUTTON = 0x8;
+}
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/shared/src/com/android/systemui/shared/system/RecentsAnimationListener.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationListener.java
index bf6179d..a473db1 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationListener.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationListener.java
@@ -16,13 +16,15 @@
 
 package com.android.systemui.shared.system;
 
+import android.graphics.Rect;
+
 public interface RecentsAnimationListener {
 
     /**
      * Called when the animation into Recents can start. This call is made on the binder thread.
      */
     void onAnimationStart(RecentsAnimationControllerCompat controller,
-            RemoteAnimationTargetCompat[] apps);
+            RemoteAnimationTargetCompat[] apps, Rect homeContentInsets, Rect minimizedHomeBounds);
 
     /**
      * Called when the animation into Recents was canceled. This call is made on the binder thread.
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java
index 3871980..b8c5049 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java
@@ -16,6 +16,9 @@
 
 package com.android.systemui.shared.system;
 
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
+
+import android.app.WindowConfiguration;
 import android.graphics.Point;
 import android.graphics.Rect;
 import android.view.RemoteAnimationTarget;
@@ -37,7 +40,10 @@
     public final Point position;
     public final Rect sourceContainerBounds;
 
+    private final RemoteAnimationTarget mTarget;
+
     public RemoteAnimationTargetCompat(RemoteAnimationTarget app) {
+        mTarget = app;
         taskId = app.taskId;
         mode = app.mode;
         leash = new SurfaceControlCompat(app.leash);
@@ -56,4 +62,18 @@
         }
         return appsCompat;
     }
+
+    /**
+     * TODO: Get as a method for compatibility (will move into ctor once Launcher updates)
+     */
+    public Rect getContentInsets() {
+        return mTarget.contentInsets;
+    }
+
+    /**
+     * TODO: Get as a method for compatibility (will move into ctor once Launcher updates)
+     */
+    public boolean isAssistantActivityType() {
+        return mTarget.windowConfiguration.getActivityType() == ACTIVITY_TYPE_ASSISTANT;
+    }
 }
\ No newline at end of file
diff --git a/packages/SystemUI/shared/tests/Android.mk b/packages/SystemUI/shared/tests/Android.mk
index 239a4e3..d01160d 100644
--- a/packages/SystemUI/shared/tests/Android.mk
+++ b/packages/SystemUI/shared/tests/Android.mk
@@ -35,13 +35,19 @@
 LOCAL_STATIC_JAVA_LIBRARIES := \
     metrics-helper-lib \
     android-support-test \
-    mockito-target-minus-junit4 \
+    mockito-target-inline-minus-junit4 \
     SystemUI-proto \
     SystemUI-tags \
     testables \
     truth-prebuilt \
 
-LOCAL_JAVA_LIBRARIES := android.test.runner telephony-common android.car
+LOCAL_MULTILIB := both
+
+LOCAL_JNI_SHARED_LIBRARIES := \
+    libdexmakerjvmtiagent \
+    libmultiplejvmtiagentsinterferenceagent
+
+LOCAL_JAVA_LIBRARIES := android.test.runner telephony-common
 
 # sign this with platform cert, so this test is allowed to inject key events into
 # UI it doesn't own. This is necessary to allow screenshots to be taken
diff --git a/packages/SystemUI/shared/tests/AndroidManifest.xml b/packages/SystemUI/shared/tests/AndroidManifest.xml
index 3e1de49..5974b76 100644
--- a/packages/SystemUI/shared/tests/AndroidManifest.xml
+++ b/packages/SystemUI/shared/tests/AndroidManifest.xml
@@ -19,7 +19,7 @@
 
     <uses-permission android:name="android.permission.READ_FRAME_BUFFER" />
 
-    <application>
+    <application android:debuggable="true">
         <uses-library android:name="android.test.runner" />
     </application>
 
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
index e440731..3b5f34c 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
@@ -16,13 +16,16 @@
 
 package com.android.keyguard;
 
+import android.app.ActivityManager;
 import android.app.AlarmManager;
+import android.app.IActivityManager;
 import android.content.Context;
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.graphics.Color;
 import android.os.Handler;
 import android.os.Looper;
+import android.os.RemoteException;
 import android.os.UserHandle;
 import android.support.v4.graphics.ColorUtils;
 import android.text.TextUtils;
@@ -51,9 +54,11 @@
 
     private final LockPatternUtils mLockPatternUtils;
     private final AlarmManager mAlarmManager;
+    private final IActivityManager mIActivityManager;
     private final float mSmallClockScale;
     private final float mWidgetPadding;
 
+    private TextView mLogoutView;
     private TextClock mClockView;
     private View mClockSeparator;
     private TextView mOwnerInfo;
@@ -80,6 +85,7 @@
                 if (DEBUG) Slog.v(TAG, "refresh statusview showing:" + showing);
                 refresh();
                 updateOwnerInfo();
+                updateLogoutView();
             }
         }
 
@@ -97,6 +103,12 @@
         public void onUserSwitchComplete(int userId) {
             refresh();
             updateOwnerInfo();
+            updateLogoutView();
+        }
+
+        @Override
+        public void onLogoutEnabledChanged() {
+            updateLogoutView();
         }
     };
 
@@ -111,6 +123,7 @@
     public KeyguardStatusView(Context context, AttributeSet attrs, int defStyle) {
         super(context, attrs, defStyle);
         mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
+        mIActivityManager = ActivityManager.getService();
         mLockPatternUtils = new LockPatternUtils(getContext());
         mHandler = new Handler(Looper.myLooper());
         mSmallClockScale = getResources().getDimension(R.dimen.widget_small_font_size)
@@ -145,6 +158,9 @@
     @Override
     protected void onFinishInflate() {
         super.onFinishInflate();
+        mLogoutView = findViewById(R.id.logout);
+        mLogoutView.setOnClickListener(this::onLogoutClicked);
+
         mClockContainer = findViewById(R.id.keyguard_clock_container);
         mClockView = findViewById(R.id.clock_view);
         mClockView.setShowCurrentUserTime(true);
@@ -164,6 +180,7 @@
         setEnableMarquee(shouldMarquee);
         refresh();
         updateOwnerInfo();
+        updateLogoutView();
 
         // Disable elegant text height because our fancy colon makes the ymin value huge for no
         // reason.
@@ -213,14 +230,28 @@
     }
 
     public int getClockBottom() {
-        return mKeyguardSlice.getVisibility() == VISIBLE ? mKeyguardSlice.getBottom()
-                : mClockView.getBottom();
+        if (mOwnerInfo != null && mOwnerInfo.getVisibility() == VISIBLE) {
+            return mOwnerInfo.getBottom();
+        } else {
+            return mClockContainer.getBottom();
+        }
+    }
+
+    public int getLogoutButtonHeight() {
+        return mLogoutView.getVisibility() == VISIBLE ? mLogoutView.getHeight() : 0;
     }
 
     public float getClockTextSize() {
         return mClockView.getTextSize();
     }
 
+    private void updateLogoutView() {
+        mLogoutView.setVisibility(shouldShowLogout() ? VISIBLE : GONE);
+        // Logout button will stay in language of user 0 if we don't set that manually.
+        mLogoutView.setText(mContext.getResources().getString(
+                com.android.internal.R.string.global_action_logout));
+    }
+
     private void updateOwnerInfo() {
         if (mOwnerInfo == null) return;
         String ownerInfo = getOwnerInfo();
@@ -309,6 +340,7 @@
         mDarkAmount = darkAmount;
 
         boolean dark = darkAmount == 1;
+        mLogoutView.setAlpha(dark ? 0 : 1);
         final int N = mClockContainer.getChildCount();
         for (int i = 0; i < N; i++) {
             View child = mClockContainer.getChildAt(i);
@@ -340,4 +372,19 @@
             child.setAlpha(mDarkAmount == 1 && mPulsing ? 0.8f : 1);
         }
     }
+
+    private boolean shouldShowLogout() {
+        return KeyguardUpdateMonitor.getInstance(mContext).isLogoutEnabled()
+                && KeyguardUpdateMonitor.getCurrentUser() != UserHandle.USER_SYSTEM;
+    }
+
+    private void onLogoutClicked(View view) {
+        int currentUserId = KeyguardUpdateMonitor.getCurrentUser();
+        try {
+            mIActivityManager.switchUser(UserHandle.USER_SYSTEM);
+            mIActivityManager.stopUser(currentUserId, true /*force*/, null);
+        } catch (RemoteException re) {
+            Log.e(TAG, "Failed to logout user", re);
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 9f5af08..d7196bf 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -141,6 +141,7 @@
     private static final int MSG_USER_UNLOCKED = 334;
     private static final int MSG_ASSISTANT_STACK_CHANGED = 335;
     private static final int MSG_FINGERPRINT_AUTHENTICATION_CONTINUE = 336;
+    private static final int MSG_DEVICE_POLICY_MANAGER_STATE_CHANGED = 337;
     private static final int MSG_LOCALE_CHANGED = 500;
 
     /** Fingerprint state: Not listening to fingerprint. */
@@ -226,6 +227,8 @@
     private LockPatternUtils mLockPatternUtils;
     private final IDreamManager mDreamManager;
     private boolean mIsDreaming;
+    private final DevicePolicyManager mDevicePolicyManager;
+    private boolean mLogoutEnabled;
 
     /**
      * Short delay before restarting fingerprint authentication after a successful try
@@ -333,6 +336,9 @@
                     break;
                 case MSG_LOCALE_CHANGED:
                     handleLocaleChanged();
+                   break;
+                case MSG_DEVICE_POLICY_MANAGER_STATE_CHANGED:
+                    updateLogoutEnabled();
                     break;
             }
         }
@@ -801,6 +807,9 @@
                         mHandler.obtainMessage(MSG_SERVICE_STATE_CHANGE, subId, 0, serviceState));
             } else if (Intent.ACTION_LOCALE_CHANGED.equals(action)) {
                 mHandler.sendEmptyMessage(MSG_LOCALE_CHANGED);
+            } else if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED.equals(
+                    action)) {
+                mHandler.sendEmptyMessage(MSG_DEVICE_POLICY_MANAGER_STATE_CHANGED);
             }
         }
     };
@@ -1166,6 +1175,7 @@
         filter.addAction(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED);
         filter.addAction(TelephonyManager.ACTION_PHONE_STATE_CHANGED);
         filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION);
+        filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
         context.registerReceiver(mBroadcastReceiver, filter);
 
         final IntentFilter bootCompleteFilter = new IntentFilter();
@@ -1220,6 +1230,8 @@
 
         ActivityManagerWrapper.getInstance().registerTaskStackListener(mTaskStackListener);
         mUserManager = context.getSystemService(UserManager.class);
+        mDevicePolicyManager = context.getSystemService(DevicePolicyManager.class);
+        mLogoutEnabled = mDevicePolicyManager.isLogoutEnabled();
     }
 
     private void updateFingerprintListeningState() {
@@ -1986,6 +1998,26 @@
         return null; // not found
     }
 
+    /**
+     * @return a cached version of DevicePolicyManager.isLogoutEnabled()
+     */
+    public boolean isLogoutEnabled() {
+        return mLogoutEnabled;
+    }
+
+    private void updateLogoutEnabled() {
+        boolean logoutEnabled = mDevicePolicyManager.isLogoutEnabled();
+        if (mLogoutEnabled != logoutEnabled) {
+            mLogoutEnabled = logoutEnabled;
+            for (int i = 0; i < mCallbacks.size(); i++) {
+                KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
+                if (cb != null) {
+                    cb.onLogoutEnabledChanged();
+                }
+            }
+        }
+    }
+
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         pw.println("KeyguardUpdateMonitor state:");
         pw.println("  SIM States:");
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
index 6284000..730ccb9 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
@@ -291,4 +291,11 @@
      * @see KeyguardIndicationController#showTransientIndication(CharSequence)
      */
     public void onTrustAgentErrorMessage(CharSequence message) { }
+
+
+    /**
+     * Called when a value of logout enabled is change.
+     */
+    public void onLogoutEnabledChanged() { }
+
 }
diff --git a/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java
index b7e1d67..1185f45 100644
--- a/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java
@@ -47,6 +47,8 @@
 import java.util.ArrayList;
 import java.util.List;
 
+import static com.android.systemui.shared.system.NavigationBarCompat.InteractionType;
+
 /**
  * Class to send information from overview to launcher with a binder.
  */
@@ -66,6 +68,8 @@
 
     private IOverviewProxy mOverviewProxy;
     private int mConnectionBackoffAttempts;
+    private CharSequence mOnboardingText;
+    private @InteractionType int mInteractionFlags;
 
     private ISystemUiProxy mSysUiProxy = new ISystemUiProxy.Stub() {
 
@@ -98,9 +102,27 @@
         public void onRecentsAnimationStarted() {
             long token = Binder.clearCallingIdentity();
             try {
-                mHandler.post(() -> {
-                    notifyRecentsAnimationStarted();
-                });
+                mHandler.post(OverviewProxyService.this::notifyRecentsAnimationStarted);
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+
+        public void setRecentsOnboardingText(CharSequence text) {
+            mOnboardingText = text;
+        }
+
+        public void setInteractionState(@InteractionType int flags) {
+            long token = Binder.clearCallingIdentity();
+            try {
+                if (mInteractionFlags != flags) {
+                    mInteractionFlags = flags;
+                    mHandler.post(() -> {
+                        for (int i = mConnectionCallbacks.size() - 1; i >= 0; --i) {
+                            mConnectionCallbacks.get(i).onInteractionFlagsChanged(flags);
+                        }
+                    });
+                }
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
@@ -223,8 +245,12 @@
         return mOverviewProxy;
     }
 
-    public ComponentName getLauncherComponent() {
-        return mLauncherComponentName;
+    public CharSequence getOnboardingText() {
+        return mOnboardingText;
+    }
+
+    public int getInteractionFlags() {
+        return mInteractionFlags;
     }
 
     private void disconnectFromLauncherService() {
@@ -260,5 +286,6 @@
     public interface OverviewProxyListener {
         default void onConnectionChanged(boolean isConnected) {}
         default void onRecentsAnimationStarted() {}
+        default void onInteractionFlagsChanged(@InteractionType int flags) {}
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/Prefs.java b/packages/SystemUI/src/com/android/systemui/Prefs.java
index 9319bc6..adb4e33 100644
--- a/packages/SystemUI/src/com/android/systemui/Prefs.java
+++ b/packages/SystemUI/src/com/android/systemui/Prefs.java
@@ -49,7 +49,7 @@
         Key.QS_NIGHTDISPLAY_ADDED,
         Key.SEEN_MULTI_USER,
         Key.NUM_APPS_LAUNCHED,
-        Key.HAS_SWIPED_UP_FOR_RECENTS,
+        Key.HAS_SEEN_RECENTS_ONBOARDING,
     })
     public @interface Key {
         @Deprecated
@@ -78,7 +78,7 @@
         String QS_NIGHTDISPLAY_ADDED = "QsNightDisplayAdded";
         String SEEN_MULTI_USER = "HasSeenMultiUser";
         String NUM_APPS_LAUNCHED = "NumAppsLaunched";
-        String HAS_SWIPED_UP_FOR_RECENTS = "HasSwipedUpForRecents";
+        String HAS_SEEN_RECENTS_ONBOARDING = "HasSeenRecentsOnboarding";
     }
 
     public static boolean getBoolean(Context context, @Key String key, boolean defaultValue) {
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/SystemUIService.java b/packages/SystemUI/src/com/android/systemui/SystemUIService.java
index ddf0bd0..bb82a54 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIService.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIService.java
@@ -28,6 +28,8 @@
 import java.io.PrintWriter;
 
 import com.android.internal.os.BinderInternal;
+import com.android.systemui.plugins.PluginManager;
+import com.android.systemui.plugins.PluginManagerImpl;
 
 public class SystemUIService extends Service {
 
@@ -70,6 +72,10 @@
                 pw.println("dumping service: " + ui.getClass().getName());
                 ui.dump(fd, pw, args);
             }
+            if (Build.IS_DEBUGGABLE) {
+                pw.println("dumping plugins:");
+                ((PluginManagerImpl) Dependency.get(PluginManager.class)).dump(fd, pw, args);
+            }
         } else {
             String svc = args[0];
             for (SystemUI ui: services) {
diff --git a/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingAnimation.java b/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingAnimation.java
index 348855b..afc9629 100644
--- a/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingAnimation.java
+++ b/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingAnimation.java
@@ -19,7 +19,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.Context;
-import android.content.res.Configuration;
 import android.graphics.PixelFormat;
 import android.os.Handler;
 import android.os.Looper;
@@ -36,13 +35,18 @@
  */
 public class WirelessChargingAnimation {
 
-    public static final long DURATION = 1400;
+    public static final long DURATION = 1133;
     private static final String TAG = "WirelessChargingView";
     private static final boolean LOCAL_LOGV = false;
 
     private final WirelessChargingView mCurrentWirelessChargingView;
     private static WirelessChargingView mPreviousWirelessChargingView;
 
+    public interface Callback {
+        void onAnimationStarting();
+        void onAnimationEnded();
+    }
+
     /**
      * Constructs an empty WirelessChargingAnimation object.  If looper is null,
      * Looper.myLooper() is used.  Must set
@@ -51,9 +55,9 @@
      * @hide
      */
     public WirelessChargingAnimation(@NonNull Context context, @Nullable Looper looper, int
-            batteryLevel) {
+            batteryLevel, Callback callback) {
         mCurrentWirelessChargingView = new WirelessChargingView(context, looper,
-                batteryLevel);
+                batteryLevel, callback);
     }
 
     /**
@@ -61,8 +65,8 @@
      * @hide
      */
     public static WirelessChargingAnimation makeWirelessChargingAnimation(@NonNull Context context,
-            @Nullable Looper looper, int batteryLevel) {
-        return new WirelessChargingAnimation(context, looper, batteryLevel);
+            @Nullable Looper looper, int batteryLevel, Callback callback) {
+        return new WirelessChargingAnimation(context, looper, batteryLevel, callback);
     }
 
     /**
@@ -95,8 +99,11 @@
         private View mView;
         private View mNextView;
         private WindowManager mWM;
+        private Callback mCallback;
 
-        public WirelessChargingView(Context context, @Nullable Looper looper, int batteryLevel) {
+        public WirelessChargingView(Context context, @Nullable Looper looper, int batteryLevel,
+                Callback callback) {
+            mCallback = callback;
             mNextView = new WirelessChargingLayout(context, batteryLevel);
             mGravity = Gravity.CENTER_HORIZONTAL | Gravity.CENTER;
 
@@ -149,6 +156,8 @@
         }
 
         public void hide(long duration) {
+            mHandler.removeMessages(HIDE);
+
             if (LOCAL_LOGV) Log.v(TAG, "HIDE: " + this);
             mHandler.sendMessageDelayed(Message.obtain(mHandler, HIDE), duration);
         }
@@ -169,18 +178,6 @@
                     context = mView.getContext();
                 }
                 mWM = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
-                // We can resolve the Gravity here by using the Locale for getting
-                // the layout direction
-                final Configuration config = mView.getContext().getResources().getConfiguration();
-                final int gravity = Gravity.getAbsoluteGravity(mGravity,
-                        config.getLayoutDirection());
-                mParams.gravity = gravity;
-                if ((gravity & Gravity.HORIZONTAL_GRAVITY_MASK) == Gravity.FILL_HORIZONTAL) {
-                    mParams.horizontalWeight = 1.0f;
-                }
-                if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == Gravity.FILL_VERTICAL) {
-                    mParams.verticalWeight = 1.0f;
-                }
                 mParams.packageName = packageName;
                 mParams.hideTimeoutMilliseconds = DURATION;
 
@@ -191,6 +188,9 @@
                 if (LOCAL_LOGV) Log.v(TAG, "ADD! " + mView + " in " + this);
 
                 try {
+                    if (mCallback != null) {
+                        mCallback.onAnimationStarting();
+                    }
                     mWM.addView(mView, mParams);
                 } catch (WindowManager.BadTokenException e) {
                     Slog.d(TAG, "Unable to add wireless charging view. " + e);
@@ -203,6 +203,9 @@
             if (mView != null) {
                 if (mView.getParent() != null) {
                     if (LOCAL_LOGV) Log.v(TAG, "REMOVE! " + mView + " in " + this);
+                    if (mCallback != null) {
+                        mCallback.onAnimationEnded();
+                    }
                     mWM.removeViewImmediate(mView);
                 }
 
diff --git a/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingLayout.java b/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingLayout.java
index c78ea56..8f87d64 100644
--- a/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingLayout.java
@@ -16,13 +16,16 @@
 
 package com.android.systemui.charging;
 
+import android.animation.AnimatorSet;
 import android.animation.ObjectAnimator;
 import android.animation.ValueAnimator;
 import android.content.Context;
 import android.util.AttributeSet;
+import android.view.animation.PathInterpolator;
 import android.widget.FrameLayout;
 import android.widget.TextView;
 
+import com.android.systemui.Interpolators;
 import com.android.systemui.R;
 
 import java.text.NumberFormat;
@@ -52,10 +55,9 @@
         init(c, attrs, -1);
     }
 
-    private void init(Context c, AttributeSet attrs, int batteryLevel) {
+    private void init(Context context, AttributeSet attrs, int batteryLevel) {
         final int mBatteryLevel = batteryLevel;
-
-        inflate(c, R.layout.wireless_charging_layout, this);
+        inflate(context, R.layout.wireless_charging_layout, this);
 
         // where the circle animation occurs:
         final WirelessChargingView mChargingView = findViewById(R.id.wireless_charging_view);
@@ -68,14 +70,57 @@
 
         if (batteryLevel != UNKNOWN_BATTERY_LEVEL) {
             mPercentage.setText(NumberFormat.getPercentInstance().format(mBatteryLevel / 100f));
-
-            ValueAnimator animator = ObjectAnimator.ofFloat(mPercentage, "textSize",
-                    getContext().getResources().getFloat(R.dimen.config_batteryLevelTextSizeStart),
-                    getContext().getResources().getFloat(R.dimen.config_batteryLevelTextSizeEnd));
-
-            animator.setDuration((long) getContext().getResources().getInteger(
-                    R.integer.config_batteryLevelTextAnimationDuration));
-            animator.start();
+            mPercentage.setAlpha(0);
         }
+
+        final long chargingAnimationFadeStartOffset = (long) context.getResources().getInteger(
+                R.integer.wireless_charging_fade_offset);
+        final long chargingAnimationFadeDuration = (long) context.getResources().getInteger(
+                R.integer.wireless_charging_fade_duration);
+        final int batteryLevelTextSizeStart = context.getResources().getDimensionPixelSize(
+                R.dimen.wireless_charging_anim_battery_level_text_size_start);
+        final int batteryLevelTextSizeEnd = context.getResources().getDimensionPixelSize(
+                R.dimen.wireless_charging_anim_battery_level_text_size_end);
+
+        // Animation Scale: battery percentage text scales from 0% to 100%
+        ValueAnimator textSizeAnimator = ObjectAnimator.ofFloat(mPercentage, "textSize",
+                batteryLevelTextSizeStart, batteryLevelTextSizeEnd);
+        textSizeAnimator.setInterpolator(new PathInterpolator(0, 0, 0, 1));
+        textSizeAnimator.setDuration((long) context.getResources().getInteger(
+                R.integer.wireless_charging_battery_level_text_scale_animation_duration));
+
+        // Animation Opacity: battery percentage text transitions from 0 to 1 opacity
+        ValueAnimator textOpacityAnimator = ObjectAnimator.ofFloat(mPercentage, "alpha", 0, 1);
+        textOpacityAnimator.setInterpolator(Interpolators.LINEAR);
+        textOpacityAnimator.setDuration((long) context.getResources().getInteger(
+                R.integer.wireless_charging_battery_level_text_opacity_duration));
+        textOpacityAnimator.setStartDelay((long) context.getResources().getInteger(
+                R.integer.wireless_charging_anim_opacity_offset));
+
+        // Animation Opacity: battery percentage text fades from 1 to 0 opacity
+        ValueAnimator textFadeAnimator = ObjectAnimator.ofFloat(mPercentage, "alpha", 1, 0);
+        textFadeAnimator.setDuration(chargingAnimationFadeDuration);
+        textFadeAnimator.setInterpolator(Interpolators.LINEAR);
+        textFadeAnimator.setStartDelay(chargingAnimationFadeStartOffset);
+
+        // Animation Opacity: wireless charging circle animation fades from 1 to 0 opacity
+        ValueAnimator circleFadeAnimator = ObjectAnimator.ofFloat(mChargingView, "alpha",
+                1, 0);
+        circleFadeAnimator.setDuration(chargingAnimationFadeDuration);
+        circleFadeAnimator.setInterpolator(Interpolators.LINEAR);
+        circleFadeAnimator.setStartDelay(chargingAnimationFadeStartOffset);
+
+        // Animation Opacity: secondary text animation fades from 1 to 0 opacity
+        ValueAnimator secondaryTextFadeAnimator = ObjectAnimator.ofFloat(mSecondaryText, "alpha",
+                1, 0);
+        circleFadeAnimator.setDuration(chargingAnimationFadeDuration);
+        secondaryTextFadeAnimator.setInterpolator(Interpolators.LINEAR);
+        secondaryTextFadeAnimator.setStartDelay(chargingAnimationFadeStartOffset);
+
+        // play all animations together
+        AnimatorSet animatorSet = new AnimatorSet();
+        animatorSet.playTogether(textSizeAnimator, textOpacityAnimator, textFadeAnimator,
+                circleFadeAnimator, secondaryTextFadeAnimator);
+        animatorSet.start();
     }
-}
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingView.java b/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingView.java
index f5edf52..19c6dc1 100644
--- a/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingView.java
+++ b/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingView.java
@@ -21,10 +21,10 @@
 import android.graphics.Paint;
 import android.util.AttributeSet;
 import android.view.View;
-import android.view.animation.DecelerateInterpolator;
 import android.view.animation.Interpolator;
 
 import com.android.settingslib.Utils;
+import com.android.systemui.Interpolators;
 import com.android.systemui.R;
 
 final class WirelessChargingView extends View {
@@ -33,21 +33,21 @@
     private float mPathGone;
     private float mInterpolatedPathGone;
     private long mAnimationStartTime;
-    private long mStartSpinCircleAnimationTime;
-    private long mAnimationOffset = 500;
-    private long mTotalAnimationDuration = WirelessChargingAnimation.DURATION - mAnimationOffset;
-    private long mExpandingCircle = (long) (mTotalAnimationDuration * .9);
-    private long mSpinCircleAnimationTime = mTotalAnimationDuration - mExpandingCircle;
+    private long mScaleDotsDuration;
 
-    private boolean mFinishedAnimatingSpinningCircles = false;
+    private boolean mFinishedAnimatingDots = false;
+    private int mNumDots;
 
-    private int mStartAngle = -90;
-    private int mNumSmallCircles = 20;
-    private int mSmallCircleRadius = 10;
+    private double mAngleOffset;
+    private double mCurrAngleOffset;
 
-    private int mMainCircleStartRadius = 100;
-    private int mMainCircleEndRadius = 230;
-    private int mMainCircleCurrentRadius = mMainCircleStartRadius;
+    private int mDotsRadiusStart;
+    private int mDotsRadiusEnd;
+    private int mCurrDotRadius;
+
+    private int mMainCircleStartRadius;
+    private int mMainCircleEndRadius;
+    private int mMainCircleCurrentRadius;
 
     private int mCenterX;
     private int mCenterY;
@@ -72,8 +72,25 @@
 
     public void init(Context context, AttributeSet attr) {
         mContext = context;
+
+        mDotsRadiusStart = context.getResources().getDimensionPixelSize(
+                R.dimen.wireless_charging_dots_radius_start);
+        mDotsRadiusEnd = context.getResources().getDimensionPixelSize(
+                R.dimen.wireless_charging_dots_radius_end);
+
+        mMainCircleStartRadius = context.getResources().getDimensionPixelSize(
+                R.dimen.wireless_charging_circle_radius_start);
+        mMainCircleEndRadius = context.getResources().getDimensionPixelSize(
+                R.dimen.wireless_charging_circle_radius_end);
+        mMainCircleCurrentRadius = mMainCircleStartRadius;
+
+        mAngleOffset = context.getResources().getInteger(R.integer.wireless_charging_angle_offset);
+        mScaleDotsDuration = (long) context.getResources().getInteger(
+                R.integer.wireless_charging_scale_dots_duration);
+        mNumDots = context.getResources().getInteger(R.integer.wireless_charging_num_dots);
+
         setupPaint();
-        mInterpolator = new DecelerateInterpolator();
+        mInterpolator = Interpolators.LINEAR_OUT_SLOW_IN;
     }
 
     private void setupPaint() {
@@ -92,64 +109,62 @@
         updateDrawingParameters();
         drawCircles(canvas);
 
-        if (!mFinishedAnimatingSpinningCircles) {
+        if (!mFinishedAnimatingDots) {
             invalidate();
         }
     }
 
     /**
      * Draws a larger circle of radius {@link WirelessChargingView#mMainCircleEndRadius} composed of
-     * {@link WirelessChargingView#mNumSmallCircles} smaller circles
+     * {@link WirelessChargingView#mNumDots} smaller circles
      * @param canvas
      */
     private void drawCircles(Canvas canvas) {
         mCenterX = canvas.getWidth() / 2;
         mCenterY = canvas.getHeight() / 2;
 
-        // angleOffset makes small circles look like they're moving around the main circle
-        float angleOffset = mPathGone * 10;
-
-        // draws mNumSmallCircles to compose a larger, main circle
-        for (int circle = 0; circle < mNumSmallCircles; circle++) {
-            double angle = ((mStartAngle + angleOffset) * Math.PI / 180) + (circle * ((2 * Math.PI)
-                    / mNumSmallCircles));
+        // draws mNumDots to compose a larger, main circle
+        for (int circle = 0; circle < mNumDots; circle++) {
+            double angle = ((mCurrAngleOffset) * Math.PI / 180) + (circle * ((2 * Math.PI)
+                    / mNumDots));
 
             int x = (int) (mCenterX + Math.cos(angle) * (mMainCircleCurrentRadius +
-                    mSmallCircleRadius));
+                    mCurrDotRadius));
             int y = (int) (mCenterY + Math.sin(angle) * (mMainCircleCurrentRadius +
-                    mSmallCircleRadius));
+                    mCurrDotRadius));
 
-            canvas.drawCircle(x, y, mSmallCircleRadius, mPaint);
+            canvas.drawCircle(x, y, mCurrDotRadius, mPaint);
         }
 
-        if (mMainCircleCurrentRadius >= mMainCircleEndRadius && !isSpinCircleAnimationStarted()) {
-            mStartSpinCircleAnimationTime = System.currentTimeMillis();
+        if (mMainCircleCurrentRadius >= mMainCircleEndRadius) {
+            mFinishedAnimatingDots = true;
         }
-
-        if (isSpinAnimationFinished()) {
-            mFinishedAnimatingSpinningCircles = true;
-        }
-    }
-
-    private boolean isSpinCircleAnimationStarted() {
-        return mStartSpinCircleAnimationTime != 0;
-    }
-
-    private boolean isSpinAnimationFinished() {
-        return isSpinCircleAnimationStarted() && System.currentTimeMillis() -
-                mStartSpinCircleAnimationTime > mSpinCircleAnimationTime;
     }
 
     private void updateDrawingParameters() {
-        mPathGone = getPathGone(System.currentTimeMillis());
+        long now = System.currentTimeMillis();
+        long timeSinceStart = now - mAnimationStartTime;
+        mPathGone = getPathGone(now);
         mInterpolatedPathGone = mInterpolator.getInterpolation(mPathGone);
 
+        // Position Dots: update main circle radius (that the dots compose)
         if (mPathGone < 1.0f) {
             mMainCircleCurrentRadius = mMainCircleStartRadius + (int) (mInterpolatedPathGone *
                     (mMainCircleEndRadius - mMainCircleStartRadius));
         } else {
             mMainCircleCurrentRadius = mMainCircleEndRadius;
         }
+
+        // Scale Dots: update dot radius
+        if (timeSinceStart < mScaleDotsDuration) {
+            mCurrDotRadius = mDotsRadiusStart + (int) (mInterpolator.getInterpolation((float)
+                    timeSinceStart / mScaleDotsDuration) * (mDotsRadiusEnd - mDotsRadiusStart));
+        } else {
+            mCurrDotRadius = mDotsRadiusEnd;
+        }
+
+        // Rotation Dot Group: dots rotate from 0 to 20 degrees
+        mCurrAngleOffset = mAngleOffset * mPathGone;
     }
 
     /**
@@ -158,6 +173,6 @@
      * For values > 1.0 the larger circle has been drawn and further animation can occur
      */
     private float getPathGone(long now) {
-        return (float) (now - mAnimationStartTime) / (mExpandingCircle);
+        return (float) (now - mAnimationStartTime) / (WirelessChargingAnimation.DURATION);
     }
 }
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
index bfb3a6e..092f3d2 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
@@ -64,7 +64,7 @@
                 createDozeTriggers(context, sensorManager, host, alarmManager, config, params,
                         handler, wakeLock, machine),
                 createDozeUi(context, host, wakeLock, machine, handler, alarmManager, params),
-                new DozeScreenState(wrappedService, handler),
+                new DozeScreenState(wrappedService, handler, params),
                 createDozeScreenBrightness(context, wrappedService, sensorManager, host, handler),
                 new DozeWallpaperState(context)
         });
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java b/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
index 8ec6afc..6ff8e3d 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
@@ -24,6 +24,7 @@
 
 import com.android.internal.hardware.AmbientDisplayConfiguration;
 import com.android.internal.util.Preconditions;
+import com.android.systemui.statusbar.phone.DozeParameters;
 import com.android.systemui.util.Assert;
 import com.android.systemui.util.wakelock.WakeLock;
 
@@ -87,12 +88,11 @@
             }
         }
 
-        int screenState() {
+        int screenState(DozeParameters parameters) {
             switch (this) {
                 case UNINITIALIZED:
                 case INITIALIZED:
                 case DOZE:
-                case DOZE_REQUEST_PULSE:
                 case DOZE_AOD_PAUSED:
                     return Display.STATE_OFF;
                 case DOZE_PULSING:
@@ -100,6 +100,9 @@
                 case DOZE_AOD:
                 case DOZE_AOD_PAUSING:
                     return Display.STATE_DOZE_SUSPEND;
+                case DOZE_REQUEST_PULSE:
+                    return parameters.getDisplayNeedsBlanking() ? Display.STATE_OFF
+                            : Display.STATE_ON;
                 default:
                     return Display.STATE_UNKNOWN;
             }
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java
index bef9cb3..3053de3 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java
@@ -19,6 +19,8 @@
 import android.os.Handler;
 import android.view.Display;
 
+import com.android.systemui.statusbar.phone.DozeParameters;
+
 /**
  * Controls the screen when dozing.
  */
@@ -26,17 +28,20 @@
     private final DozeMachine.Service mDozeService;
     private final Handler mHandler;
     private final Runnable mApplyPendingScreenState = this::applyPendingScreenState;
+    private final DozeParameters mParameters;
 
     private int mPendingScreenState = Display.STATE_UNKNOWN;
 
-    public DozeScreenState(DozeMachine.Service service, Handler handler) {
+    public DozeScreenState(DozeMachine.Service service, Handler handler,
+            DozeParameters parameters) {
         mDozeService = service;
         mHandler = handler;
+        mParameters = parameters;
     }
 
     @Override
     public void transitionTo(DozeMachine.State oldState, DozeMachine.State newState) {
-        int screenState = newState.screenState();
+        int screenState = newState.screenState(mParameters);
 
         if (newState == DozeMachine.State.FINISH) {
             // Make sure not to apply the screen state after DozeService was destroyed.
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
index 34d3928..aa26419 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
@@ -59,6 +59,12 @@
     }
 
     @Override
+    public void onDestroy() {
+        Dependency.get(PluginManager.class).removePluginListener(this);
+        super.onDestroy();
+    }
+
+    @Override
     public void onPluginConnected(DozeServicePlugin plugin, Context pluginContext) {
         mDozePlugin = plugin;
         mDozePlugin.setDozeRequester(this);
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
index c28b7ee..259bff2 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
@@ -688,7 +688,7 @@
     }
 
     private Action getLockdownAction() {
-        return new SinglePressAction(R.drawable.ic_lock_lock,
+        return new SinglePressAction(com.android.systemui.R.drawable.ic_lock_lockdown,
                 R.string.global_action_lockdown) {
 
             @Override
@@ -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/plugins/PluginInstanceManager.java b/packages/SystemUI/src/com/android/systemui/plugins/PluginInstanceManager.java
index 82c0128..d5541e9 100644
--- a/packages/SystemUI/src/com/android/systemui/plugins/PluginInstanceManager.java
+++ b/packages/SystemUI/src/com/android/systemui/plugins/PluginInstanceManager.java
@@ -168,6 +168,12 @@
         return false;
     }
 
+    @Override
+    public String toString() {
+        return String.format("%s@%s (action=%s)",
+                getClass().getSimpleName(), hashCode(), mAction);
+    }
+
     private class MainHandler extends Handler {
         private static final int PLUGIN_CONNECTED = 1;
         private static final int PLUGIN_DISCONNECTED = 2;
diff --git a/packages/SystemUI/src/com/android/systemui/plugins/PluginManagerImpl.java b/packages/SystemUI/src/com/android/systemui/plugins/PluginManagerImpl.java
index 03747d5..2a17e35 100644
--- a/packages/SystemUI/src/com/android/systemui/plugins/PluginManagerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/plugins/PluginManagerImpl.java
@@ -50,6 +50,8 @@
 
 import dalvik.system.PathClassLoader;
 
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
 import java.lang.Thread.UncaughtExceptionHandler;
 import java.util.Map;
 
@@ -303,6 +305,14 @@
         }
     }
 
+    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        pw.println(String.format("  plugin map (%d):", mPluginMap.size()));
+        for (PluginListener listener: mPluginMap.keySet()) {
+            pw.println(String.format("    %s -> %s",
+                    listener, mPluginMap.get(listener)));
+        }
+    }
+
     @VisibleForTesting
     public static class PluginInstanceManagerFactory {
         public <T extends Plugin> PluginInstanceManager createPluginInstanceManager(Context context,
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
index aa56694..3a2b12f 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
@@ -26,10 +26,6 @@
 import android.content.DialogInterface.OnDismissListener;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.icu.text.MeasureFormat;
-import android.icu.text.MeasureFormat.FormatWidth;
-import android.icu.util.Measure;
-import android.icu.util.MeasureUnit;
 import android.media.AudioAttributes;
 import android.os.AsyncTask;
 import android.os.Handler;
@@ -37,11 +33,11 @@
 import android.os.PowerManager;
 import android.os.UserHandle;
 import android.support.annotation.VisibleForTesting;
-import android.text.format.DateUtils;
 import android.util.Slog;
 
 import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
 import com.android.settingslib.Utils;
+import com.android.settingslib.utils.PowerUtil;
 import com.android.systemui.R;
 import com.android.systemui.SystemUI;
 import com.android.systemui.statusbar.phone.SystemUIDialog;
@@ -49,8 +45,6 @@
 
 import java.io.PrintWriter;
 import java.text.NumberFormat;
-import java.util.Locale;
-import java.util.concurrent.TimeUnit;
 
 public class PowerNotificationWarnings implements PowerUI.WarningsUI {
     private static final String TAG = PowerUI.TAG + ".Notification";
@@ -200,12 +194,7 @@
         // override notification copy if hybrid notification enabled
         if (mEstimate != null) {
             title = mContext.getString(R.string.battery_low_title_hybrid);
-            contentText = mContext.getString(
-                    mEstimate.isBasedOnUsage
-                            ? R.string.battery_low_percent_format_hybrid
-                            : R.string.battery_low_percent_format_hybrid_short,
-                    percentage,
-                    getTimeRemainingFormatted());
+            contentText = getHybridContentString(percentage);
         }
 
         final Notification.Builder nb =
@@ -239,21 +228,12 @@
         mNoMan.notifyAsUser(TAG_BATTERY, SystemMessage.NOTE_POWER_LOW, n, UserHandle.ALL);
     }
 
-    @VisibleForTesting
-    String getTimeRemainingFormatted() {
-        final Locale currentLocale = mContext.getResources().getConfiguration().getLocales().get(0);
-        MeasureFormat frmt = MeasureFormat.getInstance(currentLocale, FormatWidth.NARROW);
-
-        final long remainder = mEstimate.estimateMillis % DateUtils.HOUR_IN_MILLIS;
-        final long hours = TimeUnit.MILLISECONDS.toHours(
-                mEstimate.estimateMillis - remainder);
-        // round down to the nearest 15 min for now to not appear overly precise
-        final long minutes = TimeUnit.MILLISECONDS.toMinutes(
-                remainder - (remainder % TimeUnit.MINUTES.toMillis(15)));
-        final Measure hoursMeasure = new Measure(hours, MeasureUnit.HOUR);
-        final Measure minutesMeasure = new Measure(minutes, MeasureUnit.MINUTE);
-
-        return frmt.formatMeasures(hoursMeasure, minutesMeasure);
+    private String getHybridContentString(String percentage) {
+        return PowerUtil.getBatteryRemainingStringFormatted(
+            mContext,
+            mEstimate.estimateMillis,
+            percentage,
+            mEstimate.isBasedOnUsage);
     }
 
     private PendingIntent pendingBroadcast(String action) {
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
index ea2a432..ac86c8a 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
@@ -53,7 +53,6 @@
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.Arrays;
-import java.util.concurrent.TimeUnit;
 
 public class PowerUI extends SystemUI {
     static final String TAG = "PowerUI";
@@ -72,10 +71,11 @@
     private final Configuration mLastConfiguration = new Configuration();
     private int mBatteryLevel = 100;
     private long mTimeRemaining = Long.MAX_VALUE;
-    private int mBatteryStatus = BatteryManager.BATTERY_STATUS_UNKNOWN;
     private int mPlugType = 0;
     private int mInvalidCharger = 0;
     private EnhancedEstimates mEnhancedEstimates;
+    private boolean mLowWarningShownThisChargeCycle;
+    private boolean mSevereWarningShownThisChargeCycle;
 
     private int mLowBatteryAlertCloseLevel;
     private final int[] mLowBatteryReminderLevels = new int[2];
@@ -88,6 +88,8 @@
     private long mNextLogTime;
     private IThermalService mThermalService;
 
+    @VisibleForTesting int mBatteryStatus = BatteryManager.BATTERY_STATUS_UNKNOWN;
+
     // by using the same instance (method references are not guaranteed to be the same object
     // We create a method reference here so that we are guaranteed that we can remove a callback
     // each time they are created).
@@ -218,6 +220,12 @@
 
                 final boolean plugged = mPlugType != 0;
                 final boolean oldPlugged = oldPlugType != 0;
+                // if we are now unplugged but we were previously plugged in we should allow the
+                // time based trigger again.
+                if (!plugged && plugged != oldPlugged) {
+                    mLowWarningShownThisChargeCycle = false;
+                    mSevereWarningShownThisChargeCycle = false;
+                }
 
                 int oldBucket = findBatteryLevelBucket(oldBatteryLevel);
                 int bucket = findBatteryLevelBucket(mBatteryLevel);
@@ -268,7 +276,6 @@
         boolean isPowerSaver = mPowerManager.isPowerSaveMode();
         // only play SFX when the dialog comes up or the bucket changes
         final boolean playSound = bucket != oldBucket || oldPlugged;
-        long oldTimeRemaining = mTimeRemaining;
         if (mEnhancedEstimates.isHybridNotificationEnabled()) {
             final Estimate estimate = mEnhancedEstimates.getEstimate();
             // Turbo is not always booted once SysUI is running so we have ot make sure we actually
@@ -281,10 +288,18 @@
             }
         }
 
-        if (shouldShowLowBatteryWarning(plugged, oldPlugged, oldBucket, bucket, oldTimeRemaining,
-                mTimeRemaining,
-                isPowerSaver, mBatteryStatus)) {
+        if (shouldShowLowBatteryWarning(plugged, oldPlugged, oldBucket, bucket,
+                mTimeRemaining, isPowerSaver, mBatteryStatus)) {
             mWarnings.showLowBatteryWarning(playSound);
+
+            // mark if we've already shown a warning this cycle. This will prevent the time based
+            // trigger from spamming users since the time remaining can vary based on current
+            // device usage.
+            if (mTimeRemaining < mEnhancedEstimates.getSevereWarningThreshold()) {
+                mSevereWarningShownThisChargeCycle = true;
+            } else {
+                mLowWarningShownThisChargeCycle = true;
+            }
         } else if (shouldDismissLowBatteryWarning(plugged, oldBucket, bucket, mTimeRemaining,
                 isPowerSaver)) {
             mWarnings.dismissLowBatteryWarning();
@@ -295,22 +310,14 @@
 
     @VisibleForTesting
     boolean shouldShowLowBatteryWarning(boolean plugged, boolean oldPlugged, int oldBucket,
-            int bucket, long oldTimeRemaining, long timeRemaining,
-            boolean isPowerSaver, int mBatteryStatus) {
+            int bucket, long timeRemaining, boolean isPowerSaver, int mBatteryStatus) {
         return !plugged
                 && !isPowerSaver
                 && (((bucket < oldBucket || oldPlugged) && bucket < 0)
-                        || (mEnhancedEstimates.isHybridNotificationEnabled()
-                                && timeRemaining < mEnhancedEstimates.getLowWarningThreshold()
-                                && isHourLess(oldTimeRemaining, timeRemaining)))
+                        || isTimeBasedTrigger(timeRemaining))
                 && mBatteryStatus != BatteryManager.BATTERY_STATUS_UNKNOWN;
     }
 
-    private boolean isHourLess(long oldTimeRemaining, long timeRemaining) {
-        final long dif = oldTimeRemaining - timeRemaining;
-        return dif >= TimeUnit.HOURS.toMillis(1);
-    }
-
     @VisibleForTesting
     boolean shouldDismissLowBatteryWarning(boolean plugged, int oldBucket, int bucket,
             long timeRemaining, boolean isPowerSaver) {
@@ -323,6 +330,23 @@
                         || hybridWouldDismiss));
     }
 
+    private boolean isTimeBasedTrigger(long timeRemaining) {
+        if (!mEnhancedEstimates.isHybridNotificationEnabled()) {
+            return false;
+        }
+
+        // Only show the time based warning once per charge cycle
+        final boolean canShowWarning = timeRemaining < mEnhancedEstimates.getLowWarningThreshold()
+                && !mLowWarningShownThisChargeCycle;
+
+        // Only show the severe time based warning once per charge cycle
+        final boolean canShowSevereWarning =
+                timeRemaining < mEnhancedEstimates.getSevereWarningThreshold()
+                        && !mSevereWarningShownThisChargeCycle;
+
+        return canShowWarning || canShowSevereWarning;
+    }
+
     private void initTemperatureWarning() {
         ContentResolver resolver = mContext.getContentResolver();
         Resources resources = mContext.getResources();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/CellTileView.java b/packages/SystemUI/src/com/android/systemui/qs/CellTileView.java
index 5f26093..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/QSFooterImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java
index fe3ffb9..e241357 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java
@@ -174,7 +174,9 @@
                 .addFloat(mDivider, "alpha", 0, 1)
                 .addFloat(mCarrierText, "alpha", 0, 1)
                 .addFloat(mActionsContainer, "alpha", 0, 1)
-                .addFloat(mDragHandle, "translationY", 0, -mDragHandleExpandOffset)
+                .addFloat(mDragHandle, "translationY", mDragHandleExpandOffset, 0)
+                .addFloat(mDragHandle, "alpha", 1, 0)
+                .setStartDelay(0.15f)
                 .build();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSScrollLayout.java b/packages/SystemUI/src/com/android/systemui/qs/QSScrollLayout.java
index 9cda75c..7b1509d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSScrollLayout.java
@@ -14,8 +14,11 @@
 
 package com.android.systemui.qs;
 
+import android.animation.ObjectAnimator;
 import android.content.Context;
+import android.graphics.Canvas;
 import android.support.v4.widget.NestedScrollView;
+import android.util.Property;
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewConfiguration;
@@ -23,6 +26,8 @@
 import android.widget.LinearLayout;
 
 import com.android.systemui.R;
+import com.android.systemui.qs.touch.OverScroll;
+import com.android.systemui.qs.touch.SwipeDetector;
 
 /**
  * Quick setting scroll view containing the brightness slider and the QS tiles.
@@ -35,6 +40,9 @@
     private final int mTouchSlop;
     private final int mFooterHeight;
     private int mLastMotionY;
+    private final SwipeDetector mSwipeDetector;
+    private final OverScrollHelper mOverScrollHelper;
+    private float mContentTranslationY;
 
     public QSScrollLayout(Context context, View... children) {
         super(context);
@@ -49,6 +57,35 @@
             linearLayout.addView(view);
         }
         addView(linearLayout);
+        setOverScrollMode(OVER_SCROLL_NEVER);
+        mOverScrollHelper = new OverScrollHelper();
+        mSwipeDetector = new SwipeDetector(context, mOverScrollHelper, SwipeDetector.VERTICAL);
+        mSwipeDetector.setDetectableScrollConditions(SwipeDetector.DIRECTION_BOTH, true);
+    }
+
+    @Override
+    public boolean onInterceptTouchEvent(MotionEvent ev) {
+        if (!canScrollVertically(1) && !canScrollVertically(-1)) {
+            return false;
+        }
+        mSwipeDetector.onTouchEvent(ev);
+        return super.onInterceptTouchEvent(ev) || mOverScrollHelper.isInOverScroll();
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent ev) {
+        if (!canScrollVertically(1) && !canScrollVertically(-1)) {
+            return false;
+        }
+        mSwipeDetector.onTouchEvent(ev);
+        return super.onTouchEvent(ev);
+    }
+
+    @Override
+    protected void dispatchDraw(Canvas canvas) {
+        canvas.translate(0, mContentTranslationY);
+        super.dispatchDraw(canvas);
+        canvas.translate(0, -mContentTranslationY);
     }
 
     public boolean shouldIntercept(MotionEvent ev) {
@@ -81,4 +118,81 @@
             parent.requestDisallowInterceptTouchEvent(disallowIntercept);
         }
     }
+
+    private void setContentTranslationY(float contentTranslationY) {
+        mContentTranslationY = contentTranslationY;
+        invalidate();
+    }
+
+    private static final Property<QSScrollLayout, Float> CONTENT_TRANS_Y =
+            new Property<QSScrollLayout, Float>(Float.class, "qsScrollLayoutContentTransY") {
+                @Override
+                public Float get(QSScrollLayout qsScrollLayout) {
+                    return qsScrollLayout.mContentTranslationY;
+                }
+
+                @Override
+                public void set(QSScrollLayout qsScrollLayout, Float y) {
+                    qsScrollLayout.setContentTranslationY(y);
+                }
+            };
+
+    private class OverScrollHelper implements SwipeDetector.Listener {
+        private boolean mIsInOverScroll;
+
+        // We use this value to calculate the actual amount the user has overscrolled.
+        private float mFirstDisplacement = 0;
+
+        @Override
+        public void onDragStart(boolean start) {}
+
+        @Override
+        public boolean onDrag(float displacement, float velocity) {
+            // Only overscroll if the user is scrolling down when they're already at the bottom
+            // or scrolling up when they're already at the top.
+            boolean wasInOverScroll = mIsInOverScroll;
+            mIsInOverScroll = (!canScrollVertically(1) && displacement < 0) ||
+                    (!canScrollVertically(-1) && displacement > 0);
+
+            if (wasInOverScroll && !mIsInOverScroll) {
+                // Exit overscroll. This can happen when the user is in overscroll and then
+                // scrolls the opposite way. Note that this causes the reset translation animation
+                // to run while the user is dragging, which feels a bit unnatural.
+                reset();
+            } else if (mIsInOverScroll) {
+                if (Float.compare(mFirstDisplacement, 0) == 0) {
+                    // Because users can scroll before entering overscroll, we need to
+                    // subtract the amount where the user was not in overscroll.
+                    mFirstDisplacement = displacement;
+                }
+                float overscrollY = displacement - mFirstDisplacement;
+                setContentTranslationY(getDampedOverScroll(overscrollY));
+            }
+
+            return mIsInOverScroll;
+        }
+
+        @Override
+        public void onDragEnd(float velocity, boolean fling) {
+            reset();
+        }
+
+        private void reset() {
+            if (Float.compare(mContentTranslationY, 0) != 0) {
+                ObjectAnimator.ofFloat(QSScrollLayout.this, CONTENT_TRANS_Y, 0)
+                        .setDuration(100)
+                        .start();
+            }
+            mIsInOverScroll = false;
+            mFirstDisplacement = 0;
+        }
+
+        public boolean isInOverScroll() {
+            return mIsInOverScroll;
+        }
+
+        private float getDampedOverScroll(float y) {
+            return OverScroll.dampedScroll(y, getHeight());
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
index 3b9e7bc..65135ab 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
@@ -104,6 +104,11 @@
         setMeasuredDimension(width, height);
     }
 
+    @Override
+    public boolean hasOverlappingRendering() {
+        return false;
+    }
+
     private static int exactly(int size) {
         return MeasureSpec.makeMeasureSpec(size, MeasureSpec.EXACTLY);
     }
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..2a9a381 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
@@ -78,6 +78,7 @@
 
     @Override
     public void handleSetListening(boolean listening) {
+        if (mController == null) return;
         if (listening) {
             mController.addCallback(mCallback);
         } else {
@@ -131,21 +132,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 +271,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/qs/tiles/DndTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
index 6205e9a..2d31669 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
@@ -240,6 +240,7 @@
     public void handleSetListening(boolean listening) {
         if (mListening == listening) return;
         mListening = listening;
+        if (mController == null) return;
         if (mListening) {
             mController.addCallback(mZenCallback);
             Prefs.registerListener(mContext, mPrefListener);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java
index b3ff4e5b..12daff1 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java
@@ -98,6 +98,8 @@
     protected void handleUpdateState(BooleanState state, Object arg) {
         final Drawable mEnable = mContext.getDrawable(R.drawable.ic_qs_nfc_enabled);
         final Drawable mDisable = mContext.getDrawable(R.drawable.ic_qs_nfc_disabled);
+
+        if (getAdapter() == null) return;
         state.value = getAdapter().isEnabled();
         state.label = mContext.getString(R.string.quick_settings_nfc_label);
         state.icon = new DrawableIcon(state.value ? mEnable : mDisable);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java
index ea6e174..3597929 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java
@@ -21,6 +21,7 @@
 import android.content.Intent;
 import android.provider.Settings;
 import android.service.quicksettings.Tile;
+import android.support.annotation.StringRes;
 import android.widget.Switch;
 
 import com.android.internal.app.ColorDisplayController;
@@ -30,6 +31,7 @@
 import com.android.systemui.plugins.qs.QSTile.BooleanState;
 import com.android.systemui.qs.tileimpl.QSTileImpl;
 
+import java.time.LocalTime;
 import java.time.format.DateTimeFormatter;
 
 public class NightDisplayTile extends QSTileImpl<BooleanState>
@@ -39,7 +41,9 @@
      * Pattern for {@link java.time.format.DateTimeFormatter} used to approximate the time to the
      * nearest hour and add on the AM/PM indicator.
      */
-    private static final String APPROXIMATE_HOUR_DATE_TIME_PATTERN = "h a";
+    private static final String HOUR_MINUTE_DATE_TIME_PATTERN = "h a";
+    private static final String APPROXIMATE_HOUR_DATE_TIME_PATTERN = "h:m a";
+
 
     private ColorDisplayController mController;
     private boolean mIsListening;
@@ -110,17 +114,26 @@
 
             case ColorDisplayController.AUTO_MODE_CUSTOM:
                 // User-specified time, approximated to the nearest hour.
-                return isNightLightActivated
-                        ? mContext.getString(
-                                R.string.quick_settings_night_secondary_label_until,
-                                mController.getCustomEndTime().format(
-                                        DateTimeFormatter.ofPattern(
-                                                APPROXIMATE_HOUR_DATE_TIME_PATTERN)))
-                        : mContext.getString(
-                                R.string.quick_settings_night_secondary_label_on_at,
-                                mController.getCustomStartTime().format(
-                                        DateTimeFormatter.ofPattern(
-                                                APPROXIMATE_HOUR_DATE_TIME_PATTERN)));
+                final @StringRes int toggleTimeStringRes;
+                final LocalTime toggleTime;
+                final DateTimeFormatter toggleTimeFormat;
+
+                if (isNightLightActivated) {
+                    toggleTime = mController.getCustomEndTime();
+                    toggleTimeStringRes = R.string.quick_settings_night_secondary_label_until;
+                } else {
+                    toggleTime = mController.getCustomStartTime();
+                    toggleTimeStringRes = R.string.quick_settings_night_secondary_label_on_at;
+                }
+
+                // Choose between just showing the hour or also showing the minutes (based on the
+                // user-selected toggle time). This helps reduce how much space the label takes.
+                toggleTimeFormat = DateTimeFormatter.ofPattern(
+                        toggleTime.getMinute() == 0
+                                ? HOUR_MINUTE_DATE_TIME_PATTERN
+                                : APPROXIMATE_HOUR_DATE_TIME_PATTERN);
+
+                return mContext.getString(toggleTimeStringRes, toggleTime.format(toggleTimeFormat));
 
             default:
                 // No secondary label when auto mode is disabled.
diff --git a/packages/SystemUI/src/com/android/systemui/qs/touch/OverScroll.java b/packages/SystemUI/src/com/android/systemui/qs/touch/OverScroll.java
new file mode 100644
index 0000000..0464886
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/touch/OverScroll.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.qs.touch;
+
+/**
+ * Utility methods for overscroll damping and related effect.
+ *
+ * Copied from packages/apps/Launcher3/src/com/android/launcher3/touch/OverScroll.java
+ */
+public class OverScroll {
+
+    private static final float OVERSCROLL_DAMP_FACTOR = 0.07f;
+
+    /**
+     * This curve determines how the effect of scrolling over the limits of the page diminishes
+     * as the user pulls further and further from the bounds
+     *
+     * @param f The percentage of how much the user has overscrolled.
+     * @return A transformed percentage based on the influence curve.
+     */
+    private static float overScrollInfluenceCurve(float f) {
+        f -= 1.0f;
+        return f * f * f + 1.0f;
+    }
+
+    /**
+     * @param amount The original amount overscrolled.
+     * @param max The maximum amount that the View can overscroll.
+     * @return The dampened overscroll amount.
+     */
+    public static int dampedScroll(float amount, int max) {
+        if (Float.compare(amount, 0) == 0) return 0;
+
+        float f = amount / max;
+        f = f / (Math.abs(f)) * (overScrollInfluenceCurve(Math.abs(f)));
+
+        // Clamp this factor, f, to -1 < f < 1
+        if (Math.abs(f) >= 1) {
+            f /= Math.abs(f);
+        }
+
+        return Math.round(OVERSCROLL_DAMP_FACTOR * f * max);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/touch/SwipeDetector.java b/packages/SystemUI/src/com/android/systemui/qs/touch/SwipeDetector.java
new file mode 100644
index 0000000..2522052
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/touch/SwipeDetector.java
@@ -0,0 +1,356 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.qs.touch;
+
+import static android.view.MotionEvent.INVALID_POINTER_ID;
+
+import android.content.Context;
+import android.graphics.PointF;
+import android.support.annotation.NonNull;
+import android.support.annotation.VisibleForTesting;
+import android.util.Log;
+import android.view.MotionEvent;
+import android.view.ViewConfiguration;
+
+/**
+ * One dimensional scroll/drag/swipe gesture detector.
+ *
+ * Definition of swipe is different from android system in that this detector handles
+ * 'swipe to dismiss', 'swiping up/down a container' but also keeps scrolling state before
+ * swipe action happens
+ *
+ * Copied from packages/apps/Launcher3/src/com/android/launcher3/touch/SwipeDetector.java
+ */
+public class SwipeDetector {
+
+    private static final boolean DBG = false;
+    private static final String TAG = "SwipeDetector";
+
+    private int mScrollConditions;
+    public static final int DIRECTION_POSITIVE = 1 << 0;
+    public static final int DIRECTION_NEGATIVE = 1 << 1;
+    public static final int DIRECTION_BOTH = DIRECTION_NEGATIVE | DIRECTION_POSITIVE;
+
+    private static final float ANIMATION_DURATION = 1200;
+
+    protected int mActivePointerId = INVALID_POINTER_ID;
+
+    /**
+     * The minimum release velocity in pixels per millisecond that triggers fling..
+     */
+    public static final float RELEASE_VELOCITY_PX_MS = 1.0f;
+
+    /**
+     * The time constant used to calculate dampening in the low-pass filter of scroll velocity.
+     * Cutoff frequency is set at 10 Hz.
+     */
+    public static final float SCROLL_VELOCITY_DAMPENING_RC = 1000f / (2f * (float) Math.PI * 10);
+
+    /* Scroll state, this is set to true during dragging and animation. */
+    private ScrollState mState = ScrollState.IDLE;
+
+    enum ScrollState {
+        IDLE,
+        DRAGGING,      // onDragStart, onDrag
+        SETTLING       // onDragEnd
+    }
+
+    public static abstract class Direction {
+
+        abstract float getDisplacement(MotionEvent ev, int pointerIndex, PointF refPoint);
+
+        /**
+         * Distance in pixels a touch can wander before we think the user is scrolling.
+         */
+        abstract float getActiveTouchSlop(MotionEvent ev, int pointerIndex, PointF downPos);
+    }
+
+    public static final Direction VERTICAL = new Direction() {
+
+        @Override
+        float getDisplacement(MotionEvent ev, int pointerIndex, PointF refPoint) {
+            return ev.getY(pointerIndex) - refPoint.y;
+        }
+
+        @Override
+        float getActiveTouchSlop(MotionEvent ev, int pointerIndex, PointF downPos) {
+            return Math.abs(ev.getX(pointerIndex) - downPos.x);
+        }
+    };
+
+    public static final Direction HORIZONTAL = new Direction() {
+
+        @Override
+        float getDisplacement(MotionEvent ev, int pointerIndex, PointF refPoint) {
+            return ev.getX(pointerIndex) - refPoint.x;
+        }
+
+        @Override
+        float getActiveTouchSlop(MotionEvent ev, int pointerIndex, PointF downPos) {
+            return Math.abs(ev.getY(pointerIndex) - downPos.y);
+        }
+    };
+
+    //------------------- ScrollState transition diagram -----------------------------------
+    //
+    // IDLE ->      (mDisplacement > mTouchSlop) -> DRAGGING
+    // DRAGGING -> (MotionEvent#ACTION_UP, MotionEvent#ACTION_CANCEL) -> SETTLING
+    // SETTLING -> (MotionEvent#ACTION_DOWN) -> DRAGGING
+    // SETTLING -> (View settled) -> IDLE
+
+    private void setState(ScrollState newState) {
+        if (DBG) {
+            Log.d(TAG, "setState:" + mState + "->" + newState);
+        }
+        // onDragStart and onDragEnd is reported ONLY on state transition
+        if (newState == ScrollState.DRAGGING) {
+            initializeDragging();
+            if (mState == ScrollState.IDLE) {
+                reportDragStart(false /* recatch */);
+            } else if (mState == ScrollState.SETTLING) {
+                reportDragStart(true /* recatch */);
+            }
+        }
+        if (newState == ScrollState.SETTLING) {
+            reportDragEnd();
+        }
+
+        mState = newState;
+    }
+
+    public boolean isDraggingOrSettling() {
+        return mState == ScrollState.DRAGGING || mState == ScrollState.SETTLING;
+    }
+
+    /**
+     * There's no touch and there's no animation.
+     */
+    public boolean isIdleState() {
+        return mState == ScrollState.IDLE;
+    }
+
+    public boolean isSettlingState() {
+        return mState == ScrollState.SETTLING;
+    }
+
+    public boolean isDraggingState() {
+        return mState == ScrollState.DRAGGING;
+    }
+
+    private final PointF mDownPos = new PointF();
+    private final PointF mLastPos = new PointF();
+    private final Direction mDir;
+
+    private final float mTouchSlop;
+
+    /* Client of this gesture detector can register a callback. */
+    private final Listener mListener;
+
+    private long mCurrentMillis;
+
+    private float mVelocity;
+    private float mLastDisplacement;
+    private float mDisplacement;
+
+    private float mSubtractDisplacement;
+    private boolean mIgnoreSlopWhenSettling;
+
+    public interface Listener {
+        void onDragStart(boolean start);
+
+        boolean onDrag(float displacement, float velocity);
+
+        void onDragEnd(float velocity, boolean fling);
+    }
+
+    public SwipeDetector(@NonNull Context context, @NonNull Listener l, @NonNull Direction dir) {
+        this(ViewConfiguration.get(context).getScaledTouchSlop(), l, dir);
+    }
+
+    @VisibleForTesting
+    protected SwipeDetector(float touchSlope, @NonNull Listener l, @NonNull Direction dir) {
+        mTouchSlop = touchSlope;
+        mListener = l;
+        mDir = dir;
+    }
+
+    public void setDetectableScrollConditions(int scrollDirectionFlags, boolean ignoreSlop) {
+        mScrollConditions = scrollDirectionFlags;
+        mIgnoreSlopWhenSettling = ignoreSlop;
+    }
+
+    private boolean shouldScrollStart(MotionEvent ev, int pointerIndex) {
+        // reject cases where the angle or slop condition is not met.
+        if (Math.max(mDir.getActiveTouchSlop(ev, pointerIndex, mDownPos), mTouchSlop)
+                > Math.abs(mDisplacement)) {
+            return false;
+        }
+
+        // Check if the client is interested in scroll in current direction.
+        if (((mScrollConditions & DIRECTION_NEGATIVE) > 0 && mDisplacement > 0) ||
+                ((mScrollConditions & DIRECTION_POSITIVE) > 0 && mDisplacement < 0)) {
+            return true;
+        }
+        return false;
+    }
+
+    public boolean onTouchEvent(MotionEvent ev) {
+        switch (ev.getActionMasked()) {
+            case MotionEvent.ACTION_DOWN:
+                mActivePointerId = ev.getPointerId(0);
+                mDownPos.set(ev.getX(), ev.getY());
+                mLastPos.set(mDownPos);
+                mLastDisplacement = 0;
+                mDisplacement = 0;
+                mVelocity = 0;
+
+                if (mState == ScrollState.SETTLING && mIgnoreSlopWhenSettling) {
+                    setState(ScrollState.DRAGGING);
+                }
+                break;
+            //case MotionEvent.ACTION_POINTER_DOWN:
+            case MotionEvent.ACTION_POINTER_UP:
+                int ptrIdx = ev.getActionIndex();
+                int ptrId = ev.getPointerId(ptrIdx);
+                if (ptrId == mActivePointerId) {
+                    final int newPointerIdx = ptrIdx == 0 ? 1 : 0;
+                    mDownPos.set(
+                            ev.getX(newPointerIdx) - (mLastPos.x - mDownPos.x),
+                            ev.getY(newPointerIdx) - (mLastPos.y - mDownPos.y));
+                    mLastPos.set(ev.getX(newPointerIdx), ev.getY(newPointerIdx));
+                    mActivePointerId = ev.getPointerId(newPointerIdx);
+                }
+                break;
+            case MotionEvent.ACTION_MOVE:
+                int pointerIndex = ev.findPointerIndex(mActivePointerId);
+                if (pointerIndex == INVALID_POINTER_ID) {
+                    break;
+                }
+                mDisplacement = mDir.getDisplacement(ev, pointerIndex, mDownPos);
+                computeVelocity(mDir.getDisplacement(ev, pointerIndex, mLastPos),
+                        ev.getEventTime());
+
+                // handle state and listener calls.
+                if (mState != ScrollState.DRAGGING && shouldScrollStart(ev, pointerIndex)) {
+                    setState(ScrollState.DRAGGING);
+                }
+                if (mState == ScrollState.DRAGGING) {
+                    reportDragging();
+                }
+                mLastPos.set(ev.getX(pointerIndex), ev.getY(pointerIndex));
+                break;
+            case MotionEvent.ACTION_CANCEL:
+            case MotionEvent.ACTION_UP:
+                // These are synthetic events and there is no need to update internal values.
+                if (mState == ScrollState.DRAGGING) {
+                    setState(ScrollState.SETTLING);
+                }
+                break;
+            default:
+                break;
+        }
+        return true;
+    }
+
+    public void finishedScrolling() {
+        setState(ScrollState.IDLE);
+    }
+
+    private boolean reportDragStart(boolean recatch) {
+        mListener.onDragStart(!recatch);
+        if (DBG) {
+            Log.d(TAG, "onDragStart recatch:" + recatch);
+        }
+        return true;
+    }
+
+    private void initializeDragging() {
+        if (mState == ScrollState.SETTLING && mIgnoreSlopWhenSettling) {
+            mSubtractDisplacement = 0;
+        }
+        if (mDisplacement > 0) {
+            mSubtractDisplacement = mTouchSlop;
+        } else {
+            mSubtractDisplacement = -mTouchSlop;
+        }
+    }
+
+    private boolean reportDragging() {
+        if (mDisplacement != mLastDisplacement) {
+            if (DBG) {
+                Log.d(TAG, String.format("onDrag disp=%.1f, velocity=%.1f",
+                        mDisplacement, mVelocity));
+            }
+
+            mLastDisplacement = mDisplacement;
+            return mListener.onDrag(mDisplacement - mSubtractDisplacement, mVelocity);
+        }
+        return true;
+    }
+
+    private void reportDragEnd() {
+        if (DBG) {
+            Log.d(TAG, String.format("onScrollEnd disp=%.1f, velocity=%.1f",
+                    mDisplacement, mVelocity));
+        }
+        mListener.onDragEnd(mVelocity, Math.abs(mVelocity) > RELEASE_VELOCITY_PX_MS);
+
+    }
+
+    /**
+     * Computes the damped velocity.
+     */
+    public float computeVelocity(float delta, long currentMillis) {
+        long previousMillis = mCurrentMillis;
+        mCurrentMillis = currentMillis;
+
+        float deltaTimeMillis = mCurrentMillis - previousMillis;
+        float velocity = (deltaTimeMillis > 0) ? (delta / deltaTimeMillis) : 0;
+        if (Math.abs(mVelocity) < 0.001f) {
+            mVelocity = velocity;
+        } else {
+            float alpha = computeDampeningFactor(deltaTimeMillis);
+            mVelocity = interpolate(mVelocity, velocity, alpha);
+        }
+        return mVelocity;
+    }
+
+    /**
+     * Returns a time-dependent dampening factor using delta time.
+     */
+    private static float computeDampeningFactor(float deltaTime) {
+        return deltaTime / (SCROLL_VELOCITY_DAMPENING_RC + deltaTime);
+    }
+
+    /**
+     * Returns the linear interpolation between two values
+     */
+    private static float interpolate(float from, float to, float alpha) {
+        return (1.0f - alpha) * from + alpha * to;
+    }
+
+    public static long calculateDuration(float velocity, float progressNeeded) {
+        // TODO: make these values constants after tuning.
+        float velocityDivisor = Math.max(2f, Math.abs(0.5f * velocity));
+        float travelDistance = Math.max(0.2f, progressNeeded);
+        long duration = (long) Math.max(100, ANIMATION_DURATION / velocityDivisor * travelDistance);
+        if (DBG) {
+            Log.d(TAG, String.format("calculateDuration=%d, v=%f, d=%f", duration, velocity, progressNeeded));
+        }
+        return duration;
+    }
+}
+
diff --git a/packages/SystemUI/src/com/android/systemui/recents/SwipeUpOnboarding.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java
similarity index 84%
rename from packages/SystemUI/src/com/android/systemui/recents/SwipeUpOnboarding.java
rename to packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java
index b2472bf..89cc509 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/SwipeUpOnboarding.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java
@@ -16,13 +16,11 @@
 
 package com.android.systemui.recents;
 
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
 
 import android.annotation.TargetApi;
 import android.app.ActivityManager;
-import android.content.ComponentName;
 import android.content.Context;
 import android.content.res.Configuration;
 import android.content.res.Resources;
@@ -31,6 +29,10 @@
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.RippleDrawable;
 import android.os.Build;
+import android.os.SystemProperties;
+import android.os.UserManager;
+import android.text.TextUtils;
+import android.util.Log;
 import android.view.Gravity;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -41,6 +43,7 @@
 import android.widget.ImageView;
 import android.widget.TextView;
 
+import com.android.systemui.OverviewProxyService;
 import com.android.systemui.Prefs;
 import com.android.systemui.R;
 import com.android.systemui.recents.misc.SysUiTaskStackChangeListener;
@@ -50,9 +53,9 @@
  * Shows onboarding for the new recents interaction in P (codenamed quickstep).
  */
 @TargetApi(Build.VERSION_CODES.P)
-public class SwipeUpOnboarding {
+public class RecentsOnboarding {
 
-    private static final String TAG = "SwipeUpOnboarding";
+    private static final String TAG = "RecentsOnboarding";
     private static final boolean RESET_PREFS_FOR_DEBUG = false;
     private static final long SHOW_DELAY_MS = 500;
     private static final long SHOW_HIDE_DURATION_MS = 300;
@@ -61,6 +64,7 @@
 
     private final Context mContext;
     private final WindowManager mWindowManager;
+    private final OverviewProxyService mOverviewProxyService;
     private final View mLayout;
     private final TextView mTextView;
     private final ImageView mDismissView;
@@ -113,11 +117,12 @@
         }
     };
 
-    public SwipeUpOnboarding(Context context) {
+    public RecentsOnboarding(Context context, OverviewProxyService overviewProxyService) {
         mContext = context;
+        mOverviewProxyService = overviewProxyService;
         final Resources res = context.getResources();
         mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
-        mLayout = LayoutInflater.from(mContext).inflate(R.layout.recents_swipe_up_onboarding, null);
+        mLayout = LayoutInflater.from(mContext).inflate(R.layout.recents_onboarding, null);
         mTextView = mLayout.findViewById(R.id.onboarding_text);
         mDismissView = mLayout.findViewById(R.id.dismiss);
         mDarkBackgroundColor = res.getColor(android.R.color.background_dark);
@@ -135,25 +140,25 @@
         mDismissView.setOnClickListener(v -> hide(true));
 
         if (RESET_PREFS_FOR_DEBUG) {
-            Prefs.putBoolean(mContext, Prefs.Key.HAS_SWIPED_UP_FOR_RECENTS, false);
+            Prefs.putBoolean(mContext, Prefs.Key.HAS_SEEN_RECENTS_ONBOARDING, false);
             Prefs.putInt(mContext, Prefs.Key.NUM_APPS_LAUNCHED, 0);
         }
     }
 
     public void onConnectedToLauncher() {
-        boolean alreadyLearnedSwipeUpForRecents = Prefs.getBoolean(mContext,
-                Prefs.Key.HAS_SWIPED_UP_FOR_RECENTS, false);
-        if (!mTaskListenerRegistered && !alreadyLearnedSwipeUpForRecents) {
+        boolean alreadySeenRecentsOnboarding = Prefs.getBoolean(mContext,
+                Prefs.Key.HAS_SEEN_RECENTS_ONBOARDING, false);
+        if (!mTaskListenerRegistered && !alreadySeenRecentsOnboarding) {
             ActivityManagerWrapper.getInstance().registerTaskStackListener(mTaskListener);
             mTaskListenerRegistered = true;
         }
     }
 
     public void onRecentsAnimationStarted() {
-        boolean alreadyLearnedSwipeUpForRecents = Prefs.getBoolean(mContext,
-                Prefs.Key.HAS_SWIPED_UP_FOR_RECENTS, false);
-        if (!alreadyLearnedSwipeUpForRecents) {
-            Prefs.putBoolean(mContext, Prefs.Key.HAS_SWIPED_UP_FOR_RECENTS, true);
+        boolean alreadySeenRecentsOnboarding = Prefs.getBoolean(mContext,
+                Prefs.Key.HAS_SEEN_RECENTS_ONBOARDING, false);
+        if (!alreadySeenRecentsOnboarding) {
+            Prefs.putBoolean(mContext, Prefs.Key.HAS_SEEN_RECENTS_ONBOARDING, true);
             onDisconnectedFromLauncher();
         }
     }
@@ -173,6 +178,15 @@
     }
 
     public void show() {
+        if (!shouldShow()) {
+            return;
+        }
+        CharSequence onboardingText = mOverviewProxyService.getOnboardingText();
+        if (TextUtils.isEmpty(onboardingText)) {
+            Log.w(TAG, "Unable to get onboarding text");
+            return;
+        }
+        mTextView.setText(onboardingText);
         // Only show in portrait.
         int orientation = mContext.getResources().getConfiguration().orientation;
         if (!mLayoutAttachedToWindow && orientation == Configuration.ORIENTATION_PORTRAIT) {
@@ -196,6 +210,14 @@
         }
     }
 
+    /**
+     * @return True unless setprop has been set to false, or we're in demo mode.
+     */
+    private boolean shouldShow() {
+        return SystemProperties.getBoolean("persist.quickstep.onboarding.enabled",
+                !(mContext.getSystemService(UserManager.class)).isDemoUser());
+    }
+
     public void hide(boolean animate) {
         if (mLayoutAttachedToWindow) {
             if (animate) {
@@ -208,6 +230,7 @@
                         .withEndAction(() -> mWindowManager.removeView(mLayout))
                         .start();
             } else {
+                mLayout.animate().cancel();
                 mWindowManager.removeView(mLayout);
             }
         }
@@ -239,7 +262,7 @@
                 flags,
                 PixelFormat.TRANSLUCENT);
         lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
-        lp.setTitle("SwipeUpOnboarding");
+        lp.setTitle("RecentsOnboarding");
         lp.gravity = Gravity.BOTTOM;
         return lp;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java b/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
index 57f7818..3dd6e35 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
@@ -36,6 +36,7 @@
 import android.view.animation.DecelerateInterpolator;
 import android.widget.Button;
 import android.widget.FrameLayout;
+import android.widget.ImageView;
 import android.widget.LinearLayout;
 import android.widget.TextView;
 
@@ -255,6 +256,11 @@
                         : R.string.screen_pinning_description_recents_invisible;
             }
 
+            ((ImageView) mLayout.findViewById(R.id.screen_pinning_back_icon))
+                    .setImageDrawable(navigationBarView.getBackDrawable(mContext));
+            ((ImageView) mLayout.findViewById(R.id.screen_pinning_home_icon))
+                    .setImageDrawable(navigationBarView.getHomeDrawable(mContext));
+
             ((TextView) mLayout.findViewById(R.id.screen_pinning_description))
                     .setText(descriptionStringResId);
             final int backBgVisibility = touchExplorationEnabled ? View.INVISIBLE : View.VISIBLE;
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/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
index eb5619b..0876507 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
@@ -308,6 +308,10 @@
         }
     }
 
+    public void setRippleAllowed(boolean allowed) {
+        mBackgroundNormal.setPressedAllowed(allowed);
+    }
+
     private boolean handleTouchEventDimmed(MotionEvent event) {
         if (mNeedsDimming && !mDimmed) {
             // We're actually dimmed, but our content isn't dimmable, let's ensure we have a ripple
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index 11bdf6b3..fa177f2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -156,7 +156,7 @@
         default void handleShowGlobalActionsMenu() { }
         default void handleShowShutdownUi(boolean isReboot, String reason) { }
 
-        default void showChargingAnimation(int batteryLevel) {  }
+        default void showWirelessChargingAnimation(int batteryLevel) {  }
 
         default void onRotationProposal(int rotation, boolean isValid) { }
 
@@ -497,7 +497,7 @@
     }
 
     @Override
-    public void showChargingAnimation(int batteryLevel) {
+    public void showWirelessChargingAnimation(int batteryLevel) {
         mHandler.removeMessages(MSG_SHOW_CHARGING_ANIMATION);
         mHandler.obtainMessage(MSG_SHOW_CHARGING_ANIMATION, batteryLevel, 0)
                 .sendToTarget();
@@ -784,7 +784,7 @@
                     break;
                 case MSG_SHOW_CHARGING_ANIMATION:
                     for (int i = 0; i < mCallbacks.size(); i++) {
-                        mCallbacks.get(i).showChargingAnimation(msg.arg1);
+                        mCallbacks.get(i).showWirelessChargingAnimation(msg.arg1);
                     }
                     break;
                 case MSG_SHOW_PINNING_TOAST_ENTER_EXIT:
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index b3f68d3..2723df7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -370,14 +370,6 @@
         mNotificationInflater.inflateNotificationViews();
     }
 
-    @Override
-    public void setPressed(boolean pressed) {
-        if (isOnKeyguard() || mEntry.notification.getNotification().contentIntent == null) {
-            // We're dropping the ripple if we have a collapse / launch animation
-            super.setPressed(pressed);
-        }
-    }
-
     public void onNotificationUpdated() {
         for (NotificationContentView l : mLayouts) {
             l.onNotificationUpdated(mEntry);
@@ -407,6 +399,7 @@
 
         showBlockingHelper(mEntry.userSentiment ==
                 NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE);
+        updateRippleAllowed();
     }
 
     @VisibleForTesting
@@ -1805,6 +1798,13 @@
                 mAboveShelfChangedListener.onAboveShelfStateChanged(!wasAboveShelf);
             }
         }
+        updateRippleAllowed();
+    }
+
+    private void updateRippleAllowed() {
+        boolean allowed = isOnKeyguard()
+                || mEntry.notification.getNotification().contentIntent == null;
+        setRippleAllowed(allowed);
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index b7a1500..22e8909 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -300,34 +300,10 @@
                 } else if (mPowerPluggedIn) {
                     String indication = computePowerIndication();
                     if (animate) {
-                        int yTranslation = mContext.getResources().getInteger(
-                                R.integer.wired_charging_aod_text_animation_distance);
-                        int animateUpDuration = mContext.getResources().getInteger(
-                                R.integer.wired_charging_aod_text_animation_duration_up);
-                        int animateDownDuration = mContext.getResources().getInteger(
-                                R.integer.wired_charging_aod_text_animation_duration_down);
-                        mTextView.animate()
-                                .translationYBy(yTranslation)
-                                .setInterpolator(Interpolators.LINEAR)
-                                .setDuration(animateUpDuration)
-                                .setListener(new AnimatorListenerAdapter() {
-                                    @Override
-                                    public void onAnimationStart(Animator animation) {
-                                        mTextView.switchIndication(indication);
-                                    }
-                                    @Override
-                                    public void onAnimationEnd(Animator animation) {
-                                        mTextView.animate()
-                                                .setDuration(animateDownDuration)
-                                                .setInterpolator(Interpolators.BOUNCE)
-                                                .translationYBy(-1 * yTranslation)
-                                                .setListener(null);
-                                    }
-                                });
+                        animateText(mTextView, indication);
                     } else {
                         mTextView.switchIndication(indication);
                     }
-
                 } else {
                     String percentage = NumberFormat.getPercentInstance()
                             .format(mBatteryLevel / 100f);
@@ -355,8 +331,12 @@
                 if (DEBUG_CHARGING_SPEED) {
                     indication += ",  " + (mChargingWattage / 1000) + " mW";
                 }
-                mTextView.switchIndication(indication);
                 mTextView.setTextColor(mInitialTextColor);
+                if (animate) {
+                    animateText(mTextView, indication);
+                } else {
+                    mTextView.switchIndication(indication);
+                }
             } else if (!TextUtils.isEmpty(trustManagedIndication)
                     && updateMonitor.getUserTrustIsManaged(userId)
                     && !updateMonitor.getUserHasTrust(userId)) {
@@ -369,6 +349,34 @@
         }
     }
 
+    // animates textView - textView moves up and bounces down
+    private void animateText(KeyguardIndicationTextView textView, String indication) {
+        int yTranslation = mContext.getResources().getInteger(
+                R.integer.wired_charging_keyguard_text_animation_distance);
+        int animateUpDuration = mContext.getResources().getInteger(
+                R.integer.wired_charging_keyguard_text_animation_duration_up);
+        int animateDownDuration = mContext.getResources().getInteger(
+                R.integer.wired_charging_keyguard_text_animation_duration_down);
+        textView.animate()
+                .translationYBy(yTranslation)
+                .setInterpolator(Interpolators.LINEAR)
+                .setDuration(animateUpDuration)
+                .setListener(new AnimatorListenerAdapter() {
+                    @Override
+                    public void onAnimationStart(Animator animation) {
+                        textView.switchIndication(indication);
+                    }
+                    @Override
+                    public void onAnimationEnd(Animator animation) {
+                        textView.animate()
+                                .setDuration(animateDownDuration)
+                                .setInterpolator(Interpolators.BOUNCE)
+                                .translationYBy(-1 * yTranslation)
+                                .setListener(null);
+                    }
+                });
+    }
+
     private String computePowerIndication() {
         if (mPowerCharged) {
             return mContext.getResources().getString(R.string.keyguard_charged);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationBackgroundView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationBackgroundView.java
index d6beb7f..0ff4dde 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationBackgroundView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationBackgroundView.java
@@ -28,6 +28,7 @@
 import android.util.AttributeSet;
 import android.view.View;
 
+import com.android.internal.util.ArrayUtils;
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.notification.ActivityLaunchAnimator;
@@ -50,6 +51,7 @@
     private boolean mExpandAnimationRunning;
     private float mActualWidth;
     private int mDrawableAlpha = 255;
+    private boolean mIsPressedAllowed;
 
     public NotificationBackgroundView(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -94,13 +96,7 @@
 
     @Override
     protected void drawableStateChanged() {
-        drawableStateChanged(mBackground);
-    }
-
-    private void drawableStateChanged(Drawable d) {
-        if (d != null && d.isStateful()) {
-            d.setState(getDrawableState());
-        }
+        setState(getDrawableState());
     }
 
     @Override
@@ -177,7 +173,13 @@
     }
 
     public void setState(int[] drawableState) {
-        mBackground.setState(drawableState);
+        if (mBackground != null && mBackground.isStateful()) {
+            if (!mIsPressedAllowed) {
+                drawableState = ArrayUtils.removeInt(drawableState,
+                        com.android.internal.R.attr.state_pressed);
+            }
+            mBackground.setState(drawableState);
+        }
     }
 
     public void setRippleColor(int color) {
@@ -249,10 +251,17 @@
                     (GradientDrawable) ((LayerDrawable) mBackground).getDrawable(0);
             gradientDrawable.setXfermode(
                     running ? new PorterDuffXfermode(PorterDuff.Mode.SRC) : null);
+            // Speed optimization: disable AA if transfer mode is not SRC_OVER. AA is not easy to
+            // spot during animation anyways.
+            gradientDrawable.setAntiAlias(!running);
         }
         if (!mExpandAnimationRunning) {
             setDrawableAlpha(mDrawableAlpha);
         }
         invalidate();
     }
+
+    public void setPressedAllowed(boolean allowed) {
+        mIsPressedAllowed = allowed;
+    }
 }
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/NotificationGutsManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGutsManager.java
index 1aaa3b2..f730601 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGutsManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGutsManager.java
@@ -24,6 +24,7 @@
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.content.res.Resources;
+import android.net.Uri;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.UserHandle;
@@ -131,12 +132,13 @@
     }
 
     /**
-     * Sends an intent to open the notification settings for a particular package and optional
+     * Sends an intent to open the app settings for a particular package and optional
      * channel.
      */
     private void startAppNotificationSettingsActivity(String packageName, final int appUid,
             final NotificationChannel channel, ExpandableNotificationRow row) {
-        final Intent intent = new Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS);
+        final Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
+        intent.setData(Uri.fromParts("package", packageName, null));
         intent.putExtra(Settings.EXTRA_APP_PACKAGE, packageName);
         intent.putExtra(Settings.EXTRA_APP_UID, appUid);
         if (channel != 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/NotificationRemoteInputManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
index f25379a..3c480d8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
@@ -299,6 +299,11 @@
                         }
                     }, REMOTE_INPUT_KEPT_ENTRY_AUTO_CANCEL_DELAY);
                 }
+                try {
+                    mBarService.onNotificationDirectReplied(entry.notification.getKey());
+                } catch (RemoteException e) {
+                    // Nothing to do, system going down
+                }
             }
         });
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
index 46b218f..13b13fd 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/CarFacetButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarFacetButton.java
new file mode 100644
index 0000000..53101a5
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarFacetButton.java
@@ -0,0 +1,161 @@
+package com.android.systemui.statusbar.car;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.TypedArray;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+
+import com.android.keyguard.AlphaOptimizedImageButton;
+import com.android.systemui.R;
+
+/**
+ * CarFacetButton is a ui component designed to be used as a shortcut for an app of a defined
+ * category. It can also render a indicator impling that there are more options of apps to launch
+ * using this component. This is done with a "More icon" currently an arrow as defined in the layout
+ * file. The class is to serve as an example.
+ * Usage example: A button that allows a user to select a music app and indicate that there are
+ * other music apps installed.
+ */
+public class CarFacetButton extends LinearLayout {
+    private static final float SELECTED_ALPHA = 1f;
+    private static final float UNSELECTED_ALPHA = 0.7f;
+
+    private static final String FACET_FILTER_DELIMITER = ";";
+    /**
+     * Extra information to be sent to a helper to make the decision of what app to launch when
+     * clicked.
+     */
+    private static final String EXTRA_FACET_CATEGORIES = "categories";
+    private static final String EXTRA_FACET_PACKAGES = "packages";
+    private static final String EXTRA_FACET_ID = "filter_id";
+    private static final String EXTRA_FACET_LAUNCH_PICKER = "launch_picker";
+
+    private Context mContext;
+    private AlphaOptimizedImageButton mIcon;
+    private AlphaOptimizedImageButton mMoreIcon;
+    private boolean mSelected = false;
+    /** App categories that are to be used with this widget */
+    private String[] mFacetCategories;
+    /** App packages that are allowed to be used with this widget */
+    private String[] mFacetPackages;
+
+
+    public CarFacetButton(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        mContext = context;
+        View.inflate(context, R.layout.car_facet_button, this);
+
+        // extract custom attributes
+        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CarFacetButton);
+        setupIntents(typedArray);
+        setupIcons(typedArray);
+    }
+
+    /**
+     * Reads the custom attributes to setup click handlers for this component.
+     */
+    private void setupIntents(TypedArray typedArray) {
+        String intentString = typedArray.getString(R.styleable.CarFacetButton_intent);
+        String longPressIntentString = typedArray.getString(R.styleable.CarFacetButton_longIntent);
+        String categoryString = typedArray.getString(R.styleable.CarFacetButton_categories);
+        String packageString = typedArray.getString(R.styleable.CarFacetButton_packages);
+        try {
+            final Intent intent = Intent.parseUri(intentString, Intent.URI_INTENT_SCHEME);
+            intent.putExtra(EXTRA_FACET_ID, Integer.toString(getId()));
+
+            if (packageString != null) {
+                mFacetPackages = packageString.split(FACET_FILTER_DELIMITER);
+                intent.putExtra(EXTRA_FACET_PACKAGES, mFacetPackages);
+            }
+            if (categoryString != null) {
+                mFacetCategories = categoryString.split(FACET_FILTER_DELIMITER);
+                intent.putExtra(EXTRA_FACET_CATEGORIES, mFacetCategories);
+            }
+
+            setOnClickListener(v -> {
+                intent.putExtra(EXTRA_FACET_LAUNCH_PICKER, mSelected);
+                mContext.startActivity(intent);
+            });
+
+            if (longPressIntentString != null) {
+                final Intent longPressIntent = Intent.parseUri(longPressIntentString,
+                        Intent.URI_INTENT_SCHEME);
+                setOnLongClickListener(v -> {
+                    mContext.startActivity(longPressIntent);
+                    return true;
+                });
+            }
+        } catch (Exception e) {
+            throw new RuntimeException("Failed to attach intent", e);
+        }
+    }
+
+
+    private void setupIcons(TypedArray styledAttributes) {
+        mIcon = findViewById(R.id.car_nav_button_icon);
+        mIcon.setScaleType(ImageView.ScaleType.CENTER);
+        mIcon.setClickable(false);
+        mIcon.setAlpha(UNSELECTED_ALPHA);
+        int iconResourceId = styledAttributes.getResourceId(R.styleable.CarFacetButton_icon, 0);
+        if (iconResourceId == 0)  {
+            throw new RuntimeException("specified icon resource was not found and is required");
+        }
+        mIcon.setImageResource(iconResourceId);
+
+        mMoreIcon = findViewById(R.id.car_nav_button_more_icon);
+        mMoreIcon.setClickable(false);
+        mMoreIcon.setImageDrawable(getContext().getDrawable(R.drawable.car_ic_arrow));
+        mMoreIcon.setAlpha(UNSELECTED_ALPHA);
+        mMoreIcon.setVisibility(GONE);
+    }
+
+    /**
+     * @return The app categories the component represents
+     */
+    public String[] getCategories() {
+        if (mFacetCategories == null) {
+            return new String[0];
+        }
+        return mFacetCategories;
+    }
+
+    /**
+     * @return The valid packages that should be considered.
+     */
+    public String[] getFacetPackages() {
+        if (mFacetPackages == null) {
+            return new String[0];
+        }
+        return mFacetPackages;
+    }
+
+    /**
+     * Updates the alpha of the icons to "selected" and shows the "More icon"
+     * @param selected true if the view must be selected, false otherwise
+     */
+    public void setSelected(boolean selected) {
+        super.setSelected(selected);
+        setSelected(selected, selected);
+    }
+
+    /**
+     * Updates the visual state to let the user know if it's been selected.
+     * @param selected true if should update the alpha of the icon to selected, false otherwise
+     * @param showMoreIcon true if the "more icon" should be shown, false otherwise
+     */
+    public void setSelected(boolean selected, boolean showMoreIcon) {
+        mSelected = selected;
+        if (selected) {
+            mMoreIcon.setVisibility(showMoreIcon ? VISIBLE : GONE);
+            mMoreIcon.setAlpha(SELECTED_ALPHA);
+            mIcon.setAlpha(SELECTED_ALPHA);
+        } else {
+            mMoreIcon.setVisibility(GONE);
+            mIcon.setAlpha(UNSELECTED_ALPHA);
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarFacetButtonController.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarFacetButtonController.java
new file mode 100644
index 0000000..e8c9a5e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarFacetButtonController.java
@@ -0,0 +1,114 @@
+package com.android.systemui.statusbar.car;
+
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.view.View;
+import android.view.ViewGroup;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * CarFacetButtons placed on the nav bar are designed to have visual indication that the active
+ * application on screen is associated with it. This is basically a similar concept to a radio
+ * button group.
+ */
+public class CarFacetButtonController {
+
+    protected HashMap<String, CarFacetButton> mButtonsByCategory = new HashMap<>();
+    protected HashMap<String, CarFacetButton> mButtonsByPackage = new HashMap<>();
+    protected CarFacetButton mSelectedFacetButton;
+    protected Context mContext;
+
+    public CarFacetButtonController(Context context) {
+        mContext = context;
+    }
+
+    /**
+     * Goes through the supplied CarNavigationBarView and keeps track of all the CarFacetButtons
+     * such that it can select and unselect them based on running task chages
+     * @param bar that may contain CarFacetButtons
+     */
+    public void addCarNavigationBar(CarNavigationBarView bar) {
+        findFacets(bar);
+    }
+
+    private void findFacets(ViewGroup root) {
+        final int childCount = root.getChildCount();
+
+        for (int i = 0; i < childCount; ++i) {
+            final View v = root.getChildAt(i);
+            if (v instanceof CarFacetButton) {
+                CarFacetButton facetButton = (CarFacetButton) v;
+                String[] categories = facetButton.getCategories();
+                for (int j = 0; j < categories.length; j++) {
+                    String category = categories[j];
+                    mButtonsByCategory.put(category, facetButton);
+                }
+
+                String[] facetPackages = facetButton.getFacetPackages();
+                for (int j = 0; j < facetPackages.length; j++) {
+                    String facetPackage = facetPackages[j];
+                    mButtonsByPackage.put(facetPackage, facetButton);
+                }
+            } else if (v instanceof ViewGroup) {
+                findFacets((ViewGroup) v);
+            }
+        }
+    }
+
+
+    /**
+     * This will unselect the currently selected CarFacetButton and determine which one should be
+     * selected next. It does this by reading the properties on the CarFacetButton and seeing if
+     * they are a match with the supplied taskino.
+     * @param taskInfo of the currently running application
+     */
+    public void taskChanged(ActivityManager.RunningTaskInfo taskInfo) {
+        if (taskInfo == null || taskInfo.baseActivity == null) {
+            return;
+        }
+        String packageName = taskInfo.baseActivity.getPackageName();
+
+        // If the package name belongs to a filter, then highlight appropriate button in
+        // the navigation bar.
+        if (mSelectedFacetButton != null) {
+            mSelectedFacetButton.setSelected(false);
+        }
+        CarFacetButton facetButton = mButtonsByPackage.get(packageName);
+        if (facetButton != null) {
+            facetButton.setSelected(true);
+            mSelectedFacetButton = facetButton;
+        } else {
+            String category = getPackageCategory(packageName);
+            if (category != null) {
+                facetButton = mButtonsByCategory.get(category);
+                facetButton.setSelected(true);
+                mSelectedFacetButton = facetButton;
+            }
+        }
+    }
+
+    protected String getPackageCategory(String packageName) {
+        PackageManager pm = mContext.getPackageManager();
+        Set<String> supportedCategories = mButtonsByCategory.keySet();
+        for (String category : supportedCategories) {
+            Intent intent = new Intent();
+            intent.setPackage(packageName);
+            intent.setAction(Intent.ACTION_MAIN);
+            intent.addCategory(category);
+            List<ResolveInfo> list = pm.queryIntentActivities(intent, 0);
+            if (list.size() > 0) {
+                // Cache this package name into facetPackageMap, so we won't have to query
+                // all categories next time this package name shows up.
+                mButtonsByPackage.put(packageName, mButtonsByCategory.get(category));
+                return category;
+            }
+        }
+        return null;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarController.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarController.java
deleted file mode 100644
index 64c52ed..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarController.java
+++ /dev/null
@@ -1,407 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.systemui.statusbar.car;
-
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
-import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
-import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY;
-import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
-
-import android.app.ActivityManager;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.content.res.Resources;
-import android.content.res.TypedArray;
-import android.graphics.drawable.Drawable;
-import android.support.v4.util.SimpleArrayMap;
-import android.text.TextUtils;
-import android.util.Log;
-import android.util.SparseBooleanArray;
-import android.view.View;
-import android.widget.LinearLayout;
-import com.android.systemui.R;
-
-import java.net.URISyntaxException;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * A controller to populate data for CarNavigationBarView and handle user interactions.
- *
- * <p>Each button inside the navigation bar is defined by data in arrays_car.xml. OEMs can
- * customize the navigation buttons by updating arrays_car.xml appropriately in an overlay.
- */
-class CarNavigationBarController {
-    private static final String TAG = "CarNavBarController";
-
-    private static final String EXTRA_FACET_CATEGORIES = "categories";
-    private static final String EXTRA_FACET_PACKAGES = "packages";
-    private static final String EXTRA_FACET_ID = "filter_id";
-    private static final String EXTRA_FACET_LAUNCH_PICKER = "launch_picker";
-
-    /**
-     * Each facet of the navigation bar maps to a set of package names or categories defined in
-     * arrays_car.xml. Package names for a given facet are delimited by ";".
-     */
-    private static final String FACET_FILTER_DELIMITER = ";";
-
-    private final Context mContext;
-    private final CarNavigationBarView mNavBar;
-    private final CarStatusBar mStatusBar;
-
-    /**
-     * Set of categories each facet will filter on.
-     */
-    private final List<String[]> mFacetCategories = new ArrayList<>();
-
-    /**
-     * Set of package names each facet will filter on.
-     */
-    private final List<String[]> mFacetPackages = new ArrayList<>();
-
-    private final SimpleArrayMap<String, Integer> mFacetCategoryMap = new SimpleArrayMap<>();
-    private final SimpleArrayMap<String, Integer> mFacetPackageMap = new SimpleArrayMap<>();
-
-    private final List<CarNavigationButton> mNavButtons = new ArrayList<>();
-
-    private final SparseBooleanArray mFacetHasMultipleAppsCache = new SparseBooleanArray();
-
-    private int mCurrentFacetIndex;
-    private Intent mPersistentTaskIntent;
-
-    public CarNavigationBarController(Context context, CarNavigationBarView navBar,
-            CarStatusBar activityStarter) {
-        mContext = context;
-        mNavBar = navBar;
-        mStatusBar = activityStarter;
-        bind();
-
-        if (context.getResources().getBoolean(R.bool.config_enablePersistentDockedActivity)) {
-            setupPersistentDockedTask();
-        }
-    }
-
-    private void setupPersistentDockedTask() {
-        try {
-            mPersistentTaskIntent = Intent.parseUri(
-                    mContext.getString(R.string.config_persistentDockedActivityIntentUri),
-                    Intent.URI_INTENT_SCHEME);
-        } catch (URISyntaxException e) {
-            Log.e(TAG, "Malformed persistent task intent.");
-        }
-    }
-
-    public void taskChanged(String packageName, ActivityManager.RunningTaskInfo taskInfo) {
-        // If the package name belongs to a filter, then highlight appropriate button in
-        // the navigation bar.
-        if (mFacetPackageMap.containsKey(packageName)) {
-            setCurrentFacet(mFacetPackageMap.get(packageName));
-        }
-
-        // Check if the package matches any of the categories for the facets
-        String category = getPackageCategory(packageName);
-        if (category != null) {
-            setCurrentFacet(mFacetCategoryMap.get(category));
-        }
-
-        // Set up the persistent docked task if needed.
-        boolean isHomeTask =
-                taskInfo.configuration.windowConfiguration.getActivityType() == ACTIVITY_TYPE_HOME;
-        if (mPersistentTaskIntent != null && !mStatusBar.hasDockedTask() && !isHomeTask) {
-            mStatusBar.startActivityOnStack(mPersistentTaskIntent,
-                    WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_UNDEFINED);
-        }
-    }
-
-    public void onPackageChange(String packageName) {
-        if (mFacetPackageMap.containsKey(packageName)) {
-            int index = mFacetPackageMap.get(packageName);
-            mFacetHasMultipleAppsCache.put(index, facetHasMultiplePackages(index));
-            // No need to check categories because we've already refreshed the cache.
-            return;
-        }
-
-        String category = getPackageCategory(packageName);
-        if (mFacetCategoryMap.containsKey(category)) {
-            int index = mFacetCategoryMap.get(category);
-            mFacetHasMultipleAppsCache.put(index, facetHasMultiplePackages(index));
-        }
-    }
-
-    /**
-     * Iterates through the items in arrays_car.xml and sets up the facet bar buttons to
-     * perform the task in that configuration file when clicked or long-pressed.
-     */
-    private void bind() {
-        Resources res = mContext.getResources();
-
-        TypedArray icons = res.obtainTypedArray(R.array.car_facet_icons);
-        TypedArray intents = res.obtainTypedArray(R.array.car_facet_intent_uris);
-        TypedArray longPressIntents = res.obtainTypedArray(R.array.car_facet_longpress_intent_uris);
-        TypedArray facetPackageNames = res.obtainTypedArray(R.array.car_facet_package_filters);
-        TypedArray facetCategories = res.obtainTypedArray(R.array.car_facet_category_filters);
-
-        try {
-            if (icons.length() != intents.length()
-                    || icons.length() != longPressIntents.length()
-                    || icons.length() != facetPackageNames.length()
-                    || icons.length() != facetCategories.length()) {
-                throw new RuntimeException("car_facet array lengths do not match");
-            }
-
-            for (int i = 0, size = icons.length(); i < size; i++) {
-                Drawable icon = icons.getDrawable(i);
-                CarNavigationButton button = createNavButton(icon);
-                initClickListeners(button, i, intents.getString(i), longPressIntents.getString(i));
-
-                mNavButtons.add(button);
-                mNavBar.addButton(button, createNavButton(icon) /* lightsOutButton */);
-
-                initFacetFilterMaps(i, facetPackageNames.getString(i).split(FACET_FILTER_DELIMITER),
-                        facetCategories.getString(i).split(FACET_FILTER_DELIMITER));
-                mFacetHasMultipleAppsCache.put(i, facetHasMultiplePackages(i));
-            }
-        } finally {
-            // Clean up all the TypedArrays.
-            icons.recycle();
-            intents.recycle();
-            longPressIntents.recycle();
-            facetPackageNames.recycle();
-            facetCategories.recycle();
-        }
-    }
-
-    /**
-     * Recreates each of the buttons on a density or font scale change. This manual process is
-     * necessary since this class is not part of an activity that automatically gets recreated.
-     */
-    public void onDensityOrFontScaleChanged() {
-        TypedArray icons = mContext.getResources().obtainTypedArray(R.array.car_facet_icons);
-
-        try {
-            int length = icons.length();
-            if (length != mNavButtons.size()) {
-                // This should not happen since the mNavButtons list is created from the length
-                // of the icons array in bind().
-                throw new RuntimeException("car_facet array lengths do not match number of "
-                        + "created buttons.");
-            }
-
-            for (int i = 0; i < length; i++) {
-                Drawable icon = icons.getDrawable(i);
-
-                // Setting a new icon will trigger a requestLayout() call if necessary.
-                mNavButtons.get(i).setResources(icon);
-            }
-        } finally {
-            icons.recycle();
-        }
-    }
-
-    private void initFacetFilterMaps(int id, String[] packageNames, String[] categories) {
-        mFacetCategories.add(categories);
-        for (String category : categories) {
-            mFacetCategoryMap.put(category, id);
-        }
-
-        mFacetPackages.add(packageNames);
-        for (String packageName : packageNames) {
-            mFacetPackageMap.put(packageName, id);
-        }
-    }
-
-    private String getPackageCategory(String packageName) {
-        PackageManager pm = mContext.getPackageManager();
-        int size = mFacetCategories.size();
-        // For each facet, check if the given package name matches one of its categories
-        for (int i = 0; i < size; i++) {
-            String[] categories = mFacetCategories.get(i);
-            for (int j = 0; j < categories.length; j++) {
-                String category = categories[j];
-                Intent intent = new Intent();
-                intent.setPackage(packageName);
-                intent.setAction(Intent.ACTION_MAIN);
-                intent.addCategory(category);
-                List<ResolveInfo> list = pm.queryIntentActivities(intent, 0);
-                if (list.size() > 0) {
-                    // Cache this package name into facetPackageMap, so we won't have to query
-                    // all categories next time this package name shows up.
-                    mFacetPackageMap.put(packageName, mFacetCategoryMap.get(category));
-                    return category;
-                }
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Helper method to check if a given facet has multiple packages associated with it. This can
-     * be resource defined package names or package names filtered by facet category.
-     *
-     * @return {@code true} if the facet at the given index has more than one package.
-     */
-    private boolean facetHasMultiplePackages(int index) {
-        PackageManager pm = mContext.getPackageManager();
-
-        // Check if the packages defined for the filter actually exists on the device
-        String[] packages = mFacetPackages.get(index);
-        if (packages.length > 1) {
-            int count = 0;
-            for (int i = 0; i < packages.length; i++) {
-                count += pm.getLaunchIntentForPackage(packages[i]) != null ? 1 : 0;
-                if (count > 1) {
-                    return true;
-                }
-            }
-        }
-
-        // If there weren't multiple packages defined for the facet, check the categories
-        // and see if they resolve to multiple package names
-        String categories[] = mFacetCategories.get(index);
-
-        int count = 0;
-        for (int i = 0; i < categories.length; i++) {
-            String category = categories[i];
-            Intent intent = new Intent();
-            intent.setAction(Intent.ACTION_MAIN);
-            intent.addCategory(category);
-            count += pm.queryIntentActivities(intent, 0).size();
-            if (count > 1) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Sets the facet at the given index to be the facet that is currently active. The button will
-     * be highlighted appropriately.
-     */
-    private void setCurrentFacet(int index) {
-        if (index == mCurrentFacetIndex) {
-            return;
-        }
-
-        if (mNavButtons.get(mCurrentFacetIndex) != null) {
-            mNavButtons.get(mCurrentFacetIndex)
-                    .setSelected(false /* selected */, false /* showMoreIcon */);
-        }
-
-        if (mNavButtons.get(index) != null) {
-            mNavButtons.get(index).setSelected(true /* selected */,
-                    mFacetHasMultipleAppsCache.get(index)  /* showMoreIcon */);
-        }
-
-        mCurrentFacetIndex = index;
-    }
-
-    /**
-     * Creates the View that is used for the buttons along the navigation bar.
-     *
-     * @param icon The icon to be used for the button.
-     */
-    private CarNavigationButton createNavButton(Drawable icon) {
-        CarNavigationButton button = (CarNavigationButton) View.inflate(mContext,
-                R.layout.car_navigation_button, null);
-        button.setResources(icon);
-        LinearLayout.LayoutParams lp =
-                new LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.MATCH_PARENT, 1);
-        button.setLayoutParams(lp);
-
-        return button;
-    }
-
-    /**
-     * Initializes the click and long click listeners that correspond to the given command string.
-     * The click listeners are attached to the given button.
-     */
-    private void initClickListeners(View button, int index, String clickString,
-            String longPressString) {
-        // Each button at least have an action when pressed.
-        if (TextUtils.isEmpty(clickString)) {
-            throw new RuntimeException("Facet at index " + index + " does not have click action.");
-        }
-
-        try {
-            Intent intent = Intent.parseUri(clickString, Intent.URI_INTENT_SCHEME);
-            button.setOnClickListener(v -> onFacetClicked(intent, index));
-        } catch (URISyntaxException e) {
-            throw new RuntimeException("Malformed intent uri", e);
-        }
-
-        if (TextUtils.isEmpty(longPressString)) {
-            button.setLongClickable(false);
-            return;
-        }
-
-        try {
-            Intent intent = Intent.parseUri(longPressString, Intent.URI_INTENT_SCHEME);
-            button.setOnLongClickListener(v -> {
-                onFacetLongClicked(intent, index);
-                return true;
-            });
-        } catch (URISyntaxException e) {
-            throw new RuntimeException("Malformed long-press intent uri", e);
-        }
-    }
-
-    /**
-     * Handles a click on a facet. A click will trigger the given Intent.
-     *
-     * @param index The index of the facet that was clicked.
-     */
-    private void onFacetClicked(Intent intent, int index) {
-        String packageName = intent.getPackage();
-
-        if (packageName == null && !intent.getCategories().contains(Intent.CATEGORY_HOME)) {
-            return;
-        }
-
-        intent.putExtra(EXTRA_FACET_CATEGORIES, mFacetCategories.get(index));
-        intent.putExtra(EXTRA_FACET_PACKAGES, mFacetPackages.get(index));
-        // The facet is identified by the index in which it was added to the nav bar.
-        // This value can be used to determine which facet was selected
-        intent.putExtra(EXTRA_FACET_ID, Integer.toString(index));
-
-        // If the current facet is clicked, we want to launch the picker by default
-        // rather than the "preferred/last run" app.
-        intent.putExtra(EXTRA_FACET_LAUNCH_PICKER, index == mCurrentFacetIndex);
-
-        int windowingMode = WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY;
-        int activityType = ACTIVITY_TYPE_UNDEFINED;
-        if (intent.getCategories().contains(Intent.CATEGORY_HOME)) {
-            windowingMode = WINDOWING_MODE_UNDEFINED;
-            activityType = ACTIVITY_TYPE_HOME;
-        }
-
-        setCurrentFacet(index);
-        mStatusBar.startActivityOnStack(intent, windowingMode, activityType);
-    }
-
-    /**
-     * Handles a long-press on a facet. The long-press will trigger the given Intent.
-     *
-     * @param index The index of the facet that was clicked.
-     */
-    private void onFacetLongClicked(Intent intent, int index) {
-        setCurrentFacet(index);
-        mStatusBar.startActivityOnStack(intent,
-                WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY, ACTIVITY_TYPE_UNDEFINED);
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarView.java
index e5a311d..1d9ef61 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarView.java
@@ -16,17 +16,15 @@
 
 package com.android.systemui.statusbar.car;
 
+import android.app.UiModeManager;
 import android.content.Context;
-import android.graphics.Canvas;
 import android.util.AttributeSet;
-import android.view.MotionEvent;
+import android.util.Log;
 import android.view.View;
 import android.widget.LinearLayout;
 
+import com.android.keyguard.AlphaOptimizedImageButton;
 import com.android.systemui.R;
-import com.android.systemui.plugins.statusbar.phone.NavGesture;
-import com.android.systemui.statusbar.phone.NavigationBarGestureHelper;
-import com.android.systemui.statusbar.phone.NavigationBarView;
 
 /**
  * A custom navigation bar for the automotive use case.
@@ -34,9 +32,10 @@
  * The navigation bar in the automotive use case is more like a list of shortcuts, rendered
  * in a linear layout.
  */
-class CarNavigationBarView extends NavigationBarView {
+class CarNavigationBarView extends LinearLayout {
     private LinearLayout mNavButtons;
-    private LinearLayout mLightsOutButtons;
+    private AlphaOptimizedImageButton mNotificationsButton;
+    private CarStatusBar mCarStatusBar;
 
     public CarNavigationBarView(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -45,99 +44,16 @@
     @Override
     public void onFinishInflate() {
         mNavButtons = findViewById(R.id.nav_buttons);
-        mLightsOutButtons = findViewById(R.id.lights_out);
+
+        mNotificationsButton = findViewById(R.id.notifications);
+        mNotificationsButton.setOnClickListener(this::onNotificationsClick);
     }
 
-    public void addButton(CarNavigationButton button, CarNavigationButton lightsOutButton){
-        mNavButtons.addView(button);
-        mLightsOutButtons.addView(lightsOutButton);
+    void setStatusBar(CarStatusBar carStatusBar) {
+        mCarStatusBar = carStatusBar;
     }
 
-    @Override
-    public void setDisabledFlags(int disabledFlags, boolean force) {
-        // TODO: Populate.
-    }
-
-    @Override
-    public void reorient() {
-        // We expect the car head unit to always have a fixed rotation so we ignore this. The super
-        // class implentation expects mRotatedViews to be populated, so if you call into it, there
-        // is a possibility of a NullPointerException.
-    }
-
-    @Override
-    public View getCurrentView() {
-        return this;
-    }
-
-    @Override
-    public void setNavigationIconHints(int hints, boolean force) {
-        // We do not need to set the navigation icon hints for a vehicle
-        // Calling setNavigationIconHints in the base class will result in a NPE as the car
-        // navigation bar does not have a back button.
-    }
-
-    @Override
-    public void onPluginConnected(NavGesture plugin, Context context) {
-        // set to null version of the plugin ignoring incoming arg.
-        super.onPluginConnected(new NullNavGesture(), context);
-    }
-
-    @Override
-    public void onPluginDisconnected(NavGesture plugin) {
-        // reinstall the null nav gesture plugin
-        super.onPluginConnected(new NullNavGesture(), getContext());
-    }
-
-    /**
-     * Null object pattern to work around expectations of the base class.
-     * This is a temporary solution to have the car system ui working.
-     * Already underway is a refactor of they car sys ui as to not use this class
-     * hierarchy.
-     */
-    private static class NullNavGesture implements NavGesture {
-        @Override
-        public GestureHelper getGestureHelper() {
-            return new GestureHelper() {
-                @Override
-                public boolean onTouchEvent(MotionEvent event) {
-                    return false;
-                }
-
-                @Override
-                public boolean onInterceptTouchEvent(MotionEvent event) {
-                    return false;
-                }
-
-                @Override
-                public void setBarState(boolean vertical, boolean isRtl) {
-                }
-
-                @Override
-                public void onDraw(Canvas canvas) {
-                }
-
-                @Override
-                public void onDarkIntensityChange(float intensity) {
-                }
-
-                @Override
-                public void onLayout(boolean changed, int left, int top, int right, int bottom) {
-                }
-            };
-        }
-
-        @Override
-        public int getVersion() {
-            return 0;
-        }
-
-        @Override
-        public void onCreate(Context sysuiContext, Context pluginContext) {
-        }
-
-        @Override
-        public void onDestroy() {
-        }
+    protected void onNotificationsClick(View v) {
+        mCarStatusBar.togglePanel();
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationButton.java
index 2de358f..0cdaec1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationButton.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationButton.java
@@ -1,72 +1,87 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
 package com.android.systemui.statusbar.car;
 
 import android.content.Context;
-import android.graphics.drawable.Drawable;
+import android.content.Intent;
+import android.content.res.TypedArray;
 import android.util.AttributeSet;
 import android.widget.ImageView;
-import android.widget.RelativeLayout;
 
-import com.android.keyguard.AlphaOptimizedImageButton;
 import com.android.systemui.R;
 
+import java.net.URISyntaxException;
+
 /**
- * A wrapper view for a car navigation facet, which includes a button icon and a drop down icon.
+ * CarNavigationButton is an image button that allows for a bit more configuration at the
+ * xml file level. This allows for more control via overlays instead of having to update
+ * code.
  */
-public class CarNavigationButton extends RelativeLayout {
+public class CarNavigationButton extends com.android.keyguard.AlphaOptimizedImageButton {
+
     private static final float SELECTED_ALPHA = 1;
     private static final float UNSELECTED_ALPHA = 0.7f;
 
-    private AlphaOptimizedImageButton mIcon;
-    private AlphaOptimizedImageButton mMoreIcon;
+    private Context mContext;
+    private String mIntent = null;
+    private String mLongIntent = null;
+    private boolean mBroadcastIntent = false;
+    private boolean mSelected = false;
+
 
     public CarNavigationButton(Context context, AttributeSet attrs) {
         super(context, attrs);
+        mContext = context;
+        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CarNavigationButton);
+        mIntent = typedArray.getString(R.styleable.CarNavigationButton_intent);
+        mLongIntent = typedArray.getString(R.styleable.CarNavigationButton_longIntent);
+        mBroadcastIntent = typedArray.getBoolean(R.styleable.CarNavigationButton_broadcast, false);
     }
 
+
+    /**
+     * After the standard inflate this then adds the xml defined intents to click and long click
+     * actions if defined.
+     */
     @Override
     public void onFinishInflate() {
         super.onFinishInflate();
-        mIcon = findViewById(R.id.car_nav_button_icon);
-        mIcon.setScaleType(ImageView.ScaleType.CENTER);
-        mIcon.setClickable(false);
-        mIcon.setBackgroundColor(android.R.color.transparent);
-        mIcon.setAlpha(UNSELECTED_ALPHA);
-
-        mMoreIcon = findViewById(R.id.car_nav_button_more_icon);
-        mMoreIcon.setClickable(false);
-        mMoreIcon.setBackgroundColor(android.R.color.transparent);
-        mMoreIcon.setVisibility(INVISIBLE);
-        mMoreIcon.setImageDrawable(getContext().getDrawable(R.drawable.car_ic_arrow));
-        mMoreIcon.setAlpha(UNSELECTED_ALPHA);
-    }
-
-    public void setResources(Drawable icon) {
-        mIcon.setImageDrawable(icon);
-    }
-
-    public void setSelected(boolean selected, boolean showMoreIcon) {
-        if (selected) {
-            mMoreIcon.setVisibility(showMoreIcon ? VISIBLE : INVISIBLE);
-            mMoreIcon.setAlpha(SELECTED_ALPHA);
-            mIcon.setAlpha(SELECTED_ALPHA);
-        } else {
-            mMoreIcon.setVisibility(INVISIBLE);
-            mIcon.setAlpha(UNSELECTED_ALPHA);
+        setScaleType(ImageView.ScaleType.CENTER);
+        setAlpha(UNSELECTED_ALPHA);
+        try {
+            if (mIntent != null) {
+                final Intent intent = Intent.parseUri(mIntent, Intent.URI_INTENT_SCHEME);
+                intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
+                setOnClickListener(v -> {
+                    if (mBroadcastIntent) {
+                        mContext.sendBroadcast(intent);
+                        return;
+                    }
+                    mContext.startActivity(intent);
+                });
+            }
+        } catch (URISyntaxException e) {
+            throw new RuntimeException("Failed to attach intent", e);
         }
+
+        try {
+            if (mLongIntent != null) {
+                final Intent intent = Intent.parseUri(mLongIntent, Intent.URI_INTENT_SCHEME);
+                intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
+                setOnLongClickListener(v -> {
+                    mContext.startActivity(intent);
+                    return true;
+                });
+            }
+        } catch (URISyntaxException e) {
+            throw new RuntimeException("Failed to attach long press intent", e);
+        }
+    }
+
+    /**
+     * @param selected true if should indicate if this is a selected state, false otherwise
+     */
+    public void setSelected(boolean selected) {
+        super.setSelected(selected);
+        mSelected = selected;
+        setAlpha(mSelected ? SELECTED_ALPHA : UNSELECTED_ALPHA);
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
index 3ebeb4d..c15a013 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
@@ -18,17 +18,14 @@
 
 import android.app.ActivityManager;
 import android.app.ActivityOptions;
-import android.content.BroadcastReceiver;
-import android.content.Context;
 import android.content.Intent;
-import android.content.IntentFilter;
 import android.graphics.PixelFormat;
 import android.graphics.drawable.Drawable;
 import android.os.Bundle;
 import android.os.RemoteException;
 import android.os.UserHandle;
-import android.service.notification.StatusBarNotification;
 import android.util.Log;
+import android.view.Gravity;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.ViewGroup.LayoutParams;
@@ -46,10 +43,7 @@
 import com.android.systemui.fragments.FragmentHostManager;
 import com.android.systemui.recents.Recents;
 import com.android.systemui.recents.misc.SysUiTaskStackChangeListener;
-import com.android.systemui.recents.misc.SystemServicesProxy;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
-import com.android.systemui.statusbar.ExpandableNotificationRow;
-import com.android.systemui.statusbar.NotificationData;
 import com.android.systemui.statusbar.StatusBarState;
 import com.android.systemui.statusbar.phone.CollapsedStatusBarFragment;
 import com.android.systemui.statusbar.phone.NavigationBarView;
@@ -69,7 +63,6 @@
 
     private TaskStackListenerImpl mTaskStackListener;
 
-    private CarNavigationBarController mController;
     private FullscreenUserSwitcher mFullscreenUserSwitcher;
 
     private CarBatteryController mCarBatteryController;
@@ -78,15 +71,23 @@
 
     private ConnectedDeviceSignalController mConnectedDeviceSignalController;
     private ViewGroup mNavigationBarWindow;
+    private ViewGroup mLeftNavigationBarWindow;
+    private ViewGroup mRightNavigationBarWindow;
     private CarNavigationBarView mNavigationBarView;
+    private CarNavigationBarView mLeftNavigationBarView;
+    private CarNavigationBarView mRightNavigationBarView;
 
     private final Object mQueueLock = new Object();
+    private boolean mShowLeft;
+    private boolean mShowRight;
+    private boolean mShowBottom;
+    private CarFacetButtonController mCarFacetButtonController;
+
     @Override
     public void start() {
         super.start();
         mTaskStackListener = new TaskStackListenerImpl();
         ActivityManagerWrapper.getInstance().registerTaskStackListener(mTaskStackListener);
-        registerPackageChangeReceivers();
 
         mStackScroller.setScrollingEnabled(true);
 
@@ -104,6 +105,16 @@
             mNavigationBarView = null;
         }
 
+        if (mLeftNavigationBarWindow != null) {
+            mWindowManager.removeViewImmediate(mLeftNavigationBarWindow);
+            mLeftNavigationBarView = null;
+        }
+
+        if (mRightNavigationBarWindow != null) {
+            mWindowManager.removeViewImmediate(mRightNavigationBarWindow);
+            mRightNavigationBarView = null;
+        }
+
         super.destroy();
     }
 
@@ -153,10 +164,36 @@
 
     @Override
     protected void createNavigationBar() {
+        mCarFacetButtonController = new CarFacetButtonController(mContext);
         if (mNavigationBarView != null) {
             return;
         }
 
+        mShowBottom = mContext.getResources().getBoolean(R.bool.config_enableBottomNavigationBar);
+        if (mShowBottom) {
+            buildBottomBar();
+        }
+
+        int widthForSides = mContext.getResources().getDimensionPixelSize(
+                R.dimen.navigation_bar_height_car_mode);
+
+
+        mShowLeft = mContext.getResources().getBoolean(R.bool.config_enableLeftNavigationBar);
+
+        if (mShowLeft) {
+            buildLeft(widthForSides);
+        }
+
+        mShowRight = mContext.getResources().getBoolean(R.bool.config_enableRightNavigationBar);
+
+        if (mShowRight) {
+            buildRight(widthForSides);
+        }
+
+    }
+
+
+    private void buildBottomBar() {
         // SystemUI requires that the navigation bar view have a parent. Since the regular
         // StatusBar inflates navigation_bar_window as this parent view, use the same view for the
         // CarNavigationBarView.
@@ -171,17 +208,15 @@
         mNavigationBarView = (CarNavigationBarView) mNavigationBarWindow.getChildAt(0);
         if (mNavigationBarView == null) {
             Log.e(TAG, "CarStatusBar failed inflate for R.layout.car_navigation_bar");
+            throw new RuntimeException("Unable to build botom nav bar due to missing layout");
         }
+        mNavigationBarView.setStatusBar(this);
 
 
-        mController = new CarNavigationBarController(mContext, mNavigationBarView,
-                this /* ActivityStarter*/);
-        mNavigationBarView.getBarTransitions().setAlwaysOpaque(true);
         WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
                 LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT,
                 WindowManager.LayoutParams.TYPE_NAVIGATION_BAR,
-                WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING
-                        | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                         | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
                         | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
                         | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
@@ -189,9 +224,74 @@
         lp.setTitle("CarNavigationBar");
         lp.windowAnimations = 0;
 
+
+        mCarFacetButtonController.addCarNavigationBar(mNavigationBarView);
         mWindowManager.addView(mNavigationBarWindow, lp);
     }
 
+    private void buildLeft(int widthForSides) {
+        mLeftNavigationBarWindow = (ViewGroup) View.inflate(mContext,
+                R.layout.navigation_bar_window, null);
+        if (mLeftNavigationBarWindow == null) {
+            Log.e(TAG, "CarStatusBar failed inflate for R.layout.navigation_bar_window");
+        }
+
+        View.inflate(mContext, R.layout.car_left_navigation_bar, mLeftNavigationBarWindow);
+        mLeftNavigationBarView = (CarNavigationBarView) mLeftNavigationBarWindow.getChildAt(0);
+        if (mLeftNavigationBarView == null) {
+            Log.e(TAG, "CarStatusBar failed inflate for R.layout.car_navigation_bar");
+            throw new RuntimeException("Unable to build left nav bar due to missing layout");
+        }
+        mLeftNavigationBarView.setStatusBar(this);
+        mCarFacetButtonController.addCarNavigationBar(mLeftNavigationBarView);
+
+        WindowManager.LayoutParams leftlp = new WindowManager.LayoutParams(
+                widthForSides, LayoutParams.MATCH_PARENT,
+                WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL,
+                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+                        | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
+                        | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
+                        | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
+                PixelFormat.TRANSLUCENT);
+        leftlp.setTitle("LeftCarNavigationBar");
+        leftlp.windowAnimations = 0;
+        leftlp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_IS_SCREEN_DECOR;
+        leftlp.gravity = Gravity.LEFT;
+        mWindowManager.addView(mLeftNavigationBarWindow, leftlp);
+    }
+
+
+    private void buildRight(int widthForSides) {
+        mRightNavigationBarWindow = (ViewGroup) View.inflate(mContext,
+                R.layout.navigation_bar_window, null);
+        if (mRightNavigationBarWindow == null) {
+            Log.e(TAG, "CarStatusBar failed inflate for R.layout.navigation_bar_window");
+        }
+
+        View.inflate(mContext, R.layout.car_right_navigation_bar, mRightNavigationBarWindow);
+        mRightNavigationBarView = (CarNavigationBarView) mRightNavigationBarWindow.getChildAt(0);
+        if (mRightNavigationBarView == null) {
+            Log.e(TAG, "CarStatusBar failed inflate for R.layout.car_navigation_bar");
+            throw new RuntimeException("Unable to build right nav bar due to missing layout");
+        }
+        mRightNavigationBarView.setStatusBar(this);
+        mCarFacetButtonController.addCarNavigationBar(mRightNavigationBarView);
+
+        WindowManager.LayoutParams rightlp = new WindowManager.LayoutParams(
+                widthForSides, LayoutParams.MATCH_PARENT,
+                WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL,
+                 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+                        | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
+                        | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
+                        | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
+                PixelFormat.TRANSLUCENT);
+        rightlp.setTitle("RightCarNavigationBar");
+        rightlp.windowAnimations = 0;
+        rightlp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_IS_SCREEN_DECOR;
+        rightlp.gravity = Gravity.RIGHT;
+        mWindowManager.addView(mRightNavigationBarWindow, rightlp);
+    }
+
     @Override
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         //When executing dump() funciton simultaneously, we need to serialize them
@@ -204,8 +304,8 @@
         }
 
         pw.print("  mTaskStackListener="); pw.println(mTaskStackListener);
-        pw.print("  mController=");
-        pw.println(mController);
+        pw.print("  mCarFacetButtonController=");
+        pw.println(mCarFacetButtonController);
         pw.print("  mFullscreenUserSwitcher="); pw.println(mFullscreenUserSwitcher);
         pw.print("  mCarBatteryController=");
         pw.println(mCarBatteryController);
@@ -229,10 +329,6 @@
         }
     }
 
-    @Override
-    public NavigationBarView getNavigationBarView() {
-        return mNavigationBarView;
-    }
 
     @Override
     public View getNavigationBarWindow() {
@@ -269,24 +365,6 @@
         }
     }
 
-    private BroadcastReceiver mPackageChangeReceiver = new BroadcastReceiver() {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            if (intent.getData() == null || mController == null) {
-                return;
-            }
-            String packageName = intent.getData().getSchemeSpecificPart();
-            mController.onPackageChange(packageName);
-        }
-    };
-
-    private void registerPackageChangeReceivers() {
-        IntentFilter filter = new IntentFilter();
-        filter.addAction(Intent.ACTION_PACKAGE_ADDED);
-        filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
-        filter.addDataScheme("package");
-        mContext.registerReceiver(mPackageChangeReceiver, filter);
-    }
 
     public boolean hasDockedTask() {
         return Recents.getSystemServices().hasDockedTask();
@@ -301,10 +379,7 @@
         public void onTaskStackChanged() {
             ActivityManager.RunningTaskInfo runningTaskInfo =
                     ActivityManagerWrapper.getInstance().getRunningTask();
-            if (runningTaskInfo != null && runningTaskInfo.baseActivity != null) {
-                mController.taskChanged(runningTaskInfo.baseActivity.getPackageName(),
-                        runningTaskInfo);
-            }
+            mCarFacetButtonController.taskChanged(runningTaskInfo);
         }
     }
 
@@ -346,40 +421,13 @@
         // Do nothing, we don't want to display media art in the lock screen for a car.
     }
 
-    private int startActivityWithOptions(Intent intent, Bundle options) {
-        int result = ActivityManager.START_CANCELED;
-        try {
-            result = ActivityManager.getService().startActivityAsUser(null /* caller */,
-                    mContext.getBasePackageName(),
-                    intent,
-                    intent.resolveTypeIfNeeded(mContext.getContentResolver()),
-                    null /* resultTo*/,
-                    null /* resultWho*/,
-                    0 /* requestCode*/,
-                    Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP,
-                    null /* profilerInfo*/,
-                    options,
-                    UserHandle.CURRENT.getIdentifier());
-        } catch (RemoteException e) {
-            Log.w(TAG, "Unable to start activity", e);
-        }
-
-        return result;
-    }
-
-    public int startActivityOnStack(Intent intent, int windowingMode, int activityType) {
-        final ActivityOptions options = ActivityOptions.makeBasic();
-        options.setLaunchWindowingMode(windowingMode);
-        options.setLaunchActivityType(activityType);
-        return startActivityWithOptions(intent, options.toBundle());
-    }
 
     @Override
     public void animateExpandNotificationsPanel() {
         // Because space is usually constrained in the auto use-case, there should not be a
         // pinned notification when the shade has been expanded. Ensure this by removing all heads-
         // up notifications.
-        mHeadsUpManager.removeAllHeadsUpEntries();
+        mHeadsUpManager.releaseAllImmediately();
         super.animateExpandNotificationsPanel();
     }
 
@@ -390,8 +438,6 @@
     @Override
     public void onDensityOrFontScaleChanged() {
         super.onDensityOrFontScaleChanged();
-        mController.onDensityOrFontScaleChanged();
-
         // Need to update the background on density changed in case the change was due to night
         // mode.
         mNotificationPanelBackground = getDefaultWallpaper();
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/notification/ActivityLaunchAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java
index 11d20b2..ef44ad1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java
@@ -77,11 +77,11 @@
         mStatusBar = statusBar;
     }
 
-    public ActivityOptions getLaunchAnimation(
-            ExpandableNotificationRow sourceNofitication) {
-        AnimationRunner animationRunner = new AnimationRunner(sourceNofitication);
-        return ActivityOptions.makeRemoteAnimation(
-                new RemoteAnimationAdapter(animationRunner, 1000 /* Duration */, 0 /* delay */));
+    public RemoteAnimationAdapter getLaunchAnimation(
+            ExpandableNotificationRow sourceNotification) {
+        AnimationRunner animationRunner = new AnimationRunner(sourceNotification);
+        return new RemoteAnimationAdapter(animationRunner, ANIMATION_DURATION,
+                0 /* statusBarTransitionDelay */);
     }
 
     public boolean isAnimationPending() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ImageTransformState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ImageTransformState.java
index 8227b77..d3a325d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ImageTransformState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ImageTransformState.java
@@ -21,6 +21,8 @@
 import android.view.View;
 import android.widget.ImageView;
 
+import com.android.internal.widget.MessagingImageMessage;
+import com.android.internal.widget.MessagingMessage;
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.CrossFadeHelper;
@@ -117,13 +119,15 @@
 
     @Override
     protected boolean transformScale(TransformState otherState) {
-        return true;
+        return sameAs(otherState);
     }
 
     @Override
     public void recycle() {
         super.recycle();
-        sInstancePool.release(this);
+        if (getClass() == ImageTransformState.class) {
+            sInstancePool.release(this);
+        }
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/MessagingImageTransformState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/MessagingImageTransformState.java
new file mode 100644
index 0000000..b97995d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/MessagingImageTransformState.java
@@ -0,0 +1,134 @@
+/*
+ * 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.notification;
+
+import android.util.Pools;
+import android.view.View;
+
+import com.android.internal.widget.MessagingImageMessage;
+import com.android.systemui.Interpolators;
+import com.android.systemui.R;
+import com.android.systemui.statusbar.ViewTransformationHelper;
+
+/**
+ * A transform state of a image view.
+*/
+public class MessagingImageTransformState extends ImageTransformState {
+    private static Pools.SimplePool<MessagingImageTransformState> sInstancePool
+            = new Pools.SimplePool<>(40);
+    private static final int START_ACTUAL_WIDTH = R.id.transformation_start_actual_width;
+    private static final int START_ACTUAL_HEIGHT = R.id.transformation_start_actual_height;
+    private MessagingImageMessage mImageMessage;
+
+    @Override
+    public void initFrom(View view, TransformInfo transformInfo) {
+        super.initFrom(view, transformInfo);
+        mImageMessage = (MessagingImageMessage) view;
+    }
+
+    @Override
+    protected boolean sameAs(TransformState otherState) {
+        if (super.sameAs(otherState)) {
+            return true;
+        }
+        if (otherState instanceof MessagingImageTransformState) {
+            MessagingImageTransformState otherMessage = (MessagingImageTransformState) otherState;
+            return mImageMessage.sameAs(otherMessage.mImageMessage);
+        }
+        return false;
+    }
+
+    public static MessagingImageTransformState obtain() {
+        MessagingImageTransformState instance = sInstancePool.acquire();
+        if (instance != null) {
+            return instance;
+        }
+        return new MessagingImageTransformState();
+    }
+
+    @Override
+    protected boolean transformScale(TransformState otherState) {
+        return false;
+    }
+
+    @Override
+    protected void transformViewFrom(TransformState otherState, int transformationFlags,
+            ViewTransformationHelper.CustomTransformation customTransformation,
+            float transformationAmount) {
+        super.transformViewFrom(otherState, transformationFlags, customTransformation,
+                transformationAmount);
+        float interpolatedValue = mDefaultInterpolator.getInterpolation(
+                transformationAmount);
+        if (otherState instanceof MessagingImageTransformState && sameAs(otherState)) {
+            MessagingImageMessage otherMessage
+                    = ((MessagingImageTransformState) otherState).mImageMessage;
+            if (transformationAmount == 0.0f) {
+                setStartActualWidth(otherMessage.getActualWidth());
+                setStartActualHeight(otherMessage.getActualHeight());
+            }
+            float startActualWidth = getStartActualWidth();
+            mImageMessage.setActualWidth(
+                    (int) NotificationUtils.interpolate(startActualWidth,
+                            mImageMessage.getStaticWidth(),
+                            interpolatedValue));
+            float startActualHeight = getStartActualHeight();
+            mImageMessage.setActualHeight(
+                    (int) NotificationUtils.interpolate(startActualHeight,
+                            mImageMessage.getHeight(),
+                            interpolatedValue));
+        }
+    }
+
+    public int getStartActualWidth() {
+        Object tag = mTransformedView.getTag(START_ACTUAL_WIDTH);
+        return tag == null ? -1 : (int) tag;
+    }
+
+    public void setStartActualWidth(int actualWidth) {
+        mTransformedView.setTag(START_ACTUAL_WIDTH, actualWidth);
+    }
+
+    public int getStartActualHeight() {
+        Object tag = mTransformedView.getTag(START_ACTUAL_HEIGHT);
+        return tag == null ? -1 : (int) tag;
+    }
+
+    public void setStartActualHeight(int actualWidth) {
+        mTransformedView.setTag(START_ACTUAL_HEIGHT, actualWidth);
+    }
+
+    @Override
+    public void recycle() {
+        super.recycle();
+        if (getClass() == MessagingImageTransformState.class) {
+            sInstancePool.release(this);
+        }
+    }
+
+    @Override
+    protected void resetTransformedView() {
+        super.resetTransformedView();
+        mImageMessage.setActualWidth(mImageMessage.getStaticWidth());
+        mImageMessage.setActualHeight(mImageMessage.getHeight());
+    }
+
+    @Override
+    protected void reset() {
+        super.reset();
+        mImageMessage = null;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/MessagingLayoutTransformState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/MessagingLayoutTransformState.java
index 113118a..314a31d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/MessagingLayoutTransformState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/MessagingLayoutTransformState.java
@@ -22,6 +22,7 @@
 import android.view.ViewGroup;
 
 import com.android.internal.widget.MessagingGroup;
+import com.android.internal.widget.MessagingImageMessage;
 import com.android.internal.widget.MessagingLayout;
 import com.android.internal.widget.MessagingLinearLayout;
 import com.android.internal.widget.MessagingMessage;
@@ -30,6 +31,7 @@
 
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.List;
 
 /**
  * A transform state of the action list
@@ -156,6 +158,7 @@
         }
         appear(ownGroup.getAvatar(), transformationAmount);
         appear(ownGroup.getSenderView(), transformationAmount);
+        appear(ownGroup.getIsolatedMessage(), transformationAmount);
         setClippingDeactivated(ownGroup.getSenderView(), true);
         setClippingDeactivated(ownGroup.getAvatar(), true);
     }
@@ -187,12 +190,13 @@
         }
         disappear(ownGroup.getAvatar(), transformationAmount);
         disappear(ownGroup.getSenderView(), transformationAmount);
+        disappear(ownGroup.getIsolatedMessage(), transformationAmount);
         setClippingDeactivated(ownGroup.getSenderView(), true);
         setClippingDeactivated(ownGroup.getAvatar(), true);
     }
 
     private void appear(View child, float transformationAmount) {
-        if (child.getVisibility() == View.GONE) {
+        if (child == null || child.getVisibility() == View.GONE) {
             return;
         }
         TransformState ownState = TransformState.createFrom(child, mTransformInfo);
@@ -201,7 +205,7 @@
     }
 
     private void disappear(View child, float transformationAmount) {
-        if (child.getVisibility() == View.GONE) {
+        if (child == null || child.getVisibility() == View.GONE) {
             return;
         }
         TransformState ownState = TransformState.createFrom(child, mTransformInfo);
@@ -224,22 +228,24 @@
 
     private void transformGroups(MessagingGroup ownGroup, MessagingGroup otherGroup,
             float transformationAmount, boolean to) {
+        boolean useLinearTransformation =
+                otherGroup.getIsolatedMessage() == null && !mTransformInfo.isAnimating();
         transformView(transformationAmount, to, ownGroup.getSenderView(), otherGroup.getSenderView(),
-                true /* sameAsAny */);
+                true /* sameAsAny */, useLinearTransformation);
         transformView(transformationAmount, to, ownGroup.getAvatar(), otherGroup.getAvatar(),
-                true /* sameAsAny */);
-        MessagingLinearLayout ownMessages = ownGroup.getMessageContainer();
-        MessagingLinearLayout otherMessages = otherGroup.getMessageContainer();
+                true /* sameAsAny */, useLinearTransformation);
+        List<MessagingMessage> ownMessages = ownGroup.getMessages();
+        List<MessagingMessage> otherMessages = otherGroup.getMessages();
         float previousTranslation = 0;
-        for (int i = 0; i < ownMessages.getChildCount(); i++) {
-            View child = ownMessages.getChildAt(ownMessages.getChildCount() - 1 - i);
+        for (int i = 0; i < ownMessages.size(); i++) {
+            View child = ownMessages.get(ownMessages.size() - 1 - i).getView();
             if (isGone(child)) {
                 continue;
             }
-            int otherIndex = otherMessages.getChildCount() - 1 - i;
+            int otherIndex = otherMessages.size() - 1 - i;
             View otherChild = null;
             if (otherIndex >= 0) {
-                otherChild = otherMessages.getChildAt(otherIndex);
+                otherChild = otherMessages.get(otherIndex).getView();
                 if (isGone(otherChild)) {
                     otherChild = null;
                 }
@@ -252,7 +258,12 @@
                     transformationAmount = 1.0f - transformationAmount;
                 }
             }
-            transformView(transformationAmount, to, child, otherChild, false /* sameAsAny */);
+            transformView(transformationAmount, to, child, otherChild, false, /* sameAsAny */
+                    useLinearTransformation);
+            if (transformationAmount == 0.0f
+                    && otherGroup.getIsolatedMessage() == otherChild) {
+                ownGroup.setTransformingImages(true);
+            }
             if (otherChild == null) {
                 child.setTranslationY(previousTranslation);
                 setClippingDeactivated(child, true);
@@ -264,12 +275,13 @@
                 previousTranslation = child.getTranslationY();
             }
         }
+        ownGroup.updateClipRect();
     }
 
     private void transformView(float transformationAmount, boolean to, View ownView,
-            View otherView, boolean sameAsAny) {
+            View otherView, boolean sameAsAny, boolean useLinearTransformation) {
         TransformState ownState = TransformState.createFrom(ownView, mTransformInfo);
-        if (!mTransformInfo.isAnimating()) {
+        if (useLinearTransformation) {
             ownState.setDefaultInterpolator(Interpolators.LINEAR);
         }
         ownState.setIsSameAsAnyView(sameAsAny);
@@ -339,11 +351,15 @@
             if (!isGone(ownGroup)) {
                 MessagingLinearLayout ownMessages = ownGroup.getMessageContainer();
                 for (int j = 0; j < ownMessages.getChildCount(); j++) {
-                    MessagingMessage child = (MessagingMessage) ownMessages.getChildAt(j);
+                    View child = ownMessages.getChildAt(j);
                     setVisible(child, visible, force);
                 }
                 setVisible(ownGroup.getAvatar(), visible, force);
                 setVisible(ownGroup.getSenderView(), visible, force);
+                MessagingImageMessage isolatedMessage = ownGroup.getIsolatedMessage();
+                if (isolatedMessage != null) {
+                    setVisible(isolatedMessage, visible, force);
+                }
             }
         }
     }
@@ -375,11 +391,17 @@
                 }
                 resetTransformedView(ownGroup.getAvatar());
                 resetTransformedView(ownGroup.getSenderView());
+                MessagingImageMessage isolatedMessage = ownGroup.getIsolatedMessage();
+                if (isolatedMessage != null) {
+                    resetTransformedView(isolatedMessage);
+                }
                 setClippingDeactivated(ownGroup.getAvatar(), false);
                 setClippingDeactivated(ownGroup.getSenderView(), false);
                 ownGroup.setTranslationY(0);
                 ownGroup.getMessageContainer().setTranslationY(0);
             }
+            ownGroup.setTransformingImages(false);
+            ownGroup.updateClipRect();
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/TransformState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/TransformState.java
index 918b6ed..fc8ceb6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/TransformState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/TransformState.java
@@ -26,6 +26,7 @@
 import android.widget.ProgressBar;
 import android.widget.TextView;
 
+import com.android.internal.widget.MessagingImageMessage;
 import com.android.internal.widget.MessagingPropertyAnimator;
 import com.android.internal.widget.ViewClippingUtil;
 import com.android.systemui.Interpolators;
@@ -80,7 +81,7 @@
     private boolean mSameAsAny;
     private float mTransformationEndY = UNDEFINED;
     private float mTransformationEndX = UNDEFINED;
-    private Interpolator mDefaultInterpolator = Interpolators.FAST_OUT_SLOW_IN;
+    protected Interpolator mDefaultInterpolator = Interpolators.FAST_OUT_SLOW_IN;
 
     public void initFrom(View view, TransformInfo transformInfo) {
         mTransformedView = view;
@@ -131,7 +132,7 @@
         transformViewFrom(otherState, TRANSFORM_Y, null, transformationAmount);
     }
 
-    private void transformViewFrom(TransformState otherState, int transformationFlags,
+    protected void transformViewFrom(TransformState otherState, int transformationFlags,
             ViewTransformationHelper.CustomTransformation customTransformation,
             float transformationAmount) {
         final View transformedView = mTransformedView;
@@ -449,6 +450,11 @@
             result.initFrom(view, transformInfo);
             return result;
         }
+        if (view instanceof MessagingImageMessage) {
+            MessagingImageTransformState result = MessagingImageTransformState.obtain();
+            result.initFrom(view, transformInfo);
+            return result;
+        }
         if (view instanceof ImageView) {
             ImageTransformState result = ImageTransformState.obtain();
             result.initFrom(view, transformInfo);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
new file mode 100644
index 0000000..aba5cdf
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
@@ -0,0 +1,446 @@
+/*
+ * 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.phone;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v4.util.ArraySet;
+import android.util.Log;
+import android.util.Pools;
+import android.view.View;
+import android.view.ViewTreeObserver;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.systemui.Dumpable;
+import com.android.systemui.statusbar.ExpandableNotificationRow;
+import com.android.systemui.statusbar.NotificationData;
+import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.notification.VisualStabilityManager;
+import com.android.systemui.statusbar.policy.HeadsUpManager;
+import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.HashSet;
+import java.util.Stack;
+
+/**
+ * A implementation of HeadsUpManager for phone and car.
+ */
+public class HeadsUpManagerPhone extends HeadsUpManager implements Dumpable,
+       ViewTreeObserver.OnComputeInternalInsetsListener, VisualStabilityManager.Callback,
+       OnHeadsUpChangedListener {
+    private static final String TAG = "HeadsUpManagerPhone";
+    private static final boolean DEBUG = false;
+
+    private final View mStatusBarWindowView;
+    private final int mStatusBarHeight;
+    private final NotificationGroupManager mGroupManager;
+    private final StatusBar mBar;
+    private final VisualStabilityManager mVisualStabilityManager;
+
+    private boolean mReleaseOnExpandFinish;
+    private boolean mTrackingHeadsUp;
+    private HashSet<String> mSwipedOutKeys = new HashSet<>();
+    private HashSet<NotificationData.Entry> mEntriesToRemoveAfterExpand = new HashSet<>();
+    private ArraySet<NotificationData.Entry> mEntriesToRemoveWhenReorderingAllowed
+            = new ArraySet<>();
+    private boolean mIsExpanded;
+    private int[] mTmpTwoArray = new int[2];
+    private boolean mHeadsUpGoingAway;
+    private boolean mWaitingOnCollapseWhenGoingAway;
+    private boolean mIsObserving;
+    private int mStatusBarState;
+
+    private final Pools.Pool<HeadsUpEntryPhone> mEntryPool = new Pools.Pool<HeadsUpEntryPhone>() {
+        private Stack<HeadsUpEntryPhone> mPoolObjects = new Stack<>();
+
+        @Override
+        public HeadsUpEntryPhone acquire() {
+            if (!mPoolObjects.isEmpty()) {
+                return mPoolObjects.pop();
+            }
+            return new HeadsUpEntryPhone();
+        }
+
+        @Override
+        public boolean release(@NonNull HeadsUpEntryPhone instance) {
+            mPoolObjects.push(instance);
+            return true;
+        }
+    };
+
+    ///////////////////////////////////////////////////////////////////////////////////////////////
+    //  Constructor:
+
+    public HeadsUpManagerPhone(@NonNull final Context context, @NonNull View statusBarWindowView,
+            @NonNull NotificationGroupManager groupManager, @NonNull StatusBar bar,
+            @NonNull VisualStabilityManager visualStabilityManager) {
+        super(context);
+
+        mStatusBarWindowView = statusBarWindowView;
+        mGroupManager = groupManager;
+        mBar = bar;
+        mVisualStabilityManager = visualStabilityManager;
+
+        Resources resources = mContext.getResources();
+        mStatusBarHeight = resources.getDimensionPixelSize(
+                com.android.internal.R.dimen.status_bar_height);
+
+        addListener(new OnHeadsUpChangedListener() {
+            @Override
+            public void onHeadsUpPinnedModeChanged(boolean hasPinnedNotification) {
+                if (DEBUG) Log.w(TAG, "onHeadsUpPinnedModeChanged");
+                updateTouchableRegionListener();
+            }
+        });
+    }
+
+    ///////////////////////////////////////////////////////////////////////////////////////////////
+    //  Public methods:
+
+    /**
+     * Decides whether a click is invalid for a notification, i.e it has not been shown long enough
+     * that a user might have consciously clicked on it.
+     *
+     * @param key the key of the touched notification
+     * @return whether the touch is invalid and should be discarded
+     */
+    public boolean shouldSwallowClick(@NonNull String key) {
+        HeadsUpManager.HeadsUpEntry entry = getHeadsUpEntry(key);
+        return entry != null && mClock.currentTimeMillis() < entry.postTime;
+    }
+
+    public void onExpandingFinished() {
+        if (mReleaseOnExpandFinish) {
+            releaseAllImmediately();
+            mReleaseOnExpandFinish = false;
+        } else {
+            for (NotificationData.Entry entry : mEntriesToRemoveAfterExpand) {
+                if (isHeadsUp(entry.key)) {
+                    // Maybe the heads-up was removed already
+                    removeHeadsUpEntry(entry);
+                }
+            }
+        }
+        mEntriesToRemoveAfterExpand.clear();
+    }
+
+    /**
+     * Sets the tracking-heads-up flag. If the flag is true, HeadsUpManager doesn't remove the entry
+     * from the list even after a Heads Up Notification is gone.
+     */
+    public void setTrackingHeadsUp(boolean trackingHeadsUp) {
+        mTrackingHeadsUp = trackingHeadsUp;
+    }
+
+    /**
+     * Notify that the status bar panel gets expanded or collapsed.
+     *
+     * @param isExpanded True to notify expanded, false to notify collapsed.
+     */
+    public void setIsPanelExpanded(boolean isExpanded) {
+        if (isExpanded != mIsExpanded) {
+            mIsExpanded = isExpanded;
+            if (isExpanded) {
+                // make sure our state is sane
+                mWaitingOnCollapseWhenGoingAway = false;
+                mHeadsUpGoingAway = false;
+                updateTouchableRegionListener();
+            }
+        }
+    }
+
+    /**
+     * Set the current state of the statusbar.
+     */
+    public void setStatusBarState(int statusBarState) {
+        mStatusBarState = statusBarState;
+    }
+
+    /**
+     * Set that we are exiting the headsUp pinned mode, but some notifications might still be
+     * animating out. This is used to keep the touchable regions in a sane state.
+     */
+    public void setHeadsUpGoingAway(boolean headsUpGoingAway) {
+        if (headsUpGoingAway != mHeadsUpGoingAway) {
+            mHeadsUpGoingAway = headsUpGoingAway;
+            if (!headsUpGoingAway) {
+                waitForStatusBarLayout();
+            }
+            updateTouchableRegionListener();
+        }
+    }
+
+    /**
+     * Notifies that a remote input textbox in notification gets active or inactive.
+     * @param entry The entry of the target notification.
+     * @param remoteInputActive True to notify active, False to notify inactive.
+     */
+    public void setRemoteInputActive(
+            @NonNull NotificationData.Entry entry, boolean remoteInputActive) {
+        HeadsUpEntryPhone headsUpEntry = getHeadsUpEntryPhone(entry.key);
+        if (headsUpEntry != null && headsUpEntry.remoteInputActive != remoteInputActive) {
+            headsUpEntry.remoteInputActive = remoteInputActive;
+            if (remoteInputActive) {
+                headsUpEntry.removeAutoRemovalCallbacks();
+            } else {
+                headsUpEntry.updateEntry(false /* updatePostTime */);
+            }
+        }
+    }
+
+    @VisibleForTesting
+    public void removeMinimumDisplayTimeForTesting() {
+        mMinimumDisplayTime = 0;
+        mHeadsUpNotificationDecay = 0;
+        mTouchAcceptanceDelay = 0;
+    }
+
+    ///////////////////////////////////////////////////////////////////////////////////////////////
+    //  HeadsUpManager public methods overrides:
+
+    @Override
+    public boolean isTrackingHeadsUp() {
+        return mTrackingHeadsUp;
+    }
+
+    @Override
+    public void snooze() {
+        super.snooze();
+        mReleaseOnExpandFinish = true;
+    }
+
+    /**
+     * React to the removal of the notification in the heads up.
+     *
+     * @return true if the notification was removed and false if it still needs to be kept around
+     * for a bit since it wasn't shown long enough
+     */
+    @Override
+    public boolean removeNotification(@NonNull String key, boolean ignoreEarliestRemovalTime) {
+        if (wasShownLongEnough(key) || ignoreEarliestRemovalTime) {
+            return super.removeNotification(key, ignoreEarliestRemovalTime);
+        } else {
+            HeadsUpEntryPhone entry = getHeadsUpEntryPhone(key);
+            entry.removeAsSoonAsPossible();
+            return false;
+        }
+    }
+
+    public void addSwipedOutNotification(@NonNull String key) {
+        mSwipedOutKeys.add(key);
+    }
+
+    ///////////////////////////////////////////////////////////////////////////////////////////////
+    //  Dumpable overrides:
+
+    @Override
+    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        pw.println("HeadsUpManagerPhone state:");
+        dumpInternal(fd, pw, args);
+    }
+
+    ///////////////////////////////////////////////////////////////////////////////////////////////
+    //  ViewTreeObserver.OnComputeInternalInsetsListener overrides:
+
+    /**
+     * Overridden from TreeObserver.
+     */
+    @Override
+    public void onComputeInternalInsets(ViewTreeObserver.InternalInsetsInfo info) {
+        if (mIsExpanded || mBar.isBouncerShowing()) {
+            // The touchable region is always the full area when expanded
+            return;
+        }
+        if (hasPinnedHeadsUp()) {
+            ExpandableNotificationRow topEntry = getTopEntry().row;
+            if (topEntry.isChildInGroup()) {
+                final ExpandableNotificationRow groupSummary
+                        = mGroupManager.getGroupSummary(topEntry.getStatusBarNotification());
+                if (groupSummary != null) {
+                    topEntry = groupSummary;
+                }
+            }
+            topEntry.getLocationOnScreen(mTmpTwoArray);
+            int minX = mTmpTwoArray[0];
+            int maxX = mTmpTwoArray[0] + topEntry.getWidth();
+            int maxY = topEntry.getIntrinsicHeight();
+
+            info.setTouchableInsets(ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION);
+            info.touchableRegion.set(minX, 0, maxX, maxY);
+        } else if (mHeadsUpGoingAway || mWaitingOnCollapseWhenGoingAway) {
+            info.setTouchableInsets(ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION);
+            info.touchableRegion.set(0, 0, mStatusBarWindowView.getWidth(), mStatusBarHeight);
+        }
+    }
+
+    ///////////////////////////////////////////////////////////////////////////////////////////////
+    //  VisualStabilityManager.Callback overrides:
+
+    @Override
+    public void onReorderingAllowed() {
+        mBar.getNotificationScrollLayout().setHeadsUpGoingAwayAnimationsAllowed(false);
+        for (NotificationData.Entry entry : mEntriesToRemoveWhenReorderingAllowed) {
+            if (isHeadsUp(entry.key)) {
+                // Maybe the heads-up was removed already
+                removeHeadsUpEntry(entry);
+            }
+        }
+        mEntriesToRemoveWhenReorderingAllowed.clear();
+        mBar.getNotificationScrollLayout().setHeadsUpGoingAwayAnimationsAllowed(true);
+    }
+
+    ///////////////////////////////////////////////////////////////////////////////////////////////
+    //  HeadsUpManager utility (protected) methods overrides:
+
+    @Override
+    protected HeadsUpEntry createHeadsUpEntry() {
+        return mEntryPool.acquire();
+    }
+
+    @Override
+    protected void releaseHeadsUpEntry(HeadsUpEntry entry) {
+        entry.reset();
+        mEntryPool.release((HeadsUpEntryPhone) entry);
+    }
+
+    @Override
+    protected boolean shouldHeadsUpBecomePinned(NotificationData.Entry entry) {
+          return mStatusBarState != StatusBarState.KEYGUARD && !mIsExpanded
+                  || super.shouldHeadsUpBecomePinned(entry);
+    }
+
+    @Override
+    protected void dumpInternal(FileDescriptor fd, PrintWriter pw, String[] args) {
+        super.dumpInternal(fd, pw, args);
+        pw.print("  mStatusBarState="); pw.println(mStatusBarState);
+    }
+
+    ///////////////////////////////////////////////////////////////////////////////////////////////
+    //  Private utility methods:
+
+    @Nullable
+    private HeadsUpEntryPhone getHeadsUpEntryPhone(@NonNull String key) {
+        return (HeadsUpEntryPhone) getHeadsUpEntry(key);
+    }
+
+    @Nullable
+    private HeadsUpEntryPhone getTopHeadsUpEntryPhone() {
+        return (HeadsUpEntryPhone) getTopHeadsUpEntry();
+    }
+
+    private boolean wasShownLongEnough(@NonNull String key) {
+        if (mSwipedOutKeys.contains(key)) {
+            // We always instantly dismiss views being manually swiped out.
+            mSwipedOutKeys.remove(key);
+            return true;
+        }
+
+        HeadsUpEntryPhone headsUpEntry = getHeadsUpEntryPhone(key);
+        HeadsUpEntryPhone topEntry = getTopHeadsUpEntryPhone();
+        return headsUpEntry != topEntry || headsUpEntry.wasShownLongEnough();
+    }
+
+    /**
+     * We need to wait on the whole panel to collapse, before we can remove the touchable region
+     * listener.
+     */
+    private void waitForStatusBarLayout() {
+        mWaitingOnCollapseWhenGoingAway = true;
+        mStatusBarWindowView.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
+            @Override
+            public void onLayoutChange(View v, int left, int top, int right, int bottom,
+                    int oldLeft,
+                    int oldTop, int oldRight, int oldBottom) {
+                if (mStatusBarWindowView.getHeight() <= mStatusBarHeight) {
+                    mStatusBarWindowView.removeOnLayoutChangeListener(this);
+                    mWaitingOnCollapseWhenGoingAway = false;
+                    updateTouchableRegionListener();
+                }
+            }
+        });
+    }
+
+    private void updateTouchableRegionListener() {
+        boolean shouldObserve = hasPinnedHeadsUp() || mHeadsUpGoingAway
+                || mWaitingOnCollapseWhenGoingAway;
+        if (shouldObserve == mIsObserving) {
+            return;
+        }
+        if (shouldObserve) {
+            mStatusBarWindowView.getViewTreeObserver().addOnComputeInternalInsetsListener(this);
+            mStatusBarWindowView.requestLayout();
+        } else {
+            mStatusBarWindowView.getViewTreeObserver().removeOnComputeInternalInsetsListener(this);
+        }
+        mIsObserving = shouldObserve;
+    }
+
+    ///////////////////////////////////////////////////////////////////////////////////////////////
+    //  HeadsUpEntryPhone:
+
+    protected class HeadsUpEntryPhone extends HeadsUpManager.HeadsUpEntry {
+        public void setEntry(@NonNull final NotificationData.Entry entry) {
+           Runnable removeHeadsUpRunnable = () -> {
+                if (!mVisualStabilityManager.isReorderingAllowed()) {
+                    mEntriesToRemoveWhenReorderingAllowed.add(entry);
+                    mVisualStabilityManager.addReorderingAllowedCallback(
+                            HeadsUpManagerPhone.this);
+                } else if (!mTrackingHeadsUp) {
+                    removeHeadsUpEntry(entry);
+                } else {
+                    mEntriesToRemoveAfterExpand.add(entry);
+                }
+            };
+
+            super.setEntry(entry, removeHeadsUpRunnable);
+        }
+
+        public boolean wasShownLongEnough() {
+            return earliestRemovaltime < mClock.currentTimeMillis();
+        }
+
+        @Override
+        public void updateEntry(boolean updatePostTime) {
+            super.updateEntry(updatePostTime);
+
+            if (mEntriesToRemoveAfterExpand.contains(entry)) {
+                mEntriesToRemoveAfterExpand.remove(entry);
+            }
+            if (mEntriesToRemoveWhenReorderingAllowed.contains(entry)) {
+                mEntriesToRemoveWhenReorderingAllowed.remove(entry);
+            }
+        }
+
+        @Override
+        public void expanded(boolean expanded) {
+            if (this.expanded == expanded) {
+                return;
+            }
+
+            this.expanded = expanded;
+            if (expanded) {
+                removeAutoRemovalCallbacks();
+            } else {
+                updateEntry(false /* updatePostTime */);
+            }
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java
index c85571c..2bfdefe 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java
@@ -23,7 +23,7 @@
 import com.android.systemui.Gefingerpoken;
 import com.android.systemui.statusbar.ExpandableNotificationRow;
 import com.android.systemui.statusbar.ExpandableView;
-import com.android.systemui.statusbar.policy.HeadsUpManager;
+import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
 import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
 
 /**
@@ -31,7 +31,7 @@
  */
 public class HeadsUpTouchHelper implements Gefingerpoken {
 
-    private HeadsUpManager mHeadsUpManager;
+    private HeadsUpManagerPhone mHeadsUpManager;
     private NotificationStackScrollLayout mStackScroller;
     private int mTrackingPointer;
     private float mTouchSlop;
@@ -43,7 +43,7 @@
     private NotificationPanelView mPanel;
     private ExpandableNotificationRow mPickedChild;
 
-    public HeadsUpTouchHelper(HeadsUpManager headsUpManager,
+    public HeadsUpTouchHelper(HeadsUpManagerPhone headsUpManager,
             NotificationStackScrollLayout stackScroller,
             NotificationPanelView notificationPanelView) {
         mHeadsUpManager = headsUpManager;
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..79c605e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
@@ -19,6 +19,7 @@
 import static android.app.StatusBarManager.WINDOW_STATE_SHOWING;
 import static android.app.StatusBarManager.windowStateToString;
 
+import static com.android.systemui.shared.system.NavigationBarCompat.InteractionType;
 import static com.android.systemui.statusbar.phone.BarTransitions.MODE_SEMI_TRANSPARENT;
 import static com.android.systemui.statusbar.phone.StatusBar.DEBUG_WINDOW_STATE;
 import static com.android.systemui.statusbar.phone.StatusBar.dumpBarTransitions;
@@ -71,7 +72,6 @@
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityManager;
 import android.view.accessibility.AccessibilityManager.AccessibilityServicesStateChangeListener;
-import android.widget.Button;
 
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
@@ -114,8 +114,6 @@
     /** Allow some time inbetween the long press for back and recents. */
     private static final int LOCK_TO_APP_GESTURE_TOLERENCE = 200;
 
-    private static final int BUTTON_FADE_IN_OUT_DURATION_MS = 100;
-
     protected NavigationBarView mNavigationBarView = null;
     protected AssistManager mAssistManager;
 
@@ -152,7 +150,7 @@
     private RotationLockController mRotationLockController;
     private TaskStackListenerImpl mTaskStackListener;
 
-    private final Runnable mRemoveRotationProposal = () -> setRotateSuggestionButtonState(false);
+    private final Runnable mRemoveRotationProposal = () -> safeSetRotationButtonState(false);
     private Animator mRotateShowAnimator;
     private Animator mRotateHideAnimator;
 
@@ -167,6 +165,11 @@
         public void onRecentsAnimationStarted() {
             mNavigationBarView.setRecentsAnimationStarted(true);
         }
+
+        @Override
+        public void onInteractionFlagsChanged(@InteractionType int flags) {
+            mNavigationBarView.updateStates();
+        }
     };
 
     // ----- Fragment Lifecycle Callbacks -----
@@ -361,22 +364,32 @@
         // rotate button if shown.
 
         if (!isValid) {
-            setRotateSuggestionButtonState(false);
+            safeSetRotationButtonState(false);
             return;
         }
 
         if (rotation == mWindowManager.getDefaultDisplay().getRotation()) {
             // Use this as a signal to remove any current suggestions
             getView().getHandler().removeCallbacks(mRemoveRotationProposal);
-            setRotateSuggestionButtonState(false);
+            safeSetRotationButtonState(false);
         } else {
             mLastRotationSuggestion = rotation; // Remember rotation for click
-            setRotateSuggestionButtonState(true);
+            safeSetRotationButtonState(true);
             rescheduleRotationTimeout(false);
             mMetricsLogger.visible(MetricsEvent.ROTATION_SUGGESTION_SHOWN);
         }
     }
 
+    private void safeSetRotationButtonState(boolean vis) {
+        if (mNavigationBarView != null) mNavigationBarView.setRotateSuggestionButtonState(vis);
+    }
+
+    private void safeSetRotationButtonState(boolean vis, boolean force) {
+        if (mNavigationBarView != null) {
+            mNavigationBarView.setRotateSuggestionButtonState(vis, force);
+        }
+    }
+
     private void rescheduleRotationTimeout(final boolean reasonHover) {
         // May be called due to a new rotation proposal or a change in hover state
         if (reasonHover) {
@@ -402,84 +415,6 @@
         return 6000;
     }
 
-    public void setRotateSuggestionButtonState(final boolean visible) {
-        setRotateSuggestionButtonState(visible, false);
-    }
-
-    public void setRotateSuggestionButtonState(final boolean visible, final boolean skipAnim) {
-        ButtonDispatcher rotBtn = mNavigationBarView.getRotateSuggestionButton();
-        final boolean currentlyVisible = rotBtn.getVisibility() == View.VISIBLE;
-
-        // Rerun a show animation to indicate change but don't rerun a hide animation
-        if (!visible && !currentlyVisible) return;
-
-        View currentView = rotBtn.getCurrentView();
-        if (currentView == null) return;
-
-        KeyButtonDrawable kbd = rotBtn.getImageDrawable();
-        if (kbd == null) return;
-
-        AnimatedVectorDrawable animIcon = null;
-        if (kbd.getDrawable(0) instanceof AnimatedVectorDrawable) {
-            animIcon = (AnimatedVectorDrawable) kbd.getDrawable(0);
-        }
-
-        if (visible) { // Appear and change
-            rotBtn.setVisibility(View.VISIBLE);
-            mNavigationBarView.notifySubtreeAccessibilityStateChangedIfNeeded();
-
-            if (skipAnim) {
-                currentView.setAlpha(1f);
-                return;
-            }
-
-            // Start a new animation if running
-            if (mRotateShowAnimator != null) mRotateShowAnimator.pause();
-            if (mRotateHideAnimator != null) mRotateHideAnimator.pause();
-
-            ObjectAnimator appearFade = ObjectAnimator.ofFloat(currentView, "alpha",
-                    0f, 1f);
-            appearFade.setDuration(BUTTON_FADE_IN_OUT_DURATION_MS);
-            appearFade.setInterpolator(Interpolators.LINEAR);
-            mRotateShowAnimator = appearFade;
-            appearFade.start();
-
-            // Run the rotate icon's animation if it has one
-            if (animIcon != null) {
-                animIcon.reset();
-                animIcon.start();
-            }
-
-        } else { // Hide
-
-            if (skipAnim) {
-                rotBtn.setVisibility(View.INVISIBLE);
-                mNavigationBarView.notifySubtreeAccessibilityStateChangedIfNeeded();
-                return;
-            }
-
-            // Don't start any new hide animations if one is running
-            if (mRotateHideAnimator != null && mRotateHideAnimator.isRunning()) return;
-            // Pause any active show animations but don't reset the AVD to avoid jumps
-            if (mRotateShowAnimator != null) mRotateShowAnimator.pause();
-
-            ObjectAnimator fadeOut = ObjectAnimator.ofFloat(currentView, "alpha",
-                    0f);
-            fadeOut.setDuration(BUTTON_FADE_IN_OUT_DURATION_MS);
-            fadeOut.setInterpolator(Interpolators.LINEAR);
-            fadeOut.addListener(new AnimatorListenerAdapter() {
-                @Override
-                public void onAnimationEnd(Animator animation) {
-                    rotBtn.setVisibility(View.INVISIBLE);
-                    mNavigationBarView.notifySubtreeAccessibilityStateChangedIfNeeded();
-                }
-            });
-
-            mRotateHideAnimator = fadeOut;
-            fadeOut.start();
-        }
-    }
-
     // Injected from StatusBar at creation.
     public void setCurrentSysuiVisibility(int systemUiVisibility) {
         mSystemUiVisibility = systemUiVisibility;
@@ -892,7 +827,7 @@
                     if (shouldOverrideUserLockPrefs(rotation)) {
                         mRotationLockController.setRotationLockedAtAngle(true, rotation);
                     }
-                    setRotateSuggestionButtonState(false, true);
+                    safeSetRotationButtonState(false, true);
                 }
 
                 if (mNavigationBarView != null
@@ -928,22 +863,22 @@
 
         @Override
         public void onTaskStackChanged() {
-            setRotateSuggestionButtonState(false);
+            safeSetRotationButtonState(false);
         }
 
         @Override
         public void onTaskRemoved(int taskId) {
-            setRotateSuggestionButtonState(false);
+            safeSetRotationButtonState(false);
         }
 
         @Override
         public void onTaskMovedToFront(int taskId) {
-            setRotateSuggestionButtonState(false);
+            safeSetRotationButtonState(false);
         }
 
         @Override
         public void onActivityRequestedOrientationChanged(int taskId, int requestedOrientation) {
-            setRotateSuggestionButtonState(false);
+            safeSetRotationButtonState(false);
         }
     }
 
@@ -960,6 +895,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/NavigationBarGestureHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java
index 0d36efd..4454ef9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java
@@ -16,6 +16,12 @@
 
 package com.android.systemui.statusbar.phone;
 
+import static android.view.WindowManager.DOCKED_INVALID;
+import static android.view.WindowManager.DOCKED_LEFT;
+import static android.view.WindowManager.DOCKED_TOP;
+import static com.android.systemui.OverviewProxyService.DEBUG_OVERVIEW_PROXY;
+import static com.android.systemui.OverviewProxyService.TAG_OPS;
+
 import android.app.ActivityManager;
 import android.content.Context;
 import android.content.res.Resources;
@@ -27,26 +33,19 @@
 import android.view.MotionEvent;
 import android.view.VelocityTracker;
 import android.view.View;
-
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.internal.policy.DividerSnapAlgorithm.SnapTarget;
 import com.android.systemui.Dependency;
 import com.android.systemui.OverviewProxyService;
+import com.android.systemui.OverviewProxyService.OverviewProxyListener;
 import com.android.systemui.R;
 import com.android.systemui.RecentsComponent;
 import com.android.systemui.SysUiServiceProvider;
 import com.android.systemui.plugins.statusbar.phone.NavGesture.GestureHelper;
 import com.android.systemui.shared.recents.IOverviewProxy;
-import com.android.systemui.shared.recents.utilities.Utilities;
 import com.android.systemui.stackdivider.Divider;
 import com.android.systemui.tuner.TunerService;
 
-import static android.view.WindowManager.DOCKED_INVALID;
-import static android.view.WindowManager.DOCKED_LEFT;
-import static android.view.WindowManager.DOCKED_TOP;
-import static com.android.systemui.OverviewProxyService.DEBUG_OVERVIEW_PROXY;
-import static com.android.systemui.OverviewProxyService.TAG_OPS;
-
 /**
  * Class to detect gestures on the navigation bar.
  */
@@ -84,8 +83,16 @@
     private int mTouchDownY;
     private boolean mDownOnRecents;
     private VelocityTracker mVelocityTracker;
-    private OverviewProxyService mOverviewEventSender = Dependency.get(OverviewProxyService.class);
+    private OverviewProxyService mOverviewProxyService = Dependency.get(OverviewProxyService.class);
+    private final OverviewProxyListener mOverviewProxyListener = new OverviewProxyListener() {
+        @Override
+        public void onRecentsAnimationStarted() {
+            mRecentsAnimationStarted = true;
+            mQuickScrubController.cancelQuickSwitch();
+        }
+    };
 
+    private boolean mRecentsAnimationStarted;
     private boolean mDockWindowEnabled;
     private boolean mDockWindowTouchSlopExceeded;
     private int mDragMode;
@@ -97,10 +104,12 @@
         mScrollTouchSlop = r.getDimensionPixelSize(R.dimen.navigation_bar_min_swipe_distance);
         mQuickScrubController = new QuickScrubController(context);
         Dependency.get(TunerService.class).addTunable(this, KEY_DOCK_WINDOW_GESTURE);
+        mOverviewProxyService.addCallback(mOverviewProxyListener);
     }
 
     public void destroy() {
         Dependency.get(TunerService.class).removeTunable(this);
+        mOverviewProxyService.removeCallback(mOverviewProxyListener);
     }
 
     public void setComponents(RecentsComponent recentsComponent, Divider divider,
@@ -117,11 +126,14 @@
     }
 
     private boolean proxyMotionEvents(MotionEvent event) {
-        final IOverviewProxy overviewProxy = mOverviewEventSender.getProxy();
-        if (overviewProxy != null) {
+        final IOverviewProxy overviewProxy = mOverviewProxyService.getProxy();
+        if (overviewProxy != null && mNavigationBarView.isQuickStepSwipeUpEnabled()) {
             mNavigationBarView.requestUnbufferedDispatch(event);
             event.transform(mTransformGlobalMatrix);
             try {
+                if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
+                    overviewProxy.onPreMotionEvent(mNavigationBarView.getDownHitTarget());
+                }
                 overviewProxy.onMotionEvent(event);
                 if (DEBUG_OVERVIEW_PROXY) {
                     Log.d(TAG_OPS, "Send MotionEvent: " + event.toString());
@@ -137,8 +149,12 @@
     }
 
     public boolean onInterceptTouchEvent(MotionEvent event) {
-        int action = event.getAction();
-        switch (action & MotionEvent.ACTION_MASK) {
+        if (mNavigationBarView.inScreenPinning()) {
+            return false;
+        }
+
+        int action = event.getActionMasked();
+        switch (action) {
             case MotionEvent.ACTION_DOWN: {
                 mTouchDownX = (int) event.getX();
                 mTouchDownY = (int) event.getY();
@@ -146,19 +162,45 @@
                 mTransformLocalMatrix.set(Matrix.IDENTITY_MATRIX);
                 mNavigationBarView.transformMatrixToGlobal(mTransformGlobalMatrix);
                 mNavigationBarView.transformMatrixToLocal(mTransformLocalMatrix);
+                mRecentsAnimationStarted = false;
                 break;
             }
         }
-        if (mStatusBar.isPresenterFullyCollapsed()
-                && !mQuickScrubController.onInterceptTouchEvent(event)) {
+        boolean handledByQuickscrub = mQuickScrubController.onInterceptTouchEvent(event);
+        if (mStatusBar.isPresenterFullyCollapsed() && !handledByQuickscrub) {
+            // Proxy motion events until we start intercepting for quickscrub
             proxyMotionEvents(event);
+        }
+
+        boolean result = handledByQuickscrub;
+        result |= mRecentsAnimationStarted;
+        if (mDockWindowEnabled) {
+            result |= interceptDockWindowEvent(event);
+        }
+        return result;
+    }
+
+    public boolean onTouchEvent(MotionEvent event) {
+        if (mNavigationBarView.inScreenPinning()) {
             return false;
         }
-        return (mDockWindowEnabled && interceptDockWindowEvent(event));
+
+        // The same down event was just sent on intercept and therefore can be ignored here
+        boolean ignoreProxyDownEvent = event.getAction() == MotionEvent.ACTION_DOWN
+                && mOverviewProxyService.getProxy() != null;
+        boolean result = mStatusBar.isPresenterFullyCollapsed()
+                && (mQuickScrubController.onTouchEvent(event)
+                || ignoreProxyDownEvent
+                || proxyMotionEvents(event));
+        result |= mRecentsAnimationStarted;
+        if (mDockWindowEnabled) {
+            result |= handleDockWindowEvent(event);
+        }
+        return result;
     }
 
     public void onDraw(Canvas canvas) {
-        if (mOverviewEventSender.getProxy() != null) {
+        if (mNavigationBarView.isQuickScrubEnabled()) {
             mQuickScrubController.onDraw(canvas);
         }
     }
@@ -307,20 +349,6 @@
         return DRAG_MODE_RECENTS;
     }
 
-    public boolean onTouchEvent(MotionEvent event) {
-        // The same down event was just sent on intercept and therefore can be ignored here
-        boolean ignoreProxyDownEvent = event.getAction() == MotionEvent.ACTION_DOWN
-                && mOverviewEventSender.getProxy() != null;
-        boolean result = mStatusBar.isPresenterFullyCollapsed()
-                && (mQuickScrubController.onTouchEvent(event)
-                || ignoreProxyDownEvent
-                || proxyMotionEvents(event));
-        if (mDockWindowEnabled) {
-            result |= handleDockWindowEvent(event);
-        }
-        return result;
-    }
-
     @Override
     public void onTuningChanged(String key, String newValue) {
         switch (key) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
index 9d20e4e..9894235 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
@@ -57,13 +57,12 @@
     public static final String NAV_BAR_LEFT = "sysui_nav_bar_left";
     public static final String NAV_BAR_RIGHT = "sysui_nav_bar_right";
 
-    public static final String MENU_IME = "menu_ime";
+    public static final String MENU_IME_ROTATE = "menu_ime";
     public static final String BACK = "back";
     public static final String HOME = "home";
     public static final String RECENT = "recent";
     public static final String NAVSPACE = "space";
     public static final String CLIPBOARD = "clipboard";
-    public static final String ROTATE = "rotate";
     public static final String KEY = "key";
     public static final String LEFT = "left";
     public static final String RIGHT = "right";
@@ -317,10 +316,10 @@
         View v = null;
         String button = extractButton(buttonSpec);
         if (LEFT.equals(button)) {
-            String s = Dependency.get(TunerService.class).getValue(NAV_BAR_LEFT, ROTATE);
+            String s = Dependency.get(TunerService.class).getValue(NAV_BAR_LEFT, NAVSPACE);
             button = extractButton(s);
         } else if (RIGHT.equals(button)) {
-            String s = Dependency.get(TunerService.class).getValue(NAV_BAR_RIGHT, MENU_IME);
+            String s = Dependency.get(TunerService.class).getValue(NAV_BAR_RIGHT, MENU_IME_ROTATE);
             button = extractButton(s);
         }
         // Let plugins go first so they can override a standard view if they want.
@@ -334,14 +333,12 @@
             v = inflater.inflate(R.layout.back, parent, false);
         } else if (RECENT.equals(button)) {
             v = inflater.inflate(R.layout.recent_apps, parent, false);
-        } else if (MENU_IME.equals(button)) {
+        } else if (MENU_IME_ROTATE.equals(button)) {
             v = inflater.inflate(R.layout.menu_ime, parent, false);
         } else if (NAVSPACE.equals(button)) {
             v = inflater.inflate(R.layout.nav_key_space, parent, false);
         } else if (CLIPBOARD.equals(button)) {
             v = inflater.inflate(R.layout.clipboard, parent, false);
-        } else if (ROTATE.equals(button)) {
-            v = inflater.inflate(R.layout.rotate_suggestion, parent, false);
         } else if (button.startsWith(KEY)) {
             String uri = extractImage(button);
             int code = extractKeycode(button);
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 c37dd55..285980b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -16,6 +16,13 @@
 
 package com.android.systemui.statusbar.phone;
 
+import static android.view.MotionEvent.ACTION_DOWN;
+import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_BACK;
+import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_HOME;
+import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_NONE;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
 import android.animation.LayoutTransition;
 import android.animation.LayoutTransition.TransitionListener;
 import android.animation.ObjectAnimator;
@@ -29,9 +36,11 @@
 import android.graphics.Canvas;
 import android.graphics.Point;
 import android.graphics.Rect;
+import android.graphics.drawable.AnimatedVectorDrawable;
 import android.os.Handler;
 import android.os.Message;
 import android.os.RemoteException;
+import android.os.SystemProperties;
 import android.support.annotation.ColorInt;
 import android.util.AttributeSet;
 import android.util.Log;
@@ -49,15 +58,17 @@
 import com.android.settingslib.Utils;
 import com.android.systemui.Dependency;
 import com.android.systemui.DockedStackExistsListener;
+import com.android.systemui.Interpolators;
 import com.android.systemui.OverviewProxyService;
-import com.android.systemui.OverviewProxyService.OverviewProxyListener;
 import com.android.systemui.R;
 import com.android.systemui.RecentsComponent;
 import com.android.systemui.plugins.PluginListener;
 import com.android.systemui.plugins.PluginManager;
 import com.android.systemui.plugins.statusbar.phone.NavGesture;
 import com.android.systemui.plugins.statusbar.phone.NavGesture.GestureHelper;
-import com.android.systemui.recents.SwipeUpOnboarding;
+import com.android.systemui.recents.RecentsOnboarding;
+import com.android.systemui.shared.system.ActivityManagerWrapper;
+import com.android.systemui.shared.system.NavigationBarCompat;
 import com.android.systemui.stackdivider.Divider;
 import com.android.systemui.statusbar.policy.DeadZone;
 import com.android.systemui.statusbar.policy.KeyButtonDrawable;
@@ -67,10 +78,17 @@
 import java.io.PrintWriter;
 import java.util.function.Consumer;
 
+import static com.android.systemui.shared.system.NavigationBarCompat.FLAG_DISABLE_QUICK_SCRUB;
+import static com.android.systemui.shared.system.NavigationBarCompat.FLAG_DISABLE_SWIPE_UP;
+import static com.android.systemui.shared.system.NavigationBarCompat.FLAG_HIDE_BACK_BUTTON;
+import static com.android.systemui.shared.system.NavigationBarCompat.FLAG_SHOW_OVERVIEW_BUTTON;
+
 public class NavigationBarView extends FrameLayout implements PluginListener<NavGesture> {
     final static boolean DEBUG = false;
     final static String TAG = "StatusBar/NavBarView";
 
+    final static int BUTTON_FADE_IN_OUT_DURATION_MS = 100;
+
     // slippery nav bar when everything is disabled, e.g. during setup
     final static boolean SLIPPERY_WHEN_DISABLED = true;
 
@@ -86,9 +104,15 @@
     boolean mShowMenu;
     boolean mShowAccessibilityButton;
     boolean mLongClickableAccessibilityButton;
+    boolean mShowRotateButton;
     int mDisabledFlags = 0;
     int mNavigationIconHints = 0;
 
+    private @NavigationBarCompat.HitTarget int mDownHitTarget = HIT_TARGET_NONE;
+    private Rect mHomeButtonBounds = new Rect();
+    private Rect mBackButtonBounds = new Rect();
+    private int[] mTmpPosition = new int[2];
+
     private KeyButtonDrawable mBackIcon, mBackLandIcon, mBackAltIcon, mBackAltLandIcon;
     private KeyButtonDrawable mBackCarModeIcon, mBackLandCarModeIcon;
     private KeyButtonDrawable mBackAltCarModeIcon, mBackAltLandCarModeIcon;
@@ -104,7 +128,6 @@
     private DeadZone mDeadZone;
     private final NavigationBarTransitions mBarTransitions;
     private final OverviewProxyService mOverviewProxyService;
-    private boolean mRecentsAnimationStarted;
 
     // workaround for LayoutTransitions leaving the nav buttons in a weird state (bug 5549288)
     final static boolean WORKAROUND_INVALID_LAYOUT = true;
@@ -126,9 +149,11 @@
     private NavigationBarInflaterView mNavigationInflaterView;
     private RecentsComponent mRecentsComponent;
     private Divider mDivider;
-    private SwipeUpOnboarding mSwipeUpOnboarding;
+    private RecentsOnboarding mRecentsOnboarding;
     private NotificationPanelView mPanelView;
 
+    private Animator mRotateHideAnimator;
+
     private class NavTransitionListener implements TransitionListener {
         private boolean mBackTransitioning;
         private boolean mHomeAppearing;
@@ -219,6 +244,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);
@@ -234,9 +262,6 @@
                 new ButtonDispatcher(R.id.accessibility_button));
         mButtonDispatchers.put(R.id.rotate_suggestion,
                 new ButtonDispatcher(R.id.rotate_suggestion));
-
-        mOverviewProxyService = Dependency.get(OverviewProxyService.class);
-        mSwipeUpOnboarding = new SwipeUpOnboarding(context);
     }
 
     public BarTransitions getBarTransitions() {
@@ -264,9 +289,8 @@
     }
 
     public void setRecentsAnimationStarted(boolean started) {
-        mRecentsAnimationStarted = started;
-        if (mSwipeUpOnboarding != null) {
-            mSwipeUpOnboarding.onRecentsAnimationStarted();
+        if (mRecentsOnboarding != null) {
+            mRecentsOnboarding.onRecentsAnimationStarted();
         }
     }
 
@@ -277,30 +301,32 @@
     }
 
     @Override
+    public boolean onInterceptTouchEvent(MotionEvent event) {
+        switch (event.getActionMasked()) {
+            case ACTION_DOWN:
+                int x = (int) event.getX();
+                int y = (int) event.getY();
+                mDownHitTarget = HIT_TARGET_NONE;
+                if (mBackButtonBounds.contains(x, y)) {
+                    mDownHitTarget = HIT_TARGET_BACK;
+                } else if (mHomeButtonBounds.contains(x, y)) {
+                    mDownHitTarget = HIT_TARGET_HOME;
+                }
+                break;
+        }
+        return mGestureHelper.onInterceptTouchEvent(event);
+    }
+
+    @Override
     public boolean onTouchEvent(MotionEvent event) {
         if (mGestureHelper.onTouchEvent(event)) {
             return true;
         }
-        return mRecentsAnimationStarted || super.onTouchEvent(event);
+        return super.onTouchEvent(event);
     }
 
-    @Override
-    public boolean onInterceptTouchEvent(MotionEvent event) {
-        int action = event.getActionMasked();
-        if (action == MotionEvent.ACTION_DOWN) {
-            mRecentsAnimationStarted = false;
-        } else if (action == MotionEvent.ACTION_UP) {
-            // If the overview proxy service has not started the recents animation then clean up
-            // after it to ensure that the nav bar buttons still work
-            if (mOverviewProxyService.getProxy() != null && !mRecentsAnimationStarted) {
-                try {
-                    ActivityManager.getService().cancelRecentsAnimation();
-                } catch (RemoteException e) {
-                    Log.e(TAG, "Could not cancel recents animation");
-                }
-            }
-        }
-        return mGestureHelper.onInterceptTouchEvent(event) || mRecentsAnimationStarted;
+    public @NavigationBarCompat.HitTarget int getDownHitTarget() {
+        return mDownHitTarget;
     }
 
     public void abortCurrentGesture() {
@@ -353,6 +379,19 @@
         return getRecentsButton().getVisibility() == View.VISIBLE;
     }
 
+    public boolean isQuickStepSwipeUpEnabled() {
+        return mOverviewProxyService.getProxy() != null
+                && ((mOverviewProxyService.getInteractionFlags()
+                        & FLAG_DISABLE_SWIPE_UP) == 0);
+    }
+
+    public boolean isQuickScrubEnabled() {
+        return SystemProperties.getBoolean("persist.quickstep.scrub.enabled", true)
+                && mOverviewProxyService.getProxy() != null && !isRecentsButtonVisible()
+                && ((mOverviewProxyService.getInteractionFlags()
+                        & FLAG_DISABLE_QUICK_SCRUB) == 0);
+    }
+
     private void updateCarModeIcons(Context ctx) {
         mBackCarModeIcon = getDrawable(ctx,
                 R.drawable.ic_sysbar_back_carmode, R.drawable.ic_sysbar_back_carmode);
@@ -369,17 +408,14 @@
                 || oldConfig.densityDpi != newConfig.densityDpi) {
             mDockedIcon = getDrawable(ctx,
                     R.drawable.ic_sysbar_docked, R.drawable.ic_sysbar_docked_dark);
+            mHomeDefaultIcon = getHomeDrawable(ctx);
         }
         if (oldConfig.densityDpi != newConfig.densityDpi
                 || oldConfig.getLayoutDirection() != newConfig.getLayoutDirection()) {
-            mBackIcon = getDrawable(ctx, R.drawable.ic_sysbar_back, R.drawable.ic_sysbar_back_dark);
+            mBackIcon = getBackDrawable(ctx);
             mBackLandIcon = mBackIcon;
-            mBackAltIcon = getDrawable(ctx,
-                    R.drawable.ic_sysbar_back_ime, R.drawable.ic_sysbar_back_ime_dark);
+            mBackAltIcon = getBackImeDrawable(ctx);
             mBackAltLandIcon = mBackAltIcon;
-
-            mHomeDefaultIcon = 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);
@@ -404,6 +440,33 @@
         }
     }
 
+    public KeyButtonDrawable getBackDrawable(Context ctx) {
+        return chooseNavigationIconDrawable(ctx, R.drawable.ic_sysbar_back,
+                R.drawable.ic_sysbar_back_dark, R.drawable.ic_sysbar_back_quick_step,
+                R.drawable.ic_sysbar_back_quick_step_dark);
+    }
+
+    public KeyButtonDrawable getBackImeDrawable(Context ctx) {
+        return chooseNavigationIconDrawable(ctx, R.drawable.ic_sysbar_back_ime,
+                R.drawable.ic_sysbar_back_ime_dark, R.drawable.ic_sysbar_back_ime_quick_step,
+                R.drawable.ic_sysbar_back_ime_quick_step_dark);
+    }
+
+    public KeyButtonDrawable getHomeDrawable(Context ctx) {
+        return chooseNavigationIconDrawable(ctx, R.drawable.ic_sysbar_home,
+                R.drawable.ic_sysbar_home_dark, R.drawable.ic_sysbar_home_quick_step,
+                R.drawable.ic_sysbar_home_quick_step_dark);
+    }
+
+    private KeyButtonDrawable chooseNavigationIconDrawable(Context ctx, @DrawableRes int iconLight,
+            @DrawableRes int iconDark, @DrawableRes int quickStepIconLight,
+            @DrawableRes int quickStepIconDark) {
+        final boolean quickStepEnabled = isQuickStepSwipeUpEnabled() || isQuickScrubEnabled();
+        return quickStepEnabled
+                ? getDrawable(ctx, quickStepIconLight, quickStepIconDark)
+                : getDrawable(ctx, iconLight, iconDark);
+    }
+
     private KeyButtonDrawable getDrawable(Context ctx, @DrawableRes int lightIcon,
             @DrawableRes int darkIcon) {
         return getDrawable(ctx, ctx, lightIcon, darkIcon);
@@ -479,22 +542,25 @@
             getHomeButton().setImageDrawable(mHomeDefaultIcon);
         }
 
-        // The Accessibility button always overrides the appearance of the IME switcher
+        // Update IME button visibility, a11y and rotate button always overrides the appearance
         final boolean showImeButton =
-                !mShowAccessibilityButton && ((hints & StatusBarManager.NAVIGATION_HINT_IME_SHOWN)
-                        != 0);
+                !mShowAccessibilityButton &&
+                !mShowRotateButton &&
+                ((hints & StatusBarManager.NAVIGATION_HINT_IME_SHOWN) != 0);
         getImeSwitchButton().setVisibility(showImeButton ? View.VISIBLE : View.INVISIBLE);
         getImeSwitchButton().setImageDrawable(mImeIcon);
 
-        // Update menu button in case the IME state has changed.
+        // Update menu button, visibility logic in method
         setMenuVisibility(mShowMenu, true);
         getMenuButton().setImageDrawable(mMenuIcon);
 
+        // Update rotate button, visibility altered by a11y button logic
+        getRotateSuggestionButton().setImageDrawable(mRotateSuggestionIcon);
+
+        // Update a11y button, visibility logic in state method
         setAccessibilityButtonState(mShowAccessibilityButton, mLongClickableAccessibilityButton);
         getAccessibilityButton().setImageDrawable(mAccessibilityIcon);
 
-        getRotateSuggestionButton().setImageDrawable(mRotateSuggestionIcon);
-
         setDisabledFlags(mDisabledFlags, true);
 
         mBarTransitions.reapplyDarkIntensity();
@@ -509,7 +575,7 @@
 
         mDisabledFlags = disabledFlags;
 
-        final boolean disableHome = ((disabledFlags & View.STATUS_BAR_DISABLE_HOME) != 0);
+        boolean disableHome = ((disabledFlags & View.STATUS_BAR_DISABLE_HOME) != 0);
 
         // Always disable recents when alternate car mode UI is active.
         boolean disableRecent = mUseCarModeUi
@@ -518,15 +584,21 @@
         boolean disableBack = ((disabledFlags & View.STATUS_BAR_DISABLE_BACK) != 0)
                 && ((mNavigationIconHints & StatusBarManager.NAVIGATION_HINT_BACK_ALT) == 0);
 
-        if ((disableRecent || disableBack) && inScreenPinning()) {
-            // Don't hide back and recents buttons when in screen pinning mode, as they are used for
-            // exiting.
-            disableBack = false;
-            disableRecent = false;
-        }
+        // When screen pinning, don't hide back and home when connected service or back and
+        // recents buttons when disconnected from launcher service in screen pinning mode,
+        // as they are used for exiting.
         if (mOverviewProxyService.getProxy() != null) {
-            // When overview is connected to the launcher service, disable the recents button
-            disableRecent = true;
+            // Use interaction flags to show/hide navigation buttons but will be shown if required
+            // to exit screen pinning.
+            final int flags = mOverviewProxyService.getInteractionFlags();
+            disableRecent |= (flags & FLAG_SHOW_OVERVIEW_BUTTON) == 0;
+            if (inScreenPinning()) {
+                disableBack = disableHome = false;
+            } else {
+                disableBack |= (flags & FLAG_HIDE_BACK_BUTTON) != 0;
+            }
+        } else if (inScreenPinning()) {
+            disableBack = disableRecent = false;
         }
 
         ViewGroup navButtons = (ViewGroup) getCurrentView().findViewById(R.id.nav_buttons);
@@ -544,13 +616,8 @@
         getRecentsButton().setVisibility(disableRecent ? View.INVISIBLE : View.VISIBLE);
     }
 
-    private boolean inScreenPinning() {
-        try {
-            return ActivityManager.getService().getLockTaskModeState()
-                    == ActivityManager.LOCK_TASK_MODE_PINNED;
-        } catch (RemoteException e) {
-            return false;
-        }
+    public boolean inScreenPinning() {
+        return ActivityManagerWrapper.getInstance().isLockToAppActive();
     }
 
     public void setLayoutTransitionsEnabled(boolean enabled) {
@@ -604,6 +671,11 @@
         updateSlippery();
     }
 
+    public void updateStates() {
+        updateSlippery();
+        setDisabledFlags(mDisabledFlags, true);
+    }
+
     private void updateSlippery() {
         setSlippery(mOverviewProxyService.getProxy() != null && mPanelView.isFullyExpanded());
     }
@@ -638,8 +710,10 @@
 
         mShowMenu = show;
 
-        // Only show Menu if IME switcher and Accessibility button not shown.
-        final boolean shouldShow = mShowMenu && !mShowAccessibilityButton &&
+        // Only show Menu if IME switcher, rotate and Accessibility buttons are not shown.
+        final boolean shouldShow = mShowMenu &&
+                !mShowAccessibilityButton &&
+                !mShowRotateButton &&
                 ((mNavigationIconHints & StatusBarManager.NAVIGATION_HINT_IME_SHOWN) == 0);
 
         getMenuButton().setVisibility(shouldShow ? View.VISIBLE : View.INVISIBLE);
@@ -649,15 +723,96 @@
         mShowAccessibilityButton = visible;
         mLongClickableAccessibilityButton = longClickable;
         if (visible) {
-            // Accessibility button overrides Menu and IME switcher buttons.
+            // Accessibility button overrides Menu, IME switcher and rotate buttons.
             setMenuVisibility(false, true);
             getImeSwitchButton().setVisibility(View.INVISIBLE);
+            setRotateSuggestionButtonState(false, true);
         }
 
         getAccessibilityButton().setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
         getAccessibilityButton().setLongClickable(longClickable);
     }
 
+    public void setRotateSuggestionButtonState(final boolean visible) {
+        setRotateSuggestionButtonState(visible, false);
+    }
+
+    public void setRotateSuggestionButtonState(final boolean visible, final boolean force) {
+        ButtonDispatcher rotBtn = getRotateSuggestionButton();
+        final boolean currentlyVisible = mShowRotateButton;
+
+        // Rerun a show animation to indicate change but don't rerun a hide animation
+        if (!visible && !currentlyVisible) return;
+
+        View currentView = rotBtn.getCurrentView();
+        if (currentView == null) return;
+
+        KeyButtonDrawable kbd = rotBtn.getImageDrawable();
+        if (kbd == null) return;
+
+        AnimatedVectorDrawable animIcon = null;
+        if (kbd.getDrawable(0) instanceof AnimatedVectorDrawable) {
+            animIcon = (AnimatedVectorDrawable) kbd.getDrawable(0);
+        }
+
+        if (visible) { // Appear and change, cannot force
+            setRotateButtonVisibility(true);
+
+            // Stop any currently running hide animations
+            if (mRotateHideAnimator != null && mRotateHideAnimator.isRunning()) {
+                mRotateHideAnimator.pause();
+            }
+
+            // Reset the alpha if any has changed due to hide animation
+            currentView.setAlpha(1f);
+
+            // Run the rotate icon's animation if it has one
+            if (animIcon != null) {
+                animIcon.reset();
+                animIcon.start();
+            }
+
+        } else { // Hide
+            if (force) {
+                // If a hide animator is running stop it and instantly make invisible
+                if (mRotateHideAnimator != null && mRotateHideAnimator.isRunning()) {
+                    mRotateHideAnimator.pause();
+                }
+                setRotateButtonVisibility(false);
+                return;
+            }
+
+            // Don't start any new hide animations if one is running
+            if (mRotateHideAnimator != null && mRotateHideAnimator.isRunning()) return;
+
+            ObjectAnimator fadeOut = ObjectAnimator.ofFloat(currentView, "alpha",
+                    0f);
+            fadeOut.setDuration(BUTTON_FADE_IN_OUT_DURATION_MS);
+            fadeOut.setInterpolator(Interpolators.LINEAR);
+            fadeOut.addListener(new AnimatorListenerAdapter() {
+                @Override
+                public void onAnimationEnd(Animator animation) {
+                    setRotateButtonVisibility(false);
+                }
+            });
+
+            mRotateHideAnimator = fadeOut;
+            fadeOut.start();
+        }
+    }
+
+    private void setRotateButtonVisibility(final boolean visible) {
+        // Never show if a11y is visible
+        final boolean adjVisible = visible && !mShowAccessibilityButton;
+        final int vis = adjVisible ? View.VISIBLE : View.INVISIBLE;
+
+        getRotateSuggestionButton().setVisibility(vis);
+        mShowRotateButton = visible;
+
+        // Hide/restore other button visibility, if necessary
+        setNavigationIconHints(mNavigationIconHints, true);
+    }
+
     @Override
     public void onFinishInflate() {
         mNavigationInflaterView = (NavigationBarInflaterView) findViewById(
@@ -674,15 +829,16 @@
         if (mGestureHelper != null) {
             mGestureHelper.onDarkIntensityChange(intensity);
         }
-        if (mSwipeUpOnboarding != null) {
-            mSwipeUpOnboarding.setContentDarkIntensity(intensity);
+        if (mRecentsOnboarding != null) {
+            mRecentsOnboarding.setContentDarkIntensity(intensity);
         }
     }
 
     public void onOverviewProxyConnectionChanged(boolean isConnected) {
-        setSlippery(!isConnected);
-        setDisabledFlags(mDisabledFlags, true);
-        setUpSwipeUpOnboarding(isConnected);
+        updateStates();
+        setUpSwipeUpOnboarding(isQuickStepSwipeUpEnabled());
+        updateIcons(getContext(), Configuration.EMPTY, mConfiguration);
+        setNavigationIconHints(mNavigationIconHints, true);
     }
 
     @Override
@@ -694,9 +850,23 @@
     @Override
     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
         super.onLayout(changed, left, top, right, bottom);
+        updateButtonLocationOnScreen(getBackButton(), mBackButtonBounds);
+        updateButtonLocationOnScreen(getHomeButton(), mHomeButtonBounds);
         mGestureHelper.onLayout(changed, left, top, right, bottom);
     }
 
+    private void updateButtonLocationOnScreen(ButtonDispatcher button, Rect buttonBounds) {
+        View view = button.getCurrentView();
+        if (view == null) {
+            buttonBounds.setEmpty();
+            return;
+        }
+        view.getLocationInWindow(mTmpPosition);
+        buttonBounds.set(mTmpPosition[0], mTmpPosition[1],
+                mTmpPosition[0] + view.getMeasuredWidth(),
+                mTmpPosition[1] + view.getMeasuredHeight());
+    }
+
     private void updateRotatedViews() {
         mRotatedViews[Surface.ROTATION_0] =
                 mRotatedViews[Surface.ROTATION_180] = findViewById(R.id.rot0);
@@ -751,6 +921,11 @@
             Log.d(TAG, "reorient(): rot=" + mCurrentRotation);
         }
 
+        // Resolve layout direction if not resolved since components changing layout direction such
+        // as changing languages will recreate this view and the direction will be resolved later
+        if (!isLayoutDirectionResolved()) {
+            resolveLayoutDirection();
+        }
         updateTaskSwitchHelper();
         setNavigationIconHints(mNavigationIconHints, true);
 
@@ -793,7 +968,7 @@
         updateTaskSwitchHelper();
         updateIcons(getContext(), mConfiguration, newConfig);
         updateRecentsIcon();
-        mSwipeUpOnboarding.onConfigurationChanged(newConfig);
+        mRecentsOnboarding.onConfigurationChanged(newConfig);
         if (uiCarModeChanged || mConfiguration.densityDpi != newConfig.densityDpi
                 || mConfiguration.getLayoutDirection() != newConfig.getLayoutDirection()) {
             // If car mode or density changes, we need to reset the icons.
@@ -897,9 +1072,9 @@
 
     private void setUpSwipeUpOnboarding(boolean connectedToOverviewProxy) {
         if (connectedToOverviewProxy) {
-            mSwipeUpOnboarding.onConnectedToLauncher();
+            mRecentsOnboarding.onConnectedToLauncher();
         } else {
-            mSwipeUpOnboarding.onDisconnectedFromLauncher();
+            mRecentsOnboarding.onDisconnectedFromLauncher();
         }
     }
 
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 cd2e77a..3b129fc 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;
@@ -68,14 +68,12 @@
 import com.android.systemui.statusbar.NotificationShelf;
 import com.android.systemui.statusbar.StatusBarState;
 import com.android.systemui.statusbar.notification.ActivityLaunchAnimator;
-import com.android.systemui.statusbar.policy.HeadsUpManager;
 import com.android.systemui.statusbar.policy.KeyguardUserSwitcher;
 import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
 import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
 import com.android.systemui.statusbar.stack.StackStateAnimator;
 
 import java.util.List;
-import java.util.Collection;
 
 public class NotificationPanelView extends PanelView implements
         ExpandableView.OnHeightChangedListener,
@@ -113,6 +111,7 @@
                 }
             };
     private final PowerManager mPowerManager;
+    private final AccessibilityManager mAccessibilityManager;
 
     private KeyguardAffordanceHelper mAffordanceHelper;
     private KeyguardUserSwitcher mKeyguardUserSwitcher;
@@ -251,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) {
@@ -500,7 +501,8 @@
         float shelfSize = shelf.getVisibility() == GONE ? 0
                 : shelf.getIntrinsicHeight() + notificationPadding;
         float availableSpace = mNotificationStackScroller.getHeight() - minPadding - shelfSize
-                - Math.max(mIndicationBottomPadding, mAmbientIndicationBottomPadding);
+                - Math.max(mIndicationBottomPadding, mAmbientIndicationBottomPadding)
+                - mKeyguardStatusView.getLogoutButtonHeight();
         int count = 0;
         for (int i = 0; i < mNotificationStackScroller.getChildCount(); i++) {
             ExpandableView child = (ExpandableView) mNotificationStackScroller.getChildAt(i);
@@ -663,16 +665,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;
@@ -1302,10 +1294,6 @@
             setQsExpanded(true);
         } else if (height <= mQsMinExpansionHeight && mQsExpanded) {
             setQsExpanded(false);
-            if (mLastAnnouncementWasQuickSettings && !mTracking && !isCollapsing()) {
-                announceForAccessibility(getKeyguardOrLockScreenString());
-                mLastAnnouncementWasQuickSettings = false;
-            }
         }
         mQsExpansionHeight = height;
         updateQsExpansion();
@@ -1331,13 +1319,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 */);
@@ -1352,9 +1337,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 {
@@ -1571,7 +1560,7 @@
     private void updatePanelExpanded() {
         boolean isExpanded = !isFullyCollapsed();
         if (mPanelExpanded != isExpanded) {
-            mHeadsUpManager.setIsExpanded(isExpanded);
+            mHeadsUpManager.setIsPanelExpanded(isExpanded);
             mStatusBar.setPanelExpanded(isExpanded);
             mPanelExpanded = isExpanded;
         }
@@ -1882,6 +1871,9 @@
             requestScrollerTopPaddingUpdate(false /* animate */);
             requestPanelHeightUpdate();
         }
+        if (mAccessibilityManager.isEnabled()) {
+            setAccessibilityPaneTitle(determineAccessibilityPaneTitle());
+        }
     }
 
     @Override
@@ -2338,7 +2330,7 @@
     }
 
     @Override
-    public void setHeadsUpManager(HeadsUpManager headsUpManager) {
+    public void setHeadsUpManager(HeadsUpManagerPhone headsUpManager) {
         super.setHeadsUpManager(headsUpManager);
         mHeadsUpTouchHelper = new HeadsUpTouchHelper(headsUpManager, mNotificationStackScroller,
                 this);
@@ -2630,8 +2622,8 @@
         }
     }
 
-    public void setPulsing(Collection<HeadsUpManager.HeadsUpEntry> pulsing) {
-        mKeyguardStatusView.setPulsing(pulsing != null);
+    public void setPulsing(boolean pulsing) {
+        mKeyguardStatusView.setPulsing(pulsing);
         positionClockAndNotifications();
         mNotificationStackScroller.setPulsing(pulsing, mKeyguardStatusView.getLocationOnScreen()[1]
                 + mKeyguardStatusView.getClockBottom());
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index b6c7d74..dbabdb2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -50,8 +50,8 @@
 import com.android.systemui.doze.DozeLog;
 import com.android.systemui.statusbar.FlingAnimationUtils;
 import com.android.systemui.statusbar.StatusBarState;
-import com.android.systemui.statusbar.policy.HeadsUpManager;
 import android.util.BoostFramework;
+import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -76,7 +76,7 @@
     }
 
     protected StatusBar mStatusBar;
-    protected HeadsUpManager mHeadsUpManager;
+    protected HeadsUpManagerPhone mHeadsUpManager;
 
     private float mPeekHeight;
     private float mHintDistance;
@@ -1270,7 +1270,7 @@
      */
     protected abstract int getClearAllHeight();
 
-    public void setHeadsUpManager(HeadsUpManager headsUpManager) {
+    public void setHeadsUpManager(HeadsUpManagerPhone headsUpManager) {
         mHeadsUpManager = headsUpManager;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
index 6444cc8..747a551 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -575,7 +575,7 @@
 
         Intent browserIntent = getTaskIntent(taskId, userId);
         Notification.Builder builder = new Notification.Builder(mContext, NotificationChannels.GENERAL);
-        if (browserIntent != null) {
+        if (browserIntent != null && browserIntent.isWebIntent()) {
             // Make sure that this doesn't resolve back to an instant app
             browserIntent.setComponent(null)
                     .setPackage(null)
@@ -597,8 +597,9 @@
                     .addCategory("unique:" + System.currentTimeMillis())
                     .putExtra(Intent.EXTRA_PACKAGE_NAME, appInfo.packageName)
                     .putExtra(Intent.EXTRA_VERSION_CODE, (int) (appInfo.versionCode & 0x7fffffff))
-                    .putExtra(Intent.EXTRA_VERSION_CODE, appInfo.versionCode)
-                    .putExtra(Intent.EXTRA_EPHEMERAL_FAILURE, pendingIntent);
+                    .putExtra(Intent.EXTRA_LONG_VERSION_CODE, appInfo.versionCode)
+                    .putExtra(Intent.EXTRA_EPHEMERAL_FAILURE, pendingIntent)
+                    .putExtra(Intent.EXTRA_INSTANT_APP_FAILURE, pendingIntent);
 
             PendingIntent webPendingIntent = PendingIntent.getActivity(mContext, 0, goToWebIntent, 0);
             Action webAction = new Notification.Action.Builder(null, mContext.getString(R.string.go_to_web),
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickScrubController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickScrubController.java
index 001a1a2..378858a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickScrubController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickScrubController.java
@@ -29,15 +29,12 @@
 import android.graphics.Rect;
 import android.os.Handler;
 import android.os.RemoteException;
-import android.os.SystemProperties;
 import android.util.Log;
 import android.util.Slog;
-import android.view.Display;
 import android.view.GestureDetector;
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewConfiguration;
-import android.view.WindowManager;
 import android.view.WindowManagerGlobal;
 import android.view.animation.DecelerateInterpolator;
 import android.view.animation.Interpolator;
@@ -53,6 +50,7 @@
 import static android.view.WindowManagerPolicyConstants.NAV_BAR_BOTTOM;
 import static com.android.systemui.OverviewProxyService.DEBUG_OVERVIEW_PROXY;
 import static com.android.systemui.OverviewProxyService.TAG_OPS;
+import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_HOME;
 
 /**
  * Class to detect gestures on the navigation bar and implement quick scrub and switch.
@@ -63,7 +61,7 @@
     private static final String TAG = "QuickScrubController";
     private static final int QUICK_SWITCH_FLING_VELOCITY = 0;
     private static final int ANIM_DURATION_MS = 200;
-    private static final long LONG_PRESS_DELAY_MS = 150;
+    private static final long LONG_PRESS_DELAY_MS = 225;
 
     /**
      * For quick step, set a damping value to allow the button to stick closer its origin position
@@ -76,6 +74,7 @@
 
     private boolean mDraggingActive;
     private boolean mQuickScrubActive;
+    private boolean mAllowQuickSwitch;
     private float mDownOffset;
     private float mTranslation;
     private int mTouchDownX;
@@ -87,15 +86,14 @@
     private int mLightTrackColor;
     private int mDarkTrackColor;
     private float mDarkIntensity;
+    private View mHomeButtonView;
 
     private final Handler mHandler = new Handler();
     private final Interpolator mQuickScrubEndInterpolator = new DecelerateInterpolator();
     private final Rect mTrackRect = new Rect();
-    private final Rect mHomeButtonRect = new Rect();
     private final Paint mTrackPaint = new Paint();
     private final int mScrollTouchSlop;
     private final OverviewProxyService mOverviewEventSender;
-    private final Display mDisplay;
     private final int mTrackThickness;
     private final int mTrackPadding;
     private final ValueAnimator mTrackAnimator;
@@ -114,11 +112,10 @@
         if (!mQuickScrubActive) {
             pos = mDragPositive ? Math.min((int) mTranslation, pos) : Math.max((int) mTranslation, pos);
         }
-        final View homeView = mNavigationBarView.getHomeButton().getCurrentView();
         if (mIsVertical) {
-            homeView.setTranslationY(pos);
+            mHomeButtonView.setTranslationY(pos);
         } else {
-            homeView.setTranslationX(pos);
+            mHomeButtonView.setTranslationX(pos);
         }
     };
 
@@ -126,6 +123,7 @@
         @Override
         public void onAnimationEnd(Animator animation) {
             mNavigationBarView.getHomeButton().setClickable(true);
+            mHomeButtonView = null;
             mQuickScrubActive = false;
             mTranslation = 0;
         }
@@ -137,7 +135,9 @@
         new GestureDetector.SimpleOnGestureListener() {
             @Override
             public boolean onFling(MotionEvent e1, MotionEvent e2, float velX, float velY) {
-                if (!isQuickScrubEnabled() || mQuickScrubActive) {
+                if (!mNavigationBarView.isQuickScrubEnabled() || mQuickScrubActive
+                        || !mAllowQuickSwitch
+                        || mNavigationBarView.getDownHitTarget() != HIT_TARGET_HOME) {
                     return false;
                 }
                 float velocityX = mIsRTL ? -velX : velX;
@@ -158,16 +158,15 @@
                     } catch (RemoteException e) {
                         Log.e(TAG, "Failed to send start of quick switch.", e);
                     }
+                    return true;
                 }
-                return true;
+                return false;
             }
         };
 
     public QuickScrubController(Context context) {
         mContext = context;
         mScrollTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
-        mDisplay = ((WindowManager) context.getSystemService(
-                Context.WINDOW_SERVICE)).getDefaultDisplay();
         mOverviewEventSender = Dependency.get(OverviewProxyService.class);
         mGestureDetector = new GestureDetector(mContext, mGestureListener);
         mTrackThickness = getDimensionPixelSize(mContext, R.dimen.nav_quick_scrub_track_thickness);
@@ -189,21 +188,49 @@
         mNavigationBarView = navigationBarView;
     }
 
+    /**
+     * @return true if we want to intercept touch events for quick scrub/switch and prevent proxying
+     *         the event to the overview service.
+     */
     @Override
     public boolean onInterceptTouchEvent(MotionEvent event) {
-        final IOverviewProxy overviewProxy = mOverviewEventSender.getProxy();
         final ButtonDispatcher homeButton = mNavigationBarView.getHomeButton();
-        if (overviewProxy == null) {
+        if (!mNavigationBarView.isQuickScrubEnabled()) {
             homeButton.setDelayTouchFeedback(false);
             return false;
         }
-        mGestureDetector.onTouchEvent(event);
+
+        return handleTouchEvent(event);
+    }
+
+    /**
+     * @return true if we want to handle touch events for quick scrub/switch and prevent proxying
+     *         the event to the overview service.
+     */
+    @Override
+    public boolean onTouchEvent(MotionEvent event) {
+        return handleTouchEvent(event);
+    }
+
+    private boolean handleTouchEvent(MotionEvent event) {
+        final IOverviewProxy overviewProxy = mOverviewEventSender.getProxy();
+        final ButtonDispatcher homeButton = mNavigationBarView.getHomeButton();
+        if (mGestureDetector.onTouchEvent(event)) {
+            // If the fling has been handled on UP, then skip proxying the UP
+            return true;
+        }
         int action = event.getAction();
         switch (action & MotionEvent.ACTION_MASK) {
             case MotionEvent.ACTION_DOWN: {
                 int x = (int) event.getX();
                 int y = (int) event.getY();
-                if (isQuickScrubEnabled() && mHomeButtonRect.contains(x, y)) {
+                // End any existing quickscrub animations before starting the new transition
+                if (mQuickScrubEndAnimator != null) {
+                    mQuickScrubEndAnimator.end();
+                }
+                mHomeButtonView = homeButton.getCurrentView();
+                if (mNavigationBarView.isQuickScrubEnabled()
+                        && mNavigationBarView.getDownHitTarget() == HIT_TARGET_HOME) {
                     mTouchDownX = x;
                     mTouchDownY = y;
                     homeButton.setDelayTouchFeedback(true);
@@ -212,6 +239,7 @@
                     homeButton.setDelayTouchFeedback(false);
                     mTouchDownX = mTouchDownY = -1;
                 }
+                mAllowQuickSwitch = true;
                 break;
             }
             case MotionEvent.ACTION_MOVE: {
@@ -240,8 +268,9 @@
                         offset = pos - mTrackRect.left;
                         trackSize = mTrackRect.width();
                     }
-                    // Do not start scrubbing when dragging in the perpendicular direction
-                    if (!mDraggingActive && exceededPerpendicularTouchSlop) {
+                    // Do not start scrubbing when dragging in the perpendicular direction if we
+                    // haven't already started quickscrub
+                    if (!mDraggingActive && !mQuickScrubActive && exceededPerpendicularTouchSlop) {
                         mHandler.removeCallbacksAndMessages(null);
                         return false;
                     }
@@ -268,7 +297,7 @@
                             : Utilities.clamp(offset - mDownOffset, 0, trackSize);
                         if (mQuickScrubActive) {
                             try {
-                                overviewProxy.onQuickScrubProgress(scrubFraction);
+                                mOverviewEventSender.getProxy().onQuickScrubProgress(scrubFraction);
                                 if (DEBUG_OVERVIEW_PROXY) {
                                     Log.d(TAG_OPS, "Quick Scrub Progress:" + scrubFraction);
                                 }
@@ -279,9 +308,9 @@
                             mTranslation /= SWITCH_STICKINESS;
                         }
                         if (mIsVertical) {
-                            homeButton.getCurrentView().setTranslationY(mTranslation);
+                            mHomeButtonView.setTranslationY(mTranslation);
                         } else {
-                            homeButton.getCurrentView().setTranslationX(mTranslation);
+                            mHomeButtonView.setTranslationX(mTranslation);
                         }
                     }
                 }
@@ -289,7 +318,7 @@
             }
             case MotionEvent.ACTION_CANCEL:
             case MotionEvent.ACTION_UP:
-                endQuickScrub();
+                endQuickScrub(true /* animate */);
                 break;
         }
         return mDraggingActive || mQuickScrubActive;
@@ -321,17 +350,6 @@
             x2 = x1 + width / 2 - mTrackPadding;
         }
         mTrackRect.set(x1, y1, x2, y2);
-
-        // Get the touch rect of the home button location
-        View homeView = mNavigationBarView.getHomeButton().getCurrentView();
-        if (homeView != null) {
-            int[] globalHomePos = homeView.getLocationOnScreen();
-            int[] globalNavBarPos = mNavigationBarView.getLocationOnScreen();
-            int homeX = globalHomePos[0] - globalNavBarPos[0];
-            int homeY = globalHomePos[1] - globalNavBarPos[1];
-            mHomeButtonRect.set(homeX, homeY, homeX + homeView.getMeasuredWidth(),
-                    homeY + homeView.getMeasuredHeight());
-        }
     }
 
     @Override
@@ -341,15 +359,12 @@
     }
 
     @Override
-    public boolean onTouchEvent(MotionEvent event) {
-        if (event.getAction() == MotionEvent.ACTION_UP) {
-            endQuickScrub();
-        }
-        return false;
-    }
-
-    @Override
     public void setBarState(boolean isVertical, boolean isRTL) {
+        final boolean changed = (mIsVertical != isVertical) || (mIsRTL != isRTL);
+        if (changed) {
+            // End quickscrub if the state changes mid-transition
+            endQuickScrub(false /* animate */);
+        }
         mIsVertical = isVertical;
         mIsRTL = isRTL;
         try {
@@ -363,10 +378,6 @@
         }
     }
 
-    boolean isQuickScrubEnabled() {
-        return SystemProperties.getBoolean("persist.quickstep.scrub.enabled", false);
-    }
-
     private void startQuickScrub() {
         if (!mQuickScrubActive) {
             mQuickScrubActive = true;
@@ -385,7 +396,7 @@
         }
     }
 
-    private void endQuickScrub() {
+    private void endQuickScrub(boolean animate) {
         mHandler.removeCallbacks(mLongPressRunnable);
         if (mDraggingActive || mQuickScrubActive) {
             mButtonAnimator.setIntValues((int) mTranslation, 0);
@@ -399,10 +410,18 @@
             } catch (RemoteException e) {
                 Log.e(TAG, "Failed to send end of quick scrub.", e);
             }
+            if (!animate) {
+                mQuickScrubEndAnimator.end();
+            }
         }
         mDraggingActive = false;
     }
 
+    public void cancelQuickSwitch() {
+        mAllowQuickSwitch = false;
+        mHandler.removeCallbacks(mLongPressRunnable);
+    }
+
     private int getDimensionPixelSize(Context context, @DimenRes int resId) {
         return context.getResources().getDimensionPixelSize(resId);
     }
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 59c44ed..2b50853 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -30,6 +30,7 @@
 import android.os.Trace;
 import android.util.Log;
 import android.util.MathUtils;
+import android.view.Choreographer;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.ViewTreeObserver;
@@ -111,7 +112,6 @@
     protected static final float SCRIM_IN_FRONT_ALPHA_LOCKED = GRADIENT_SCRIM_ALPHA_BUSY;
 
     static final int TAG_KEY_ANIM = R.id.scrim;
-    static final int TAG_KEY_ANIM_BLANK = R.id.scrim_blanking;
     private static final int TAG_KEY_ANIM_TARGET = R.id.scrim_target;
     private static final int TAG_START_ALPHA = R.id.scrim_alpha_start;
     private static final int TAG_END_ALPHA = R.id.scrim_alpha_end;
@@ -166,6 +166,11 @@
     private boolean mScreenBlankingCallbackCalled;
     private Callback mCallback;
     private boolean mWallpaperSupportsAmbientMode;
+    private boolean mScreenOn;
+
+    // Scrim blanking callbacks
+    private Choreographer.FrameCallback mPendingFrameCallback;
+    private Runnable mBlankingTransitionRunnable;
 
     private final WakeLock mWakeLock;
     private boolean mWakeLockHeld;
@@ -248,6 +253,16 @@
         mCurrentInFrontAlpha = state.getFrontAlpha();
         mCurrentBehindAlpha = state.getBehindAlpha();
 
+        // Cancel blanking transitions that were pending before we requested a new state
+        if (mPendingFrameCallback != null) {
+            Choreographer.getInstance().removeFrameCallback(mPendingFrameCallback);
+            mPendingFrameCallback = null;
+        }
+        if (getHandler().hasCallbacks(mBlankingTransitionRunnable)) {
+            getHandler().removeCallbacks(mBlankingTransitionRunnable);
+            mBlankingTransitionRunnable = null;
+        }
+
         // Showing/hiding the keyguard means that scrim colors have to be switched, not necessary
         // to do the same when you're just showing the brightness mirror.
         mNeedsDrawableColorUpdate = state != ScrimState.BRIGHTNESS_MIRROR;
@@ -692,11 +707,12 @@
             }
         }
 
-        final boolean blankingInProgress = mScrimInFront.getTag(TAG_KEY_ANIM_BLANK) != null;
-        if (mBlankScreen || blankingInProgress) {
-            if (!blankingInProgress) {
-                blankDisplay();
-            }
+        if (mPendingFrameCallback != null) {
+            // Display is off and we're waiting.
+            return;
+        } else if (mBlankScreen) {
+            // Need to blank the display before continuing.
+            blankDisplay();
             return;
         } else if (!mScreenBlankingCallbackCalled) {
             // Not blanking the screen. Letting the callback know that we're ready
@@ -750,45 +766,38 @@
     }
 
     private void blankDisplay() {
-        final float initialAlpha = mScrimInFront.getViewAlpha();
-        final int initialTint = mScrimInFront.getTint();
-        ValueAnimator anim = ValueAnimator.ofFloat(0, 1);
-        anim.addUpdateListener(animation -> {
-            final float amount = (float) animation.getAnimatedValue();
-            float animAlpha = MathUtils.lerp(initialAlpha, 1, amount);
-            int animTint = ColorUtils.blendARGB(initialTint, Color.BLACK, amount);
-            updateScrimColor(mScrimInFront, animAlpha, animTint);
-            dispatchScrimsVisible();
-        });
-        anim.setInterpolator(getInterpolator());
-        anim.setDuration(mDozeParameters.getPulseInDuration());
-        anim.addListener(new AnimatorListenerAdapter() {
-            @Override
-            public void onAnimationEnd(Animator animation) {
-                if (mCallback != null) {
-                    mCallback.onDisplayBlanked();
-                    mScreenBlankingCallbackCalled = true;
-                }
-                Runnable blankingCallback = () -> {
-                    mScrimInFront.setTag(TAG_KEY_ANIM_BLANK, null);
-                    mBlankScreen = false;
-                    // Try again.
-                    updateScrims();
-                };
+        updateScrimColor(mScrimInFront, 1, Color.BLACK);
 
-                // Setting power states can happen after we push out the frame. Make sure we
-                // stay fully opaque until the power state request reaches the lower levels.
-                getHandler().postDelayed(blankingCallback, 100);
-
+        // Notify callback that the screen is completely black and we're
+        // ready to change the display power mode
+        mPendingFrameCallback = frameTimeNanos -> {
+            if (mCallback != null) {
+                mCallback.onDisplayBlanked();
+                mScreenBlankingCallbackCalled = true;
             }
-        });
-        anim.start();
-        mScrimInFront.setTag(TAG_KEY_ANIM_BLANK, anim);
 
-        // Finish animation if we're already at its final state
-        if (initialAlpha == 1 && mScrimInFront.getTint() == Color.BLACK) {
-            anim.end();
-        }
+            mBlankingTransitionRunnable = () -> {
+                mBlankingTransitionRunnable = null;
+                mPendingFrameCallback = null;
+                mBlankScreen = false;
+                // Try again.
+                updateScrims();
+            };
+
+            // Setting power states can happen after we push out the frame. Make sure we
+            // stay fully opaque until the power state request reaches the lower levels.
+            final int delay = mScreenOn ? 16 : 500;
+            if (DEBUG) {
+                Log.d(TAG, "Fading out scrims with delay: " + delay);
+            }
+            getHandler().postDelayed(mBlankingTransitionRunnable, delay);
+        };
+        doOnTheNextFrame(mPendingFrameCallback);
+    }
+
+    @VisibleForTesting
+    protected void doOnTheNextFrame(Choreographer.FrameCallback callback) {
+        Choreographer.getInstance().postFrameCallback(callback);
     }
 
     @VisibleForTesting
@@ -893,6 +902,25 @@
         }
     }
 
+    /**
+     * Interrupts blanking transitions once the display notifies that it's already on.
+     */
+    public void onScreenTurnedOn() {
+        mScreenOn = true;
+        final Handler handler = getHandler();
+        if (handler.hasCallbacks(mBlankingTransitionRunnable)) {
+            if (DEBUG) {
+                Log.d(TAG, "Shorter blanking because screen turned on. All good.");
+            }
+            handler.removeCallbacks(mBlankingTransitionRunnable);
+            mBlankingTransitionRunnable.run();
+        }
+    }
+
+    public void onScreenTurnedOff() {
+        mScreenOn = false;
+    }
+
     public interface Callback {
         default void onStart() {
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
index 314d6aa..381e4af 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
@@ -48,7 +48,6 @@
                     // set our scrim to black in this frame to avoid flickering and
                     // fade it out afterwards.
                     mBlankScreen = true;
-                    updateScrimColor(mScrimInFront, 1, Color.BLACK);
                 }
             } else {
                 mAnimationDuration = ScrimController.ANIMATION_DURATION;
@@ -86,9 +85,6 @@
     AOD(3) {
         @Override
         public void prepare(ScrimState previousState) {
-            if (previousState == ScrimState.PULSING && !mCanControlScreenOff) {
-                updateScrimColor(mScrimInFront, 1, Color.BLACK);
-            }
             final boolean alwaysOnEnabled = mDozeParameters.getAlwaysOn();
             final boolean wasPulsing = previousState == ScrimState.PULSING;
             mBlankScreen = wasPulsing && !mCanControlScreenOff;
@@ -115,9 +111,6 @@
                     && !mKeyguardUpdateMonitor.hasLockscreenWallpaper() ? 0f : 1f;
             mCurrentBehindTint = Color.BLACK;
             mBlankScreen = mDisplayRequiresBlanking;
-            if (mDisplayRequiresBlanking) {
-                updateScrimColor(mScrimInFront, 1, Color.BLACK);
-            }
         }
     },
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 1bf719a..24920cb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -111,6 +111,7 @@
 import android.view.KeyEvent;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
+import android.view.RemoteAnimationAdapter;
 import android.view.ThreadedRenderer;
 import android.view.View;
 import android.view.ViewGroup;
@@ -140,7 +141,6 @@
 import com.android.keyguard.ViewMediatorCallback;
 import com.android.systemui.ActivityStarterDelegate;
 import com.android.systemui.AutoReinflateContainer;
-import com.android.systemui.charging.WirelessChargingAnimation;
 import com.android.systemui.DemoMode;
 import com.android.systemui.Dependency;
 import com.android.systemui.EventLogTags;
@@ -152,6 +152,7 @@
 import com.android.systemui.SystemUIFactory;
 import com.android.systemui.UiOffloadThread;
 import com.android.systemui.assist.AssistManager;
+import com.android.systemui.charging.WirelessChargingAnimation;
 import com.android.systemui.classifier.FalsingLog;
 import com.android.systemui.classifier.FalsingManager;
 import com.android.systemui.colorextraction.SysuiColorExtractor;
@@ -181,6 +182,7 @@
 import com.android.systemui.statusbar.ActivatableNotificationView;
 import com.android.systemui.statusbar.BackDropView;
 import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.CrossFadeHelper;
 import com.android.systemui.statusbar.DismissView;
 import com.android.systemui.statusbar.DragDownHelper;
 import com.android.systemui.statusbar.EmptyShadeView;
@@ -208,6 +210,7 @@
 import com.android.systemui.statusbar.notification.AboveShelfObserver;
 import com.android.systemui.statusbar.notification.ActivityLaunchAnimator;
 import com.android.systemui.statusbar.notification.VisualStabilityManager;
+import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
 import com.android.systemui.statusbar.phone.UnlockMethodCache.OnUnlockMethodChangedListener;
 import com.android.systemui.statusbar.policy.BatteryController;
 import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback;
@@ -219,6 +222,7 @@
 import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
 import com.android.systemui.statusbar.policy.ExtensionController;
 import com.android.systemui.statusbar.policy.HeadsUpManager;
+import com.android.systemui.statusbar.policy.HeadsUpUtil;
 import com.android.systemui.statusbar.policy.KeyguardMonitor;
 import com.android.systemui.statusbar.policy.KeyguardMonitorImpl;
 import com.android.systemui.statusbar.policy.KeyguardUserSwitcher;
@@ -809,15 +813,14 @@
                 .commit();
         mIconController = Dependency.get(StatusBarIconController.class);
 
-        mHeadsUpManager = new HeadsUpManager(context, mStatusBarWindow, mGroupManager);
-        mHeadsUpManager.setBar(this);
+        mHeadsUpManager = new HeadsUpManagerPhone(context, mStatusBarWindow, mGroupManager, this,
+                mVisualStabilityManager);
         mHeadsUpManager.addListener(this);
         mHeadsUpManager.addListener(mNotificationPanel);
         mHeadsUpManager.addListener(mGroupManager);
         mHeadsUpManager.addListener(mVisualStabilityManager);
         mNotificationPanel.setHeadsUpManager(mHeadsUpManager);
         mGroupManager.setHeadsUpManager(mHeadsUpManager);
-        mHeadsUpManager.setVisualStabilityManager(mVisualStabilityManager);
         putComponent(HeadsUpManager.class, mHeadsUpManager);
 
         mEntryManager.setUpWithPresenter(this, mStackScroller, this, mHeadsUpManager);
@@ -1348,7 +1351,8 @@
 
     @Override
     public void onPerformRemoveNotification(StatusBarNotification n) {
-        if (mStackScroller.hasPulsingNotifications() && mHeadsUpManager.getAllEntries().isEmpty()) {
+        if (mStackScroller.hasPulsingNotifications() &&
+                    !mHeadsUpManager.hasHeadsUpNotifications()) {
             // We were showing a pulse for a notification, but no notifications are pulsing anymore.
             // Finish the pulse.
             mDozeScrimController.pulseOutNow();
@@ -2097,9 +2101,8 @@
     }
 
     public void maybeEscalateHeadsUp() {
-        Collection<HeadsUpManager.HeadsUpEntry> entries = mHeadsUpManager.getAllEntries();
-        for (HeadsUpManager.HeadsUpEntry entry : entries) {
-            final StatusBarNotification sbn = entry.entry.notification;
+        mHeadsUpManager.getAllEntries().forEach(entry -> {
+            final StatusBarNotification sbn = entry.notification;
             final Notification notification = sbn.getNotification();
             if (notification.fullScreenIntent != null) {
                 if (DEBUG) {
@@ -2109,11 +2112,11 @@
                     EventLog.writeEvent(EventLogTags.SYSUI_HEADS_UP_ESCALATION,
                             sbn.getKey());
                     notification.fullScreenIntent.send();
-                    entry.entry.notifyFullScreenIntentLaunched();
+                    entry.notifyFullScreenIntentLaunched();
                 } catch (PendingIntent.CanceledException e) {
                 }
             }
-        }
+        });
         mHeadsUpManager.releaseAllImmediately();
     }
 
@@ -2459,14 +2462,25 @@
     }
 
     @Override
-    public void showChargingAnimation(int batteryLevel) {
-        if (mDozing) {
-            // ambient
-        } else if (mKeyguardManager.isKeyguardLocked()) {
-            // lockscreen
-        } else {
+    public void showWirelessChargingAnimation(int batteryLevel) {
+        if (mDozing || mKeyguardManager.isKeyguardLocked()) {
+            // on ambient or lockscreen, hide notification panel
             WirelessChargingAnimation.makeWirelessChargingAnimation(mContext, null,
-                    batteryLevel).show();
+                    batteryLevel, new WirelessChargingAnimation.Callback() {
+                        @Override
+                        public void onAnimationStarting() {
+                            CrossFadeHelper.fadeOut(mNotificationPanel, 1);
+                        }
+
+                        @Override
+                        public void onAnimationEnded() {
+                            CrossFadeHelper.fadeIn(mNotificationPanel);
+                        }
+                    }).show();
+        } else {
+            // workspace
+            WirelessChargingAnimation.makeWirelessChargingAnimation(mContext, null,
+                    batteryLevel, null).show();
         }
     }
 
@@ -2836,7 +2850,7 @@
                     Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
             int result = ActivityManager.START_CANCELED;
             ActivityOptions options = new ActivityOptions(getActivityOptions(
-                    null /* sourceNotification */));
+                    null /* remoteAnimation */));
             options.setDisallowEnterPictureInPictureWhileLaunching(
                     disallowEnterPictureInPictureWhileLaunching);
             if (intent == KeyguardBottomAreaView.INSECURE_CAMERA_INTENT) {
@@ -3882,6 +3896,7 @@
 
     private void instantCollapseNotificationPanel() {
         mNotificationPanel.instantCollapse();
+        runPostCollapseRunnables();
     }
 
     @Override
@@ -4393,11 +4408,13 @@
 
         @Override
         public void onScreenTurnedOn() {
+            mScrimController.onScreenTurnedOn();
         }
 
         @Override
         public void onScreenTurnedOff() {
             mFalsingManager.onScreenOff();
+            mScrimController.onScreenTurnedOff();
             // If we pulse in from AOD, we turn the screen off first. However, updatingIsKeyguard
             // in that case destroys the HeadsUpManager state, so don't do it in that case.
             if (!isPulsing()) {
@@ -4658,24 +4675,22 @@
                 @Override
                 public void onPulseStarted() {
                     callback.onPulseStarted();
-                    Collection<HeadsUpManager.HeadsUpEntry> pulsingEntries =
-                            mHeadsUpManager.getAllEntries();
-                    if (!pulsingEntries.isEmpty()) {
+                    if (mHeadsUpManager.hasHeadsUpNotifications()) {
                         // Only pulse the stack scroller if there's actually something to show.
                         // Otherwise just show the always-on screen.
-                        setPulsing(pulsingEntries);
+                        setPulsing(true);
                     }
                 }
 
                 @Override
                 public void onPulseFinished() {
                     callback.onPulseFinished();
-                    setPulsing(null);
+                    setPulsing(false);
                 }
 
-                private void setPulsing(Collection<HeadsUpManager.HeadsUpEntry> pulsing) {
+                private void setPulsing(boolean pulsing) {
                     mNotificationPanel.setPulsing(pulsing);
-                    mVisualStabilityManager.setPulsing(pulsing != null);
+                    mVisualStabilityManager.setPulsing(pulsing);
                     mIgnoreTouchWhilePulsing = false;
                 }
             }, reason);
@@ -4823,7 +4838,7 @@
 
 
     // for heads up notifications
-    protected HeadsUpManager mHeadsUpManager;
+    protected HeadsUpManagerPhone mHeadsUpManager;
 
     private AboveShelfObserver mAboveShelfObserver;
 
@@ -4926,7 +4941,7 @@
                 // Release the HUN notification to the shade.
 
                 if (isPresenterFullyCollapsed()) {
-                    HeadsUpManager.setIsClickedNotification(row, true);
+                    HeadsUpUtil.setIsClickedHeadsUpNotification(row, true);
                 }
                 //
                 // In most cases, when FLAG_AUTO_CANCEL is set, the notification will
@@ -4987,11 +5002,15 @@
                         fillInIntent = new Intent().putExtra(Notification.EXTRA_REMOTE_INPUT_DRAFT,
                                 remoteInputText.toString());
                     }
+                    RemoteAnimationAdapter adapter = mActivityLaunchAnimator.getLaunchAnimation(
+                            row);
                     try {
+                        ActivityManager.getService().registerRemoteAnimationForNextActivityStart(
+                                intent.getCreatorPackage(), adapter);
                         launchResult = intent.sendAndReturnResult(mContext, 0, fillInIntent, null,
-                                null, null, getActivityOptions(row));
+                                null, null, getActivityOptions(adapter));
                         mActivityLaunchAnimator.setLaunchResult(launchResult);
-                    } catch (PendingIntent.CanceledException e) {
+                    } catch (RemoteException | PendingIntent.CanceledException e) {
                         // the stack trace isn't very helpful here.
                         // Just log the exception message.
                         Log.w(TAG, "Sending contentIntent failed: " + e);
@@ -5045,6 +5064,8 @@
         } else if (!isPresenterFullyCollapsed()) {
             instantCollapseNotificationPanel();
             visibilityChanged(false);
+        } else {
+            runPostCollapseRunnables();
         }
     }
 
@@ -5149,7 +5170,8 @@
             AsyncTask.execute(() -> {
                 int launchResult = TaskStackBuilder.create(mContext)
                         .addNextIntentWithParentStack(intent)
-                        .startActivities(getActivityOptions(row),
+                        .startActivities(getActivityOptions(
+                                mActivityLaunchAnimator.getLaunchAnimation(row)),
                                 new UserHandle(UserHandle.getUserId(appUid)));
                 mActivityLaunchAnimator.setLaunchResult(launchResult);
                 if (shouldCollapse()) {
@@ -5284,7 +5306,7 @@
                 }
                 try {
                     intent.send(null, 0, null, null, null, null, getActivityOptions(
-                            null /* sourceNotification */));
+                            null /* animationAdapter */));
                 } catch (PendingIntent.CanceledException e) {
                     // the stack trace isn't very helpful here.
                     // Just log the exception message.
@@ -5312,10 +5334,10 @@
         return true;
     }
 
-    protected Bundle getActivityOptions(ExpandableNotificationRow sourceNotification) {
+    protected Bundle getActivityOptions(@Nullable RemoteAnimationAdapter animationAdapter) {
         ActivityOptions options;
-        if (sourceNotification != null) {
-            options = mActivityLaunchAnimator.getLaunchAnimation(sourceNotification);
+        if (animationAdapter != null) {
+            options = ActivityOptions.makeRemoteAnimation(animationAdapter);
         } else {
             options = ActivityOptions.makeBasic();
         }
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/HeadsUpManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
index 53dfb24..040d7ec 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
@@ -16,119 +16,69 @@
 
 package com.android.systemui.statusbar.policy;
 
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.content.Context;
 import android.content.res.Resources;
 import android.database.ContentObserver;
+import android.os.SystemClock;
 import android.os.Handler;
 import android.os.Looper;
-import android.os.SystemClock;
-import android.provider.Settings;
-import android.support.v4.util.ArraySet;
 import android.util.ArrayMap;
+import android.provider.Settings;
 import android.util.Log;
-import android.util.Pools;
-import android.view.View;
-import android.view.ViewTreeObserver;
 import android.view.accessibility.AccessibilityEvent;
 
 import com.android.internal.logging.MetricsLogger;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.ExpandableNotificationRow;
 import com.android.systemui.statusbar.NotificationData;
-import com.android.systemui.statusbar.StatusBarState;
-import com.android.systemui.statusbar.notification.VisualStabilityManager;
-import com.android.systemui.statusbar.phone.NotificationGroupManager;
-import com.android.systemui.statusbar.phone.StatusBar;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.Collection;
+import java.util.Iterator;
+import java.util.stream.Stream;
 import java.util.HashMap;
 import java.util.HashSet;
-import java.util.Stack;
 
 /**
  * A manager which handles heads up notifications which is a special mode where
  * they simply peek from the top of the screen.
  */
-public class HeadsUpManager implements ViewTreeObserver.OnComputeInternalInsetsListener,
-        VisualStabilityManager.Callback {
+public class HeadsUpManager {
     private static final String TAG = "HeadsUpManager";
     private static final boolean DEBUG = false;
     private static final String SETTING_HEADS_UP_SNOOZE_LENGTH_MS = "heads_up_snooze_length_ms";
-    private static final int TAG_CLICKED_NOTIFICATION = R.id.is_clicked_heads_up_tag;
 
-    private final int mHeadsUpNotificationDecay;
-    private final int mMinimumDisplayTime;
+    protected final Clock mClock = new Clock();
+    protected final HashSet<OnHeadsUpChangedListener> mListeners = new HashSet<>();
+    protected final Handler mHandler = new Handler(Looper.getMainLooper());
 
-    private final int mTouchAcceptanceDelay;
+    protected final Context mContext;
+
+    protected int mHeadsUpNotificationDecay;
+    protected int mMinimumDisplayTime;
+    protected int mTouchAcceptanceDelay;
+    protected int mSnoozeLengthMs;
+    protected boolean mHasPinnedNotification;
+    protected int mUser;
+
+    private final HashMap<String, HeadsUpEntry> mHeadsUpEntries = new HashMap<>();
     private final ArrayMap<String, Long> mSnoozedPackages;
-    private final HashSet<OnHeadsUpChangedListener> mListeners = new HashSet<>();
-    private final int mDefaultSnoozeLengthMs;
-    private final Handler mHandler = new Handler(Looper.getMainLooper());
-    private final Pools.Pool<HeadsUpEntry> mEntryPool = new Pools.Pool<HeadsUpEntry>() {
 
-        private Stack<HeadsUpEntry> mPoolObjects = new Stack<>();
-
-        @Override
-        public HeadsUpEntry acquire() {
-            if (!mPoolObjects.isEmpty()) {
-                return mPoolObjects.pop();
-            }
-            return new HeadsUpEntry();
-        }
-
-        @Override
-        public boolean release(HeadsUpEntry instance) {
-            instance.reset();
-            mPoolObjects.push(instance);
-            return true;
-        }
-    };
-
-    private final View mStatusBarWindowView;
-    private final int mStatusBarHeight;
-    private final Context mContext;
-    private final NotificationGroupManager mGroupManager;
-    private StatusBar mBar;
-    private int mSnoozeLengthMs;
-    private ContentObserver mSettingsObserver;
-    private HashMap<String, HeadsUpEntry> mHeadsUpEntries = new HashMap<>();
-    private HashSet<String> mSwipedOutKeys = new HashSet<>();
-    private int mUser;
-    private Clock mClock;
-    private boolean mReleaseOnExpandFinish;
-    private boolean mTrackingHeadsUp;
-    private HashSet<NotificationData.Entry> mEntriesToRemoveAfterExpand = new HashSet<>();
-    private ArraySet<NotificationData.Entry> mEntriesToRemoveWhenReorderingAllowed
-            = new ArraySet<>();
-    private boolean mIsExpanded;
-    private boolean mHasPinnedNotification;
-    private int[] mTmpTwoArray = new int[2];
-    private boolean mHeadsUpGoingAway;
-    private boolean mWaitingOnCollapseWhenGoingAway;
-    private boolean mIsObserving;
-    private boolean mRemoteInputActive;
-    private float mExpandedHeight;
-    private VisualStabilityManager mVisualStabilityManager;
-    private int mStatusBarState;
-
-    public HeadsUpManager(final Context context, View statusBarWindowView,
-                          NotificationGroupManager groupManager) {
+    public HeadsUpManager(@NonNull final Context context) {
         mContext = context;
-        Resources resources = mContext.getResources();
-        mTouchAcceptanceDelay = resources.getInteger(R.integer.touch_acceptance_delay);
-        mSnoozedPackages = new ArrayMap<>();
-        mDefaultSnoozeLengthMs = resources.getInteger(R.integer.heads_up_default_snooze_length_ms);
-        mSnoozeLengthMs = mDefaultSnoozeLengthMs;
+        Resources resources = context.getResources();
         mMinimumDisplayTime = resources.getInteger(R.integer.heads_up_notification_minimum_time);
         mHeadsUpNotificationDecay = resources.getInteger(R.integer.heads_up_notification_decay);
-        mClock = new Clock();
+        mTouchAcceptanceDelay = resources.getInteger(R.integer.touch_acceptance_delay);
+        mSnoozedPackages = new ArrayMap<>();
+        int defaultSnoozeLengthMs =
+                resources.getInteger(R.integer.heads_up_default_snooze_length_ms);
 
         mSnoozeLengthMs = Settings.Global.getInt(context.getContentResolver(),
-                SETTING_HEADS_UP_SNOOZE_LENGTH_MS, mDefaultSnoozeLengthMs);
-        mSettingsObserver = new ContentObserver(mHandler) {
+                SETTING_HEADS_UP_SNOOZE_LENGTH_MS, defaultSnoozeLengthMs);
+        ContentObserver settingsObserver = new ContentObserver(mHandler) {
             @Override
             public void onChange(boolean selfChange) {
                 final int packageSnoozeLengthMs = Settings.Global.getInt(
@@ -141,48 +91,27 @@
         };
         context.getContentResolver().registerContentObserver(
                 Settings.Global.getUriFor(SETTING_HEADS_UP_SNOOZE_LENGTH_MS), false,
-                mSettingsObserver);
-        mStatusBarWindowView = statusBarWindowView;
-        mGroupManager = groupManager;
-        mStatusBarHeight = resources.getDimensionPixelSize(
-                com.android.internal.R.dimen.status_bar_height);
+                settingsObserver);
     }
 
-    private void updateTouchableRegionListener() {
-        boolean shouldObserve = mHasPinnedNotification || mHeadsUpGoingAway
-                || mWaitingOnCollapseWhenGoingAway;
-        if (shouldObserve == mIsObserving) {
-            return;
-        }
-        if (shouldObserve) {
-            mStatusBarWindowView.getViewTreeObserver().addOnComputeInternalInsetsListener(this);
-            mStatusBarWindowView.requestLayout();
-        } else {
-            mStatusBarWindowView.getViewTreeObserver().removeOnComputeInternalInsetsListener(this);
-        }
-        mIsObserving = shouldObserve;
-    }
-
-    public void setBar(StatusBar bar) {
-        mBar = bar;
-    }
-
-    public void addListener(OnHeadsUpChangedListener listener) {
+    /**
+     * Adds an OnHeadUpChangedListener to observe events.
+     */
+    public void addListener(@NonNull OnHeadsUpChangedListener listener) {
         mListeners.add(listener);
     }
 
-    public void removeListener(OnHeadsUpChangedListener listener) {
+    /**
+     * Removes the OnHeadUpChangedListener from the observer list.
+     */
+    public void removeListener(@NonNull OnHeadsUpChangedListener listener) {
         mListeners.remove(listener);
     }
 
-    public StatusBar getBar() {
-        return mBar;
-    }
-
     /**
      * Called when posting a new notification to the heads up.
      */
-    public void showNotification(NotificationData.Entry headsUp) {
+    public void showNotification(@NonNull NotificationData.Entry headsUp) {
         if (DEBUG) Log.v(TAG, "showNotification");
         addHeadsUpEntry(headsUp);
         updateNotification(headsUp, true);
@@ -192,7 +121,7 @@
     /**
      * Called when updating or posting a notification to the heads up.
      */
-    public void updateNotification(NotificationData.Entry headsUp, boolean alert) {
+    public void updateNotification(@NonNull NotificationData.Entry headsUp, boolean alert) {
         if (DEBUG) Log.v(TAG, "updateNotification");
 
         headsUp.row.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
@@ -204,14 +133,13 @@
                 // with the groupmanager
                 return;
             }
-            headsUpEntry.updateEntry();
+            headsUpEntry.updateEntry(true /* updatePostTime */);
             setEntryPinned(headsUpEntry, shouldHeadsUpBecomePinned(headsUp));
         }
     }
 
-    private void addHeadsUpEntry(NotificationData.Entry entry) {
-        HeadsUpEntry headsUpEntry = mEntryPool.acquire();
-
+    private void addHeadsUpEntry(@NonNull NotificationData.Entry entry) {
+        HeadsUpEntry headsUpEntry = createHeadsUpEntry();
         // This will also add the entry to the sortedList
         headsUpEntry.setEntry(entry);
         mHeadsUpEntries.put(entry.key, headsUpEntry);
@@ -223,16 +151,17 @@
         entry.row.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
     }
 
-    private boolean shouldHeadsUpBecomePinned(NotificationData.Entry entry) {
-        return mStatusBarState != StatusBarState.KEYGUARD
-                && !mIsExpanded || hasFullScreenIntent(entry);
+    protected boolean shouldHeadsUpBecomePinned(@NonNull NotificationData.Entry entry) {
+        return hasFullScreenIntent(entry);
     }
 
-    private boolean hasFullScreenIntent(NotificationData.Entry entry) {
+    protected boolean hasFullScreenIntent(@NonNull NotificationData.Entry entry) {
         return entry.notification.getNotification().fullScreenIntent != null;
     }
 
-    private void setEntryPinned(HeadsUpEntry headsUpEntry, boolean isPinned) {
+    protected void setEntryPinned(
+            @NonNull HeadsUpManager.HeadsUpEntry headsUpEntry, boolean isPinned) {
+        if (DEBUG) Log.v(TAG, "setEntryPinned: " + isPinned);
         ExpandableNotificationRow row = headsUpEntry.entry.row;
         if (row.isPinned() != isPinned) {
             row.setPinned(isPinned);
@@ -247,33 +176,35 @@
         }
     }
 
-    private void removeHeadsUpEntry(NotificationData.Entry entry) {
+    protected void removeHeadsUpEntry(@NonNull NotificationData.Entry entry) {
         HeadsUpEntry remove = mHeadsUpEntries.remove(entry.key);
+        onHeadsUpEntryRemoved(remove);
+    }
+
+    protected void onHeadsUpEntryRemoved(@NonNull HeadsUpEntry remove) {
+        NotificationData.Entry entry = remove.entry;
         entry.row.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
         entry.row.setHeadsUp(false);
         setEntryPinned(remove, false /* isPinned */);
         for (OnHeadsUpChangedListener listener : mListeners) {
             listener.onHeadsUpStateChanged(entry, false);
         }
-        mEntryPool.release(remove);
+        releaseHeadsUpEntry(remove);
     }
 
-    public void removeAllHeadsUpEntries() {
-        for (String key : mHeadsUpEntries.keySet()) {
-            removeHeadsUpEntry(mHeadsUpEntries.get(key).entry);
-        }
-    }
-
-    private void updatePinnedMode() {
+    protected void updatePinnedMode() {
         boolean hasPinnedNotification = hasPinnedNotificationInternal();
         if (hasPinnedNotification == mHasPinnedNotification) {
             return;
         }
+        if (DEBUG) {
+            Log.v(TAG, "Pinned mode changed: " + mHasPinnedNotification + " -> " +
+                       hasPinnedNotification);
+        }
         mHasPinnedNotification = hasPinnedNotification;
         if (mHasPinnedNotification) {
             MetricsLogger.count(mContext, "note_peek", 1);
         }
-        updateTouchableRegionListener();
         for (OnHeadsUpChangedListener listener : mListeners) {
             listener.onHeadsUpPinnedModeChanged(hasPinnedNotification);
         }
@@ -285,47 +216,36 @@
      * @return true if the notification was removed and false if it still needs to be kept around
      * for a bit since it wasn't shown long enough
      */
-    public boolean removeNotification(String key, boolean ignoreEarliestRemovalTime) {
-        if (DEBUG) Log.v(TAG, "remove");
-        if (wasShownLongEnough(key) || ignoreEarliestRemovalTime) {
-            releaseImmediately(key);
-            return true;
-        } else {
-            getHeadsUpEntry(key).removeAsSoonAsPossible();
-            return false;
-        }
+    public boolean removeNotification(@NonNull String key, boolean ignoreEarliestRemovalTime) {
+        if (DEBUG) Log.v(TAG, "removeNotification");
+        releaseImmediately(key);
+        return true;
     }
 
-    private boolean wasShownLongEnough(String key) {
-        HeadsUpEntry headsUpEntry = getHeadsUpEntry(key);
-        HeadsUpEntry topEntry = getTopEntry();
-        if (mSwipedOutKeys.contains(key)) {
-            // We always instantly dismiss views being manually swiped out.
-            mSwipedOutKeys.remove(key);
-            return true;
-        }
-        if (headsUpEntry != topEntry) {
-            return true;
-        }
-        return headsUpEntry.wasShownLongEnough();
-    }
-
-    public boolean isHeadsUp(String key) {
+    /**
+     * Returns if the given notification is in the Heads Up Notification list or not.
+     */
+    public boolean isHeadsUp(@NonNull String key) {
         return mHeadsUpEntries.containsKey(key);
     }
 
     /**
-     * Push any current Heads Up notification down into the shade.
+     * Pushes any current Heads Up notification down into the shade.
      */
     public void releaseAllImmediately() {
         if (DEBUG) Log.v(TAG, "releaseAllImmediately");
-        ArrayList<String> keys = new ArrayList<>(mHeadsUpEntries.keySet());
-        for (String key : keys) {
-            releaseImmediately(key);
+        Iterator<HeadsUpEntry> iterator = mHeadsUpEntries.values().iterator();
+        while (iterator.hasNext()) {
+            HeadsUpEntry entry = iterator.next();
+            iterator.remove();
+            onHeadsUpEntryRemoved(entry);
         }
     }
 
-    public void releaseImmediately(String key) {
+    /**
+     * Pushes the given Heads Up notification down into the shade.
+     */
+    public void releaseImmediately(@NonNull String key) {
         HeadsUpEntry headsUpEntry = getHeadsUpEntry(key);
         if (headsUpEntry == null) {
             return;
@@ -334,11 +254,14 @@
         removeHeadsUpEntry(shadeEntry);
     }
 
-    public boolean isSnoozed(String packageName) {
+    /**
+     * Returns if the given notification is snoozed or not.
+     */
+    public boolean isSnoozed(@NonNull String packageName) {
         final String key = snoozeKey(packageName, mUser);
         Long snoozedUntil = mSnoozedPackages.get(key);
         if (snoozedUntil != null) {
-            if (snoozedUntil > SystemClock.elapsedRealtime()) {
+            if (snoozedUntil > mClock.currentTimeMillis()) {
                 if (DEBUG) Log.v(TAG, key + " snoozed");
                 return true;
             }
@@ -347,39 +270,71 @@
         return false;
     }
 
+    /**
+     * Snoozes all current Heads Up Notifications.
+     */
     public void snooze() {
         for (String key : mHeadsUpEntries.keySet()) {
             HeadsUpEntry entry = mHeadsUpEntries.get(key);
             String packageName = entry.entry.notification.getPackageName();
             mSnoozedPackages.put(snoozeKey(packageName, mUser),
-                    SystemClock.elapsedRealtime() + mSnoozeLengthMs);
+                    mClock.currentTimeMillis() + mSnoozeLengthMs);
         }
-        mReleaseOnExpandFinish = true;
     }
 
-    private static String snoozeKey(String packageName, int user) {
+    @NonNull
+    private static String snoozeKey(@NonNull String packageName, int user) {
         return user + "," + packageName;
     }
 
-    private HeadsUpEntry getHeadsUpEntry(String key) {
+    @Nullable
+    protected HeadsUpEntry getHeadsUpEntry(@NonNull String key) {
         return mHeadsUpEntries.get(key);
     }
 
-    public NotificationData.Entry getEntry(String key) {
-        return mHeadsUpEntries.get(key).entry;
+    /**
+     * Returns the entry of given Heads Up Notification.
+     *
+     * @param key Key of heads up notification
+     */
+    @Nullable
+    public NotificationData.Entry getEntry(@NonNull String key) {
+        HeadsUpEntry entry = mHeadsUpEntries.get(key);
+        return entry != null ? entry.entry : null;
     }
 
-    public Collection<HeadsUpEntry> getAllEntries() {
-        return mHeadsUpEntries.values();
+    /**
+     * Returns the stream of all current Heads Up Notifications.
+     */
+    @NonNull
+    public Stream<NotificationData.Entry> getAllEntries() {
+        return mHeadsUpEntries.values().stream().map(headsUpEntry -> headsUpEntry.entry);
     }
 
-    public HeadsUpEntry getTopEntry() {
+    /**
+     * Returns the top Heads Up Notification, which appeares to show at first.
+     */
+    @Nullable
+    public NotificationData.Entry getTopEntry() {
+        HeadsUpEntry topEntry = getTopHeadsUpEntry();
+        return (topEntry != null) ? topEntry.entry : null;
+    }
+
+    /**
+     * Returns if any heads up notification is available or not.
+     */
+    public boolean hasHeadsUpNotifications() {
+        return !mHeadsUpEntries.isEmpty();
+    }
+
+    @Nullable
+    protected HeadsUpEntry getTopHeadsUpEntry() {
         if (mHeadsUpEntries.isEmpty()) {
             return null;
         }
         HeadsUpEntry topEntry = null;
         for (HeadsUpEntry entry: mHeadsUpEntries.values()) {
-            if (topEntry == null || entry.compareTo(topEntry) == -1) {
+            if (topEntry == null || entry.compareTo(topEntry) < 0) {
                 topEntry = entry;
             }
         }
@@ -387,56 +342,22 @@
     }
 
     /**
-     * Decides whether a click is invalid for a notification, i.e it has not been shown long enough
-     * that a user might have consciously clicked on it.
-     *
-     * @param key the key of the touched notification
-     * @return whether the touch is invalid and should be discarded
+     * Sets the current user.
      */
-    public boolean shouldSwallowClick(String key) {
-        HeadsUpEntry entry = mHeadsUpEntries.get(key);
-        if (entry != null && mClock.currentTimeMillis() < entry.postTime) {
-            return true;
-        }
-        return false;
-    }
-
-    public void onComputeInternalInsets(ViewTreeObserver.InternalInsetsInfo info) {
-        if (mIsExpanded || mBar.isBouncerShowing()) {
-            // The touchable region is always the full area when expanded
-            return;
-        }
-        if (mHasPinnedNotification) {
-            ExpandableNotificationRow topEntry = getTopEntry().entry.row;
-            if (topEntry.isChildInGroup()) {
-                final ExpandableNotificationRow groupSummary
-                        = mGroupManager.getGroupSummary(topEntry.getStatusBarNotification());
-                if (groupSummary != null) {
-                    topEntry = groupSummary;
-                }
-            }
-            topEntry.getLocationOnScreen(mTmpTwoArray);
-            int minX = mTmpTwoArray[0];
-            int maxX = mTmpTwoArray[0] + topEntry.getWidth();
-            int maxY = topEntry.getIntrinsicHeight();
-
-            info.setTouchableInsets(ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION);
-            info.touchableRegion.set(minX, 0, maxX, maxY);
-        } else if (mHeadsUpGoingAway || mWaitingOnCollapseWhenGoingAway) {
-            info.setTouchableInsets(ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION);
-            info.touchableRegion.set(0, 0, mStatusBarWindowView.getWidth(), mStatusBarHeight);
-        }
-    }
-
     public void setUser(int user) {
         mUser = user;
     }
 
-    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+    public void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw, @NonNull String[] args) {
         pw.println("HeadsUpManager state:");
+        dumpInternal(fd, pw, args);
+    }
+
+    protected void dumpInternal(
+            @NonNull FileDescriptor fd, @NonNull PrintWriter pw, @NonNull String[] args) {
         pw.print("  mTouchAcceptanceDelay="); pw.println(mTouchAcceptanceDelay);
         pw.print("  mSnoozeLengthMs="); pw.println(mSnoozeLengthMs);
-        pw.print("  now="); pw.println(SystemClock.elapsedRealtime());
+        pw.print("  now="); pw.println(mClock.currentTimeMillis());
         pw.print("  mUser="); pw.println(mUser);
         for (HeadsUpEntry entry: mHeadsUpEntries.values()) {
             pw.print("  HeadsUpEntry="); pw.println(entry.entry);
@@ -449,6 +370,9 @@
         }
     }
 
+    /**
+     * Returns if there are any pinned Heads Up Notifications or not.
+     */
     public boolean hasPinnedHeadsUp() {
         return mHasPinnedNotification;
     }
@@ -464,14 +388,8 @@
     }
 
     /**
-     * Notifies that a notification was swiped out and will be removed.
-     *
-     * @param key the notification key
+     * Unpins all pinned Heads Up Notifications.
      */
-    public void addSwipedOutNotification(String key) {
-        mSwipedOutKeys.add(key);
-    }
-
     public void unpinAll() {
         for (String key : mHeadsUpEntries.keySet()) {
             HeadsUpEntry entry = mHeadsUpEntries.get(key);
@@ -481,60 +399,13 @@
         }
     }
 
-    public void onExpandingFinished() {
-        if (mReleaseOnExpandFinish) {
-            releaseAllImmediately();
-            mReleaseOnExpandFinish = false;
-        } else {
-            for (NotificationData.Entry entry : mEntriesToRemoveAfterExpand) {
-                if (isHeadsUp(entry.key)) {
-                    // Maybe the heads-up was removed already
-                    removeHeadsUpEntry(entry);
-                }
-            }
-        }
-        mEntriesToRemoveAfterExpand.clear();
-    }
-
-    public void setTrackingHeadsUp(boolean trackingHeadsUp) {
-        mTrackingHeadsUp = trackingHeadsUp;
-    }
-
-    public boolean isTrackingHeadsUp() {
-        return mTrackingHeadsUp;
-    }
-
-    public void setIsExpanded(boolean isExpanded) {
-        if (isExpanded != mIsExpanded) {
-            mIsExpanded = isExpanded;
-            if (isExpanded) {
-                // make sure our state is sane
-                mWaitingOnCollapseWhenGoingAway = false;
-                mHeadsUpGoingAway = false;
-                updateTouchableRegionListener();
-            }
-        }
-    }
-
     /**
-     * @return the height of the top heads up notification when pinned. This is different from the
-     *         intrinsic height, which also includes whether the notification is system expanded and
-     *         is mainly used when dragging down from a heads up notification.
+     * Returns the value of the tracking-heads-up flag. See the doc of {@code setTrackingHeadsUp} as
+     * well.
      */
-    public int getTopHeadsUpPinnedHeight() {
-        HeadsUpEntry topEntry = getTopEntry();
-        if (topEntry == null || topEntry.entry == null) {
-            return 0;
-        }
-        ExpandableNotificationRow row = topEntry.entry.row;
-        if (row.isChildInGroup()) {
-            final ExpandableNotificationRow groupSummary
-                    = mGroupManager.getGroupSummary(row.getStatusBarNotification());
-            if (groupSummary != null) {
-                row = groupSummary;
-            }
-        }
-        return row.getPinnedHeadsUpHeight();
+    public boolean isTrackingHeadsUp() {
+        // Might be implemented in subclass.
+        return false;
     }
 
     /**
@@ -543,7 +414,7 @@
      * @return -1 if the first argument should be ranked higher than the second, 1 if the second
      * one should be ranked higher and 0 if they are equal.
      */
-    public int compare(NotificationData.Entry a, NotificationData.Entry b) {
+    public int compare(@NonNull NotificationData.Entry a, @NonNull NotificationData.Entry b) {
         HeadsUpEntry aEntry = getHeadsUpEntry(a.key);
         HeadsUpEntry bEntry = getHeadsUpEntry(b.key);
         if (aEntry == null || bEntry == null) {
@@ -553,147 +424,62 @@
     }
 
     /**
-     * Set that we are exiting the headsUp pinned mode, but some notifications might still be
-     * animating out. This is used to keep the touchable regions in a sane state.
-     */
-    public void setHeadsUpGoingAway(boolean headsUpGoingAway) {
-        if (headsUpGoingAway != mHeadsUpGoingAway) {
-            mHeadsUpGoingAway = headsUpGoingAway;
-            if (!headsUpGoingAway) {
-                waitForStatusBarLayout();
-            }
-            updateTouchableRegionListener();
-        }
-    }
-
-    /**
-     * We need to wait on the whole panel to collapse, before we can remove the touchable region
-     * listener.
-     */
-    private void waitForStatusBarLayout() {
-        mWaitingOnCollapseWhenGoingAway = true;
-        mStatusBarWindowView.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
-            @Override
-            public void onLayoutChange(View v, int left, int top, int right, int bottom,
-                    int oldLeft,
-                    int oldTop, int oldRight, int oldBottom) {
-                if (mStatusBarWindowView.getHeight() <= mStatusBarHeight) {
-                    mStatusBarWindowView.removeOnLayoutChangeListener(this);
-                    mWaitingOnCollapseWhenGoingAway = false;
-                    updateTouchableRegionListener();
-                }
-            }
-        });
-    }
-
-    public static void setIsClickedNotification(View child, boolean clicked) {
-        child.setTag(TAG_CLICKED_NOTIFICATION, clicked ? true : null);
-    }
-
-    public static boolean isClickedHeadsUpNotification(View child) {
-        Boolean clicked = (Boolean) child.getTag(TAG_CLICKED_NOTIFICATION);
-        return clicked != null && clicked;
-    }
-
-    public void setRemoteInputActive(NotificationData.Entry entry, boolean remoteInputActive) {
-        HeadsUpEntry headsUpEntry = mHeadsUpEntries.get(entry.key);
-        if (headsUpEntry != null && headsUpEntry.remoteInputActive != remoteInputActive) {
-            headsUpEntry.remoteInputActive = remoteInputActive;
-            if (remoteInputActive) {
-                headsUpEntry.removeAutoRemovalCallbacks();
-            } else {
-                headsUpEntry.updateEntry(false /* updatePostTime */);
-            }
-        }
-    }
-
-    /**
      * Set an entry to be expanded and therefore stick in the heads up area if it's pinned
      * until it's collapsed again.
      */
-    public void setExpanded(NotificationData.Entry entry, boolean expanded) {
-        HeadsUpEntry headsUpEntry = mHeadsUpEntries.get(entry.key);
-        if (headsUpEntry != null && headsUpEntry.expanded != expanded && entry.row.isPinned()) {
-            headsUpEntry.expanded = expanded;
-            if (expanded) {
-                headsUpEntry.removeAutoRemovalCallbacks();
-            } else {
-                headsUpEntry.updateEntry(false /* updatePostTime */);
-            }
+    public void setExpanded(@NonNull NotificationData.Entry entry, boolean expanded) {
+        HeadsUpManager.HeadsUpEntry headsUpEntry = mHeadsUpEntries.get(entry.key);
+        if (headsUpEntry != null && entry.row.isPinned()) {
+            headsUpEntry.expanded(expanded);
         }
     }
 
-    @Override
-    public void onReorderingAllowed() {
-        mBar.getNotificationScrollLayout().setHeadsUpGoingAwayAnimationsAllowed(false);
-        for (NotificationData.Entry entry : mEntriesToRemoveWhenReorderingAllowed) {
-            if (isHeadsUp(entry.key)) {
-                // Maybe the heads-up was removed already
-                removeHeadsUpEntry(entry);
-            }
-        }
-        mEntriesToRemoveWhenReorderingAllowed.clear();
-        mBar.getNotificationScrollLayout().setHeadsUpGoingAwayAnimationsAllowed(true);
+    @NonNull
+    protected HeadsUpEntry createHeadsUpEntry() {
+        return new HeadsUpEntry();
     }
 
-    public void setVisualStabilityManager(VisualStabilityManager visualStabilityManager) {
-        mVisualStabilityManager = visualStabilityManager;
-    }
-
-    public void setStatusBarState(int statusBarState) {
-        mStatusBarState = statusBarState;
+    protected void releaseHeadsUpEntry(@NonNull HeadsUpEntry entry) {
+        entry.reset();
     }
 
     /**
      * This represents a notification and how long it is in a heads up mode. It also manages its
      * lifecycle automatically when created.
      */
-    public class HeadsUpEntry implements Comparable<HeadsUpEntry> {
-        public NotificationData.Entry entry;
+    protected class HeadsUpEntry implements Comparable<HeadsUpEntry> {
+        @Nullable public NotificationData.Entry entry;
         public long postTime;
-        public long earliestRemovaltime;
-        private Runnable mRemoveHeadsUpRunnable;
         public boolean remoteInputActive;
+        public long earliestRemovaltime;
         public boolean expanded;
 
-        public void setEntry(final NotificationData.Entry entry) {
+        @Nullable private Runnable mRemoveHeadsUpRunnable;
+
+        public void setEntry(@Nullable final NotificationData.Entry entry) {
+            setEntry(entry, null);
+        }
+
+        public void setEntry(@Nullable final NotificationData.Entry entry,
+                @Nullable Runnable removeHeadsUpRunnable) {
             this.entry = entry;
+            this.mRemoveHeadsUpRunnable = removeHeadsUpRunnable;
 
             // The actual post time will be just after the heads-up really slided in
             postTime = mClock.currentTimeMillis() + mTouchAcceptanceDelay;
-            mRemoveHeadsUpRunnable = new Runnable() {
-                @Override
-                public void run() {
-                    if (!mVisualStabilityManager.isReorderingAllowed()) {
-                        mEntriesToRemoveWhenReorderingAllowed.add(entry);
-                        mVisualStabilityManager.addReorderingAllowedCallback(HeadsUpManager.this);
-                    } else if (!mTrackingHeadsUp) {
-                        removeHeadsUpEntry(entry);
-                    } else {
-                        mEntriesToRemoveAfterExpand.add(entry);
-                    }
-                }
-            };
-            updateEntry();
-        }
-
-        public void updateEntry() {
-            updateEntry(true);
+            updateEntry(true /* updatePostTime */);
         }
 
         public void updateEntry(boolean updatePostTime) {
+            if (DEBUG) Log.v(TAG, "updateEntry");
+
             long currentTime = mClock.currentTimeMillis();
             earliestRemovaltime = currentTime + mMinimumDisplayTime;
             if (updatePostTime) {
                 postTime = Math.max(postTime, currentTime);
             }
             removeAutoRemovalCallbacks();
-            if (mEntriesToRemoveAfterExpand.contains(entry)) {
-                mEntriesToRemoveAfterExpand.remove(entry);
-            }
-            if (mEntriesToRemoveWhenReorderingAllowed.contains(entry)) {
-                mEntriesToRemoveWhenReorderingAllowed.remove(entry);
-            }
+
             if (!isSticky()) {
                 long finishTime = postTime + mHeadsUpNotificationDecay;
                 long removeDelay = Math.max(finishTime - currentTime, mMinimumDisplayTime);
@@ -707,7 +493,7 @@
         }
 
         @Override
-        public int compareTo(HeadsUpEntry o) {
+        public int compareTo(@NonNull HeadsUpEntry o) {
             boolean isPinned = entry.row.isPinned();
             boolean otherPinned = o.entry.row.isPinned();
             if (isPinned && !otherPinned) {
@@ -734,26 +520,29 @@
                             : -1;
         }
 
-        public void removeAutoRemovalCallbacks() {
-            mHandler.removeCallbacks(mRemoveHeadsUpRunnable);
-        }
-
-        public boolean wasShownLongEnough() {
-            return earliestRemovaltime < mClock.currentTimeMillis();
-        }
-
-        public void removeAsSoonAsPossible() {
-            removeAutoRemovalCallbacks();
-            mHandler.postDelayed(mRemoveHeadsUpRunnable,
-                    earliestRemovaltime - mClock.currentTimeMillis());
+        public void expanded(boolean expanded) {
+            this.expanded = expanded;
         }
 
         public void reset() {
-            removeAutoRemovalCallbacks();
             entry = null;
-            mRemoveHeadsUpRunnable = null;
             expanded = false;
             remoteInputActive = false;
+            removeAutoRemovalCallbacks();
+            mRemoveHeadsUpRunnable = null;
+        }
+
+        public void removeAutoRemovalCallbacks() {
+            if (mRemoveHeadsUpRunnable != null)
+                mHandler.removeCallbacks(mRemoveHeadsUpRunnable);
+        }
+
+        public void removeAsSoonAsPossible() {
+            if (mRemoveHeadsUpRunnable != null) {
+                removeAutoRemovalCallbacks();
+                mHandler.postDelayed(mRemoveHeadsUpRunnable,
+                        earliestRemovaltime - mClock.currentTimeMillis());
+            }
         }
     }
 
@@ -762,5 +551,4 @@
             return SystemClock.elapsedRealtime();
         }
     }
-
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpUtil.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpUtil.java
new file mode 100644
index 0000000..1e3c123c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpUtil.java
@@ -0,0 +1,47 @@
+/*
+ * 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.systemui.statusbar.policy;
+
+import android.view.View;
+
+import com.android.systemui.R;
+
+/**
+ * A class of utility static methods for heads up notifications.
+ */
+public final class HeadsUpUtil {
+    private static final int TAG_CLICKED_NOTIFICATION = R.id.is_clicked_heads_up_tag;
+
+    /**
+     * Set the given view as clicked or not-clicked.
+     * @param view The view to be set the flag to.
+     * @param clicked True to set as clicked. False to not-clicked.
+     */
+    public static void setIsClickedHeadsUpNotification(View view, boolean clicked) {
+        view.setTag(TAG_CLICKED_NOTIFICATION, clicked ? true : null);
+    }
+
+    /**
+     * Check if the given view has the flag of "clicked notification"
+     * @param view The view to be checked.
+     * @return True if the view has clicked. False othrewise.
+     */
+    public static boolean isClickedHeadsUpNotification(View view) {
+        Boolean clicked = (Boolean) view.getTag(TAG_CLICKED_NOTIFICATION);
+        return clicked != null && clicked;
+    }
+}
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 077c6c3..98bebec 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
@@ -27,8 +27,12 @@
 import android.metrics.LogMaker;
 import android.os.AsyncTask;
 import android.os.Bundle;
+import android.os.RemoteException;
 import android.os.SystemClock;
+import android.os.VibrationEffect;
+import android.os.Vibrator;
 import android.util.AttributeSet;
+import android.util.Log;
 import android.util.TypedValue;
 import android.view.HapticFeedbackConstants;
 import android.view.InputDevice;
@@ -45,25 +49,32 @@
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.Dependency;
+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;
 
 public class KeyButtonView extends ImageView implements ButtonInterface {
+    private static final String TAG = KeyButtonView.class.getSimpleName();
 
     private final boolean mPlaySounds;
     private int mContentDescriptionRes;
     private long mDownTime;
     private int mCode;
     private int mTouchSlop;
+    private int mTouchDownX;
+    private int mTouchDownY;
     private boolean mSupportsLongpress = true;
     private AudioManager mAudioManager;
     private boolean mGestureAborted;
     private boolean mLongClicked;
     private OnClickListener mOnClickListener;
     private final KeyButtonRipple mRipple;
+    private final OverviewProxyService mOverviewProxyService;
+    private final Vibrator mVibrator;
     private final MetricsLogger mMetricsLogger = Dependency.get(MetricsLogger.class);
 
     private final Runnable mCheckLongPress = new Runnable() {
@@ -110,6 +121,8 @@
         mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
 
         mRipple = new KeyButtonRipple(context, this);
+        mVibrator = mContext.getSystemService(Vibrator.class);
+        mOverviewProxyService = Dependency.get(OverviewProxyService.class);
         setBackground(mRipple);
     }
 
@@ -189,6 +202,7 @@
     }
 
     public boolean onTouchEvent(MotionEvent ev) {
+        final boolean isProxyConnected = mOverviewProxyService.getProxy() != null;
         final int action = ev.getAction();
         int x, y;
         if (action == MotionEvent.ACTION_DOWN) {
@@ -203,23 +217,34 @@
                 mDownTime = SystemClock.uptimeMillis();
                 mLongClicked = false;
                 setPressed(true);
+                mTouchDownX = (int) ev.getX();
+                mTouchDownY = (int) ev.getY();
                 if (mCode != 0) {
                     sendEvent(KeyEvent.ACTION_DOWN, 0, mDownTime);
                 } else {
                     // Provide the same haptic feedback that the system offers for virtual keys.
                     performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY);
                 }
-                playSoundEffect(SoundEffectConstants.CLICK);
+                if (isProxyConnected) {
+                    // Provide small vibration for quick step or immediate down feedback
+                    AsyncTask.execute(() ->
+                            mVibrator.vibrate(VibrationEffect
+                                    .get(VibrationEffect.EFFECT_TICK, false)));
+                } else {
+                    playSoundEffect(SoundEffectConstants.CLICK);
+                }
                 removeCallbacks(mCheckLongPress);
                 postDelayed(mCheckLongPress, ViewConfiguration.getLongPressTimeout());
                 break;
             case MotionEvent.ACTION_MOVE:
                 x = (int)ev.getX();
                 y = (int)ev.getY();
-                setPressed(x >= -mTouchSlop
-                        && x < getWidth() + mTouchSlop
-                        && y >= -mTouchSlop
-                        && y < getHeight() + mTouchSlop);
+                boolean exceededTouchSlopX = Math.abs(x - mTouchDownX) > mTouchSlop;
+                boolean exceededTouchSlopY = Math.abs(y - mTouchDownY) > mTouchSlop;
+                if (exceededTouchSlopX || exceededTouchSlopY) {
+                    setPressed(false);
+                    removeCallbacks(mCheckLongPress);
+                }
                 break;
             case MotionEvent.ACTION_CANCEL:
                 setPressed(false);
@@ -231,13 +256,21 @@
             case MotionEvent.ACTION_UP:
                 final boolean doIt = isPressed() && !mLongClicked;
                 setPressed(false);
-                // Always send a release ourselves because it doesn't seem to be sent elsewhere
-                // and it feels weird to sometimes get a release haptic and other times not.
-                if ((SystemClock.uptimeMillis() - mDownTime) > 150 && !mLongClicked) {
+                if (isProxyConnected) {
+                    if (doIt) {
+                        performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY);
+                        playSoundEffect(SoundEffectConstants.CLICK);
+                    }
+                } else if ((SystemClock.uptimeMillis() - mDownTime) > 150 && !mLongClicked) {
+                    // Always send a release ourselves because it doesn't seem to be sent elsewhere
+                    // and it feels weird to sometimes get a release haptic and other times not.
                     performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY_RELEASE);
                 }
                 if (mCode != 0) {
                     if (doIt) {
+                        // If there was a pending remote recents animation, then we need to
+                        // cancel the animation now before we handle the button itself
+                        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 46455eb..4a3a173 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
@@ -36,8 +36,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..790135f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java
@@ -4,23 +4,105 @@
 import android.app.RemoteInput;
 import android.content.Context;
 import android.content.Intent;
+import android.content.res.TypedArray;
+import android.graphics.Canvas;
+import android.graphics.drawable.GradientDrawable;
+import android.graphics.drawable.RippleDrawable;
 import android.os.Bundle;
+import android.text.Layout;
+import android.text.TextPaint;
+import android.text.method.TransformationMethod;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.view.LayoutInflater;
+import android.view.View;
 import android.view.ViewGroup;
 import android.widget.Button;
-import android.widget.LinearLayout;
 
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.systemui.Dependency;
 import com.android.systemui.R;
 
+import java.text.BreakIterator;
+import java.util.Comparator;
+import java.util.PriorityQueue;
+
 /** View which displays smart reply buttons in notifications. */
-public class SmartReplyView extends LinearLayout {
+public class SmartReplyView extends ViewGroup {
 
     private static final String TAG = "SmartReplyView";
 
+    private static final int MEASURE_SPEC_ANY_WIDTH =
+            MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
+
+    private static final Comparator<View> DECREASING_MEASURED_WIDTH_WITHOUT_PADDING_COMPARATOR =
+            (v1, v2) -> ((v2.getMeasuredWidth() - v2.getPaddingLeft() - v2.getPaddingRight())
+                    - (v1.getMeasuredWidth() - v1.getPaddingLeft() - v1.getPaddingRight()));
+
+    private static final int SQUEEZE_FAILED = -1;
+
+    private final SmartReplyConstants mConstants;
+
+    /** Spacing to be applied between views. */
+    private final int mSpacing;
+
+    /** Horizontal padding of smart reply buttons if all of them use only one line of text. */
+    private final int mSingleLineButtonPaddingHorizontal;
+
+    /** Horizontal padding of smart reply buttons if at least one of them uses two lines of text. */
+    private final int mDoubleLineButtonPaddingHorizontal;
+
+    /** Increase in width of a smart reply button as a result of using two lines instead of one. */
+    private final int mSingleToDoubleLineButtonWidthIncrease;
+
+    private final BreakIterator mBreakIterator;
+
+    private PriorityQueue<Button> mCandidateButtonQueueForSqueezing;
+
     public SmartReplyView(Context context, AttributeSet attrs) {
         super(context, attrs);
+        mConstants = Dependency.get(SmartReplyConstants.class);
+
+        int spacing = 0;
+        int singleLineButtonPaddingHorizontal = 0;
+        int doubleLineButtonPaddingHorizontal = 0;
+
+        final TypedArray arr = context.obtainStyledAttributes(attrs, R.styleable.SmartReplyView,
+                0, 0);
+        final int length = arr.getIndexCount();
+        for (int i = 0; i < length; i++) {
+            int attr = arr.getIndex(i);
+            switch (attr) {
+                case R.styleable.SmartReplyView_spacing:
+                    spacing = arr.getDimensionPixelSize(i, 0);
+                    break;
+                case R.styleable.SmartReplyView_singleLineButtonPaddingHorizontal:
+                    singleLineButtonPaddingHorizontal = arr.getDimensionPixelSize(i, 0);
+                    break;
+                case R.styleable.SmartReplyView_doubleLineButtonPaddingHorizontal:
+                    doubleLineButtonPaddingHorizontal = arr.getDimensionPixelSize(i, 0);
+                    break;
+            }
+        }
+        arr.recycle();
+
+        mSpacing = spacing;
+        mSingleLineButtonPaddingHorizontal = singleLineButtonPaddingHorizontal;
+        mDoubleLineButtonPaddingHorizontal = doubleLineButtonPaddingHorizontal;
+        mSingleToDoubleLineButtonWidthIncrease =
+                2 * (doubleLineButtonPaddingHorizontal - singleLineButtonPaddingHorizontal);
+
+        mBreakIterator = BreakIterator.getLineInstance();
+        reallocateCandidateButtonQueueForSqueezing();
+    }
+
+    private void reallocateCandidateButtonQueueForSqueezing() {
+        // Instead of clearing the priority queue, we re-allocate so that it would fit all buttons
+        // exactly. This avoids (1) wasting memory because PriorityQueue never shrinks and
+        // (2) growing in onMeasure.
+        // The constructor throws an IllegalArgument exception if initial capacity is less than 1.
+        mCandidateButtonQueueForSqueezing = new PriorityQueue<>(
+                Math.max(getChildCount(), 1), DECREASING_MEASURED_WIDTH_WITHOUT_PADDING_COMPARATOR);
     }
 
     public void setRepliesFromRemoteInput(RemoteInput remoteInput, PendingIntent pendingIntent) {
@@ -35,6 +117,7 @@
                 }
             }
         }
+        reallocateCandidateButtonQueueForSqueezing();
     }
 
     public static SmartReplyView inflate(Context context, ViewGroup root) {
@@ -42,7 +125,8 @@
                 LayoutInflater.from(context).inflate(R.layout.smart_reply_view, root, false);
     }
 
-    private static Button inflateReplyButton(Context context, ViewGroup root, CharSequence choice,
+    @VisibleForTesting
+    static Button inflateReplyButton(Context context, ViewGroup root, CharSequence choice,
             RemoteInput remoteInput, PendingIntent pendingIntent) {
         Button b = (Button) LayoutInflater.from(context).inflate(
                 R.layout.smart_reply_button, root, false);
@@ -61,4 +145,376 @@
         });
         return b;
     }
+
+    @Override
+    public LayoutParams generateLayoutParams(AttributeSet attrs) {
+        return new LayoutParams(mContext, attrs);
+    }
+
+    @Override
+    protected LayoutParams generateDefaultLayoutParams() {
+        return new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
+    }
+
+    @Override
+    protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams params) {
+        return new LayoutParams(params.width, params.height);
+    }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        final int targetWidth = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.UNSPECIFIED
+                ? Integer.MAX_VALUE : MeasureSpec.getSize(widthMeasureSpec);
+
+        // Mark all buttons as hidden and un-squeezed.
+        resetButtonsLayoutParams();
+
+        if (!mCandidateButtonQueueForSqueezing.isEmpty()) {
+            Log.wtf(TAG, "Single line button queue leaked between onMeasure calls");
+            mCandidateButtonQueueForSqueezing.clear();
+        }
+
+        int measuredWidth = mPaddingLeft + mPaddingRight;
+        int maxChildHeight = 0;
+        int displayedChildCount = 0;
+        int buttonPaddingHorizontal = mSingleLineButtonPaddingHorizontal;
+
+        final int childCount = getChildCount();
+        for (int i = 0; i < childCount; i++) {
+            final View child = getChildAt(i);
+            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
+            if (child.getVisibility() != View.VISIBLE || !(child instanceof Button)) {
+                continue;
+            }
+
+            child.setPadding(buttonPaddingHorizontal, child.getPaddingTop(),
+                    buttonPaddingHorizontal, child.getPaddingBottom());
+            child.measure(MEASURE_SPEC_ANY_WIDTH, heightMeasureSpec);
+
+            final int lineCount = ((Button) child).getLineCount();
+            if (lineCount < 1 || lineCount > 2) {
+                // If smart reply has no text, or more than two lines, then don't show it.
+                continue;
+            }
+
+            if (lineCount == 1) {
+                mCandidateButtonQueueForSqueezing.add((Button) child);
+            }
+
+            // Remember the current measurements in case the current button doesn't fit in.
+            final int originalMaxChildHeight = maxChildHeight;
+            final int originalMeasuredWidth = measuredWidth;
+            final int originalButtonPaddingHorizontal = buttonPaddingHorizontal;
+
+            final int spacing = displayedChildCount == 0 ? 0 : mSpacing;
+            final int childWidth = child.getMeasuredWidth();
+            final int childHeight = child.getMeasuredHeight();
+            measuredWidth += spacing + childWidth;
+            maxChildHeight = Math.max(maxChildHeight, childHeight);
+
+            // Do we need to increase the number of lines in smart reply buttons to two?
+            final boolean increaseToTwoLines =
+                    buttonPaddingHorizontal == mSingleLineButtonPaddingHorizontal
+                            && (lineCount == 2 || measuredWidth > targetWidth);
+            if (increaseToTwoLines) {
+                measuredWidth += (displayedChildCount + 1) * mSingleToDoubleLineButtonWidthIncrease;
+                buttonPaddingHorizontal = mDoubleLineButtonPaddingHorizontal;
+            }
+
+            // If the last button doesn't fit into the remaining width, try squeezing preceding
+            // smart reply buttons.
+            if (measuredWidth > targetWidth) {
+                // Keep squeezing preceding and current smart reply buttons until they all fit.
+                while (measuredWidth > targetWidth
+                        && !mCandidateButtonQueueForSqueezing.isEmpty()) {
+                    final Button candidate = mCandidateButtonQueueForSqueezing.poll();
+                    final int squeezeReduction = squeezeButton(candidate, heightMeasureSpec);
+                    if (squeezeReduction != SQUEEZE_FAILED) {
+                        maxChildHeight = Math.max(maxChildHeight, candidate.getMeasuredHeight());
+                        measuredWidth -= squeezeReduction;
+                    }
+                }
+
+                // If the current button still doesn't fit after squeezing all buttons, undo the
+                // last squeezing round.
+                if (measuredWidth > targetWidth) {
+                    measuredWidth = originalMeasuredWidth;
+                    maxChildHeight = originalMaxChildHeight;
+                    buttonPaddingHorizontal = originalButtonPaddingHorizontal;
+
+                    // Mark all buttons from the last squeezing round as "failed to squeeze", so
+                    // that they're re-measured without squeezing later.
+                    markButtonsWithPendingSqueezeStatusAs(LayoutParams.SQUEEZE_STATUS_FAILED, i);
+
+                    // The current button doesn't fit, so there's no point in measuring further
+                    // buttons.
+                    break;
+                }
+
+                // The current button fits, so mark all squeezed buttons as "successfully squeezed"
+                // to prevent them from being un-squeezed in a subsequent squeezing round.
+                markButtonsWithPendingSqueezeStatusAs(LayoutParams.SQUEEZE_STATUS_SUCCESSFUL, i);
+            }
+
+            lp.show = true;
+            displayedChildCount++;
+        }
+
+        // We're done squeezing buttons, so we can clear the priority queue.
+        mCandidateButtonQueueForSqueezing.clear();
+
+        // Finally, we need to update corner radius and re-measure some buttons.
+        updateCornerRadiusAndRemeasureButtonsIfNecessary(buttonPaddingHorizontal, maxChildHeight);
+
+        setMeasuredDimension(
+                resolveSize(Math.max(getSuggestedMinimumWidth(), measuredWidth), widthMeasureSpec),
+                resolveSize(Math.max(getSuggestedMinimumHeight(),
+                        mPaddingTop + maxChildHeight + mPaddingBottom), heightMeasureSpec));
+    }
+
+    private void resetButtonsLayoutParams() {
+        final int childCount = getChildCount();
+        for (int i = 0; i < childCount; i++) {
+            final View child = getChildAt(i);
+            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
+            lp.show = false;
+            lp.squeezeStatus = LayoutParams.SQUEEZE_STATUS_NONE;
+        }
+    }
+
+    private int squeezeButton(Button button, int heightMeasureSpec) {
+        final int estimatedOptimalTextWidth = estimateOptimalSqueezedButtonTextWidth(button);
+        if (estimatedOptimalTextWidth == SQUEEZE_FAILED) {
+            return SQUEEZE_FAILED;
+        }
+        return squeezeButtonToTextWidth(button, heightMeasureSpec, estimatedOptimalTextWidth);
+    }
+
+    private int estimateOptimalSqueezedButtonTextWidth(Button button) {
+        // Find a line-break point in the middle of the smart reply button text.
+        final String rawText = button.getText().toString();
+
+        // The button sometimes has a transformation affecting text layout (e.g. all caps).
+        final TransformationMethod transformation = button.getTransformationMethod();
+        final String text = transformation == null ?
+                rawText : transformation.getTransformation(rawText, button).toString();
+        final int length = text.length();
+        mBreakIterator.setText(text);
+
+        if (mBreakIterator.preceding(length / 2) == BreakIterator.DONE) {
+            if (mBreakIterator.next() == BreakIterator.DONE) {
+                // Can't find a single possible line break in either direction.
+                return SQUEEZE_FAILED;
+            }
+        }
+
+        final TextPaint paint = button.getPaint();
+        final int initialPosition = mBreakIterator.current();
+        final float initialLeftTextWidth = Layout.getDesiredWidth(text, 0, initialPosition, paint);
+        final float initialRightTextWidth =
+                Layout.getDesiredWidth(text, initialPosition, length, paint);
+        float optimalTextWidth = Math.max(initialLeftTextWidth, initialRightTextWidth);
+
+        if (initialLeftTextWidth != initialRightTextWidth) {
+            // See if there's a better line-break point (leading to a more narrow button) in
+            // either left or right direction.
+            final boolean moveLeft = initialLeftTextWidth > initialRightTextWidth;
+            final int maxSqueezeRemeasureAttempts = mConstants.getMaxSqueezeRemeasureAttempts();
+            for (int i = 0; i < maxSqueezeRemeasureAttempts; i++) {
+                final int newPosition =
+                        moveLeft ? mBreakIterator.previous() : mBreakIterator.next();
+                if (newPosition == BreakIterator.DONE) {
+                    break;
+                }
+
+                final float newLeftTextWidth = Layout.getDesiredWidth(text, 0, newPosition, paint);
+                final float newRightTextWidth =
+                        Layout.getDesiredWidth(text, newPosition, length, paint);
+                final float newOptimalTextWidth = Math.max(newLeftTextWidth, newRightTextWidth);
+                if (newOptimalTextWidth < optimalTextWidth) {
+                    optimalTextWidth = newOptimalTextWidth;
+                } else {
+                    break;
+                }
+
+                boolean tooFar = moveLeft
+                        ? newLeftTextWidth <= newRightTextWidth
+                        : newLeftTextWidth >= newRightTextWidth;
+                if (tooFar) {
+                    break;
+                }
+            }
+        }
+
+        return (int) Math.ceil(optimalTextWidth);
+    }
+
+    private int squeezeButtonToTextWidth(Button button, int heightMeasureSpec, int textWidth) {
+        int oldWidth = button.getMeasuredWidth();
+        if (button.getPaddingLeft() != mDoubleLineButtonPaddingHorizontal) {
+            // Correct for the fact that the button was laid out with single-line horizontal
+            // padding.
+            oldWidth += mSingleToDoubleLineButtonWidthIncrease;
+        }
+
+        // Re-measure the squeezed smart reply button.
+        button.setPadding(mDoubleLineButtonPaddingHorizontal, button.getPaddingTop(),
+                mDoubleLineButtonPaddingHorizontal, button.getPaddingBottom());
+        final int widthMeasureSpec = MeasureSpec.makeMeasureSpec(
+                2 * mDoubleLineButtonPaddingHorizontal + textWidth, MeasureSpec.AT_MOST);
+        button.measure(widthMeasureSpec, heightMeasureSpec);
+
+        final int newWidth = button.getMeasuredWidth();
+
+        final LayoutParams lp = (LayoutParams) button.getLayoutParams();
+        if (button.getLineCount() > 2 || newWidth >= oldWidth) {
+            lp.squeezeStatus = LayoutParams.SQUEEZE_STATUS_FAILED;
+            return SQUEEZE_FAILED;
+        } else {
+            lp.squeezeStatus = LayoutParams.SQUEEZE_STATUS_PENDING;
+            return oldWidth - newWidth;
+        }
+    }
+
+    private void updateCornerRadiusAndRemeasureButtonsIfNecessary(
+            int buttonPaddingHorizontal, int maxChildHeight) {
+        final float cornerRadius = ((float) maxChildHeight) / 2;
+        final int maxChildHeightMeasure =
+                MeasureSpec.makeMeasureSpec(maxChildHeight, MeasureSpec.EXACTLY);
+
+        final int childCount = getChildCount();
+        for (int i = 0; i < childCount; i++) {
+            final View child = getChildAt(i);
+            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
+            if (!lp.show) {
+                continue;
+            }
+
+            // Update corner radius.
+            GradientDrawable backgroundDrawable =
+                    (GradientDrawable) ((RippleDrawable) child.getBackground()).getDrawable(0);
+            backgroundDrawable.setCornerRadius(cornerRadius);
+
+            boolean requiresNewMeasure = false;
+            int newWidth = child.getMeasuredWidth();
+
+            // Re-measure reason 1: The button needs to be un-squeezed (either because it resulted
+            // in more than two lines or because it was unnecessary).
+            if (lp.squeezeStatus == LayoutParams.SQUEEZE_STATUS_FAILED) {
+                requiresNewMeasure = true;
+                newWidth = Integer.MAX_VALUE;
+            }
+
+            // Re-measure reason 2: The button's horizontal padding is incorrect (because it was
+            // measured with the wrong number of lines).
+            if (child.getPaddingLeft() != buttonPaddingHorizontal) {
+                requiresNewMeasure = true;
+                if (buttonPaddingHorizontal == mSingleLineButtonPaddingHorizontal) {
+                    // Decrease padding (2->1 line).
+                    newWidth -= mSingleToDoubleLineButtonWidthIncrease;
+                } else {
+                    // Increase padding (1->2 lines).
+                    newWidth += mSingleToDoubleLineButtonWidthIncrease;
+                }
+                child.setPadding(buttonPaddingHorizontal, child.getPaddingTop(),
+                        buttonPaddingHorizontal, child.getPaddingBottom());
+            }
+
+            // Re-measure reason 3: The button's height is less than the max height of all buttons
+            // (all should have the same height).
+            if (child.getMeasuredHeight() != maxChildHeight) {
+                requiresNewMeasure = true;
+            }
+
+            if (requiresNewMeasure) {
+                child.measure(MeasureSpec.makeMeasureSpec(newWidth, MeasureSpec.AT_MOST),
+                        maxChildHeightMeasure);
+            }
+        }
+    }
+
+    private void markButtonsWithPendingSqueezeStatusAs(int squeezeStatus, int maxChildIndex) {
+        for (int i = 0; i <= maxChildIndex; i++) {
+            final View child = getChildAt(i);
+            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
+            if (lp.squeezeStatus == LayoutParams.SQUEEZE_STATUS_PENDING) {
+                lp.squeezeStatus = squeezeStatus;
+            }
+        }
+    }
+
+    @Override
+    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+        final boolean isRtl = getLayoutDirection() == View.LAYOUT_DIRECTION_RTL;
+
+        final int width = right - left;
+        int position = isRtl ? width - mPaddingRight : mPaddingLeft;
+
+        final int childCount = getChildCount();
+        for (int i = 0; i < childCount; i++) {
+            final View child = getChildAt(i);
+            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
+            if (!lp.show) {
+                continue;
+            }
+
+            final int childWidth = child.getMeasuredWidth();
+            final int childHeight = child.getMeasuredHeight();
+            final int childLeft = isRtl ? position - childWidth : position;
+            child.layout(childLeft, 0, childLeft + childWidth, childHeight);
+
+            final int childWidthWithSpacing = childWidth + mSpacing;
+            if (isRtl) {
+                position -= childWidthWithSpacing;
+            } else {
+                position += childWidthWithSpacing;
+            }
+        }
+    }
+
+    @Override
+    protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
+        final LayoutParams lp = (LayoutParams) child.getLayoutParams();
+        return lp.show && super.drawChild(canvas, child, drawingTime);
+    }
+
+    @VisibleForTesting
+    static class LayoutParams extends ViewGroup.LayoutParams {
+
+        /** Button is not squeezed. */
+        private static final int SQUEEZE_STATUS_NONE = 0;
+
+        /**
+         * Button was successfully squeezed, but it might be un-squeezed later if the squeezing
+         * turns out to have been unnecessary (because there's still not enough space to add another
+         * button).
+         */
+        private static final int SQUEEZE_STATUS_PENDING = 1;
+
+        /** Button was successfully squeezed and it won't be un-squeezed. */
+        private static final int SQUEEZE_STATUS_SUCCESSFUL = 2;
+
+        /**
+         * Button wasn't successfully squeezed. The squeezing resulted in more than two lines of
+         * text or it didn't reduce the button's width at all. The button will have to be
+         * re-measured to use only one line of text.
+         */
+        private static final int SQUEEZE_STATUS_FAILED = 3;
+
+        private boolean show = false;
+        private int squeezeStatus = SQUEEZE_STATUS_NONE;
+
+        private LayoutParams(Context c, AttributeSet attrs) {
+            super(c, attrs);
+        }
+
+        private LayoutParams(int width, int height) {
+            super(width, height);
+        }
+
+        @VisibleForTesting
+        boolean isShown() {
+            return show;
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java
index 424858a..d7a810e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java
@@ -64,7 +64,7 @@
     private boolean mPanelTracking;
     private boolean mExpansionChanging;
     private boolean mPanelFullWidth;
-    private Collection<HeadsUpManager.HeadsUpEntry> mPulsing;
+    private boolean mPulsing;
     private boolean mUnlockHintRunning;
     private boolean mQsCustomizerShowing;
     private int mIntrinsicPadding;
@@ -315,23 +315,18 @@
     }
 
     public boolean hasPulsingNotifications() {
-        return mPulsing != null;
+        return mPulsing;
     }
 
-    public void setPulsing(Collection<HeadsUpManager.HeadsUpEntry> hasPulsing) {
+    public void setPulsing(boolean hasPulsing) {
         mPulsing = hasPulsing;
     }
 
     public boolean isPulsing(NotificationData.Entry entry) {
-        if (mPulsing == null) {
+        if (!mPulsing || mHeadsUpManager == null) {
             return false;
         }
-        for (HeadsUpManager.HeadsUpEntry e : mPulsing) {
-            if (e.entry == entry) {
-                return true;
-            }
-        }
-        return false;
+        return mHeadsUpManager.getAllEntries().anyMatch(e -> (e == entry));
     }
 
     public boolean isPanelTracking() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index c114a6f..1b55a5b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -92,10 +92,11 @@
 import com.android.systemui.statusbar.notification.FakeShadowView;
 import com.android.systemui.statusbar.notification.NotificationUtils;
 import com.android.systemui.statusbar.notification.VisibilityLocationProvider;
+import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
 import com.android.systemui.statusbar.phone.NotificationGroupManager;
 import com.android.systemui.statusbar.phone.StatusBar;
 import com.android.systemui.statusbar.phone.ScrimController;
-import com.android.systemui.statusbar.policy.HeadsUpManager;
+import com.android.systemui.statusbar.policy.HeadsUpUtil;
 import com.android.systemui.statusbar.policy.ScrollAdapter;
 
 import android.support.v4.graphics.ColorUtils;
@@ -288,7 +289,7 @@
     private HashSet<View> mClearOverlayViewsWhenFinished = new HashSet<>();
     private HashSet<Pair<ExpandableNotificationRow, Boolean>> mHeadsUpChangeAnimations
             = new HashSet<>();
-    private HeadsUpManager mHeadsUpManager;
+    private HeadsUpManagerPhone mHeadsUpManager;
     private boolean mTrackingHeadsUp;
     private ScrimController mScrimController;
     private boolean mForceNoOverlappingRendering;
@@ -358,7 +359,7 @@
         }
     };
     private PorterDuffXfermode mSrcMode = new PorterDuffXfermode(PorterDuff.Mode.SRC);
-    private Collection<HeadsUpManager.HeadsUpEntry> mPulsing;
+    private boolean mPulsing;
     private boolean mDrawBackgroundAsSrc;
     private boolean mFadingOut;
     private boolean mParentNotFullyVisible;
@@ -690,7 +691,7 @@
     }
 
     private void updateAlgorithmHeightAndPadding() {
-        if (mPulsing != null) {
+        if (mPulsing) {
             mTopPadding = mClockBottom;
         } else {
             mTopPadding = mAmbientState.isDark() ? mDarkTopPadding : mRegularTopPadding;
@@ -920,6 +921,27 @@
     }
 
     /**
+     * @return the height of the top heads up notification when pinned. This is different from the
+     *         intrinsic height, which also includes whether the notification is system expanded and
+     *         is mainly used when dragging down from a heads up notification.
+     */
+    private int getTopHeadsUpPinnedHeight() {
+        NotificationData.Entry topEntry = mHeadsUpManager.getTopEntry();
+        if (topEntry == null) {
+            return 0;
+        }
+        ExpandableNotificationRow row = topEntry.row;
+        if (row.isChildInGroup()) {
+            final ExpandableNotificationRow groupSummary
+                    = mGroupManager.getGroupSummary(row.getStatusBarNotification());
+            if (groupSummary != null) {
+                row = groupSummary;
+            }
+        }
+        return row.getPinnedHeadsUpHeight();
+    }
+
+    /**
      * @return the position from where the appear transition ends when expanding.
      *         Measured in absolute height.
      */
@@ -930,7 +952,7 @@
             int minNotificationsForShelf = 1;
             if (mTrackingHeadsUp
                     || (mHeadsUpManager.hasPinnedHeadsUp() && !mAmbientState.isDark())) {
-                appearPosition = mHeadsUpManager.getTopHeadsUpPinnedHeight();
+                appearPosition = getTopHeadsUpPinnedHeight();
                 minNotificationsForShelf = 2;
             } else {
                 appearPosition = 0;
@@ -1198,9 +1220,9 @@
                 if (slidingChild instanceof ExpandableNotificationRow) {
                     ExpandableNotificationRow row = (ExpandableNotificationRow) slidingChild;
                     if (!mIsExpanded && row.isHeadsUp() && row.isPinned()
-                            && mHeadsUpManager.getTopEntry().entry.row != row
+                            && mHeadsUpManager.getTopEntry().row != row
                             && mGroupManager.getGroupSummary(
-                                mHeadsUpManager.getTopEntry().entry.row.getStatusBarNotification())
+                                mHeadsUpManager.getTopEntry().row.getStatusBarNotification())
                                 != row) {
                         continue;
                     }
@@ -2120,7 +2142,7 @@
 
     @Override
     public boolean hasPulsingNotifications() {
-        return mPulsing != null;
+        return mPulsing;
     }
 
     private void updateScrollability() {
@@ -2753,7 +2775,7 @@
     }
 
     private boolean isClickedHeadsUp(View child) {
-        return HeadsUpManager.isClickedHeadsUpNotification(child);
+        return HeadsUpUtil.isClickedHeadsUpNotification(child);
     }
 
     /**
@@ -4258,7 +4280,7 @@
         mAnimationFinishedRunnables.add(runnable);
     }
 
-    public void setHeadsUpManager(HeadsUpManager headsUpManager) {
+    public void setHeadsUpManager(HeadsUpManagerPhone headsUpManager) {
         mHeadsUpManager = headsUpManager;
         mAmbientState.setHeadsUpManager(headsUpManager);
     }
@@ -4326,8 +4348,8 @@
         return mIsExpanded;
     }
 
-    public void setPulsing(Collection<HeadsUpManager.HeadsUpEntry> pulsing, int clockBottom) {
-        if (mPulsing == null && pulsing == null) {
+    public void setPulsing(boolean pulsing, int clockBottom) {
+        if (!mPulsing && !pulsing) {
             return;
         }
         mPulsing = pulsing;
@@ -4466,7 +4488,7 @@
         pw.println(String.format("[%s: pulsing=%s qsCustomizerShowing=%s visibility=%s"
                         + " alpha:%f scrollY:%d]",
                 this.getClass().getSimpleName(),
-                mPulsing != null ?"T":"f",
+                mPulsing ? "T":"f",
                 mAmbientState.isQsCustomizerShowing() ? "T":"f",
                 getVisibility() == View.VISIBLE ? "visible"
                         : getVisibility() == View.GONE ? "gone"
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/ViewState.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/ViewState.java
index 682b849..04a7bd7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/ViewState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/ViewState.java
@@ -30,7 +30,7 @@
 import com.android.systemui.statusbar.ExpandableView;
 import com.android.systemui.statusbar.notification.AnimatableProperty;
 import com.android.systemui.statusbar.notification.PropertyAnimator;
-import com.android.systemui.statusbar.policy.HeadsUpManager;
+import com.android.systemui.statusbar.policy.HeadsUpUtil;
 
 /**
  * A state of a view. This can be used to apply a set of view properties to a view with
@@ -582,7 +582,7 @@
         animator.addListener(new AnimatorListenerAdapter() {
             @Override
             public void onAnimationEnd(Animator animation) {
-                HeadsUpManager.setIsClickedNotification(child, false);
+                HeadsUpUtil.setIsClickedHeadsUpNotification(child, false);
                 child.setTag(TAG_ANIMATOR_TRANSLATION_Y, null);
                 child.setTag(TAG_START_TRANSLATION_Y, null);
                 child.setTag(TAG_END_TRANSLATION_Y, null);
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/NavBarTuner.java b/packages/SystemUI/src/com/android/systemui/tuner/NavBarTuner.java
index 45abd45..eb0c89b 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/NavBarTuner.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/NavBarTuner.java
@@ -18,7 +18,7 @@
 import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.KEY_CODE_END;
 import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.KEY_CODE_START;
 import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.KEY_IMAGE_DELIM;
-import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.MENU_IME;
+import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.MENU_IME_ROTATE;
 import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.NAVSPACE;
 import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.NAV_BAR_LEFT;
 import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.NAV_BAR_RIGHT;
@@ -29,24 +29,14 @@
 
 import android.annotation.Nullable;
 import android.app.AlertDialog;
-import android.content.DialogInterface;
-import android.content.DialogInterface.OnClickListener;
-import android.content.res.Resources;
 import android.graphics.Color;
-import android.graphics.Paint;
-import android.graphics.Paint.FontMetricsInt;
-import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.Icon;
 import android.os.Bundle;
 import android.os.Handler;
-import android.support.v14.preference.PreferenceFragment;
-import android.support.v7.preference.DropDownPreference;
 import android.support.v7.preference.ListPreference;
 import android.support.v7.preference.Preference;
 import android.support.v7.preference.Preference.OnPreferenceChangeListener;
-import android.support.v7.preference.Preference.OnPreferenceClickListener;
-import android.support.v7.preference.PreferenceCategory;
 import android.text.SpannableStringBuilder;
 import android.text.style.ImageSpan;
 import android.util.Log;
@@ -56,7 +46,6 @@
 
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
-import com.android.systemui.statusbar.phone.NavigationBarInflaterView;
 import com.android.systemui.tuner.TunerService.Tunable;
 
 import java.util.ArrayList;
@@ -100,7 +89,7 @@
         addPreferencesFromResource(R.xml.nav_bar_tuner);
         bindLayout((ListPreference) findPreference(LAYOUT));
         bindButton(NAV_BAR_LEFT, NAVSPACE, LEFT);
-        bindButton(NAV_BAR_RIGHT, MENU_IME, RIGHT);
+        bindButton(NAV_BAR_RIGHT, MENU_IME_ROTATE, RIGHT);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/volume/OutputChooserDialog.java b/packages/SystemUI/src/com/android/systemui/volume/OutputChooserDialog.java
index 5c888ac..6ed07f8 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/OutputChooserDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/OutputChooserDialog.java
@@ -49,6 +49,8 @@
 import android.view.Window;
 import android.view.WindowManager;
 
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.nano.MetricsProto;
 import com.android.settingslib.Utils;
 import com.android.settingslib.bluetooth.CachedBluetoothDevice;
 import com.android.systemui.Dependency;
@@ -81,6 +83,7 @@
     private final MediaRouterWrapper mRouter;
     private final MediaRouterCallback mRouterCallback;
     private long mLastUpdateTime;
+    static final boolean INCLUDE_MEDIA_ROUTES = false;
     private boolean mIsInCall;
     protected boolean isAttached;
 
@@ -174,7 +177,7 @@
     public void onAttachedToWindow() {
         super.onAttachedToWindow();
 
-        if (!mIsInCall) {
+        if (!mIsInCall && INCLUDE_MEDIA_ROUTES) {
             mRouter.addCallback(mRouteSelector, mRouterCallback,
                     MediaRouter.CALLBACK_FLAG_PERFORM_ACTIVE_SCAN);
         }
@@ -201,6 +204,7 @@
     @Override
     public void show() {
         super.show();
+        Dependency.get(MetricsLogger.class).visible(MetricsProto.MetricsEvent.OUTPUT_CHOOSER);
         mHardwareLayout.setTranslationX(getAnimTranslation());
         mHardwareLayout.setAlpha(0);
         mHardwareLayout.animate()
@@ -214,6 +218,7 @@
 
     @Override
     public void dismiss() {
+        Dependency.get(MetricsLogger.class).hidden(MetricsProto.MetricsEvent.OUTPUT_CHOOSER);
         mHardwareLayout.setTranslationX(0);
         mHardwareLayout.setAlpha(1);
         mHardwareLayout.animate()
@@ -236,11 +241,15 @@
         if (item.deviceType == OutputChooserLayout.Item.DEVICE_TYPE_BT) {
             final CachedBluetoothDevice device = (CachedBluetoothDevice) item.tag;
             if (device.getMaxConnectionState() == BluetoothProfile.STATE_DISCONNECTED) {
+                Dependency.get(MetricsLogger.class).action(
+                        MetricsProto.MetricsEvent.ACTION_OUTPUT_CHOOSER_CONNECT);
                 mBluetoothController.connect(device);
             }
         } else if (item.deviceType == OutputChooserLayout.Item.DEVICE_TYPE_MEDIA_ROUTER) {
             final MediaRouter.RouteInfo route = (MediaRouter.RouteInfo) item.tag;
             if (route.isEnabled()) {
+                Dependency.get(MetricsLogger.class).action(
+                        MetricsProto.MetricsEvent.ACTION_OUTPUT_CHOOSER_CONNECT);
                 route.select();
             }
         }
@@ -251,8 +260,12 @@
         if (item == null || item.tag == null) return;
         if (item.deviceType == OutputChooserLayout.Item.DEVICE_TYPE_BT) {
             final CachedBluetoothDevice device = (CachedBluetoothDevice) item.tag;
+            Dependency.get(MetricsLogger.class).action(
+                    MetricsProto.MetricsEvent.ACTION_OUTPUT_CHOOSER_DISCONNECT);
             mBluetoothController.disconnect(device);
         } else if (item.deviceType == OutputChooserLayout.Item.DEVICE_TYPE_MEDIA_ROUTER) {
+            Dependency.get(MetricsLogger.class).action(
+                    MetricsProto.MetricsEvent.ACTION_OUTPUT_CHOOSER_DISCONNECT);
             mRouter.unselect(UNSELECT_REASON_DISCONNECTED);
         }
     }
@@ -272,7 +285,7 @@
         addBluetoothDevices(items);
 
         // Add remote displays
-        if (!mIsInCall) {
+        if (!mIsInCall && INCLUDE_MEDIA_ROUTES) {
             addRemoteDisplayRoutes(items);
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java
index efa8386..0203c43 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java
@@ -27,16 +27,15 @@
 import android.view.WindowManager.LayoutParams;
 
 import com.android.settingslib.applications.InterestingConfigChanges;
-import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.Dependency;
 import com.android.systemui.SystemUI;
 import com.android.systemui.keyguard.KeyguardViewMediator;
+import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.plugins.PluginDependencyProvider;
 import com.android.systemui.plugins.VolumeDialog;
 import com.android.systemui.plugins.VolumeDialogController;
 import com.android.systemui.qs.tiles.DndTile;
 import com.android.systemui.statusbar.policy.ExtensionController;
-import com.android.systemui.statusbar.policy.ExtensionController.Extension;
 import com.android.systemui.tuner.TunerService;
 
 import java.io.FileDescriptor;
@@ -53,8 +52,8 @@
     public static final String VOLUME_SILENT_DO_NOT_DISTURB = "sysui_do_not_disturb";
 
     public static final boolean DEFAULT_VOLUME_DOWN_TO_ENTER_SILENT = false;
-    public static final boolean DEFAULT_VOLUME_UP_TO_EXIT_SILENT = true;
-    public static final boolean DEFAULT_DO_NOT_DISTURB_WHEN_SILENT = true;
+    public static final boolean DEFAULT_VOLUME_UP_TO_EXIT_SILENT = false;
+    public static final boolean DEFAULT_DO_NOT_DISTURB_WHEN_SILENT = false;
 
     private final SystemUI mSysui;
     private final Context mContext;
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
index a131a61..1e8e98c 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
@@ -37,6 +37,7 @@
 import android.content.res.ColorStateList;
 import android.content.res.Resources;
 import android.graphics.Color;
+import android.graphics.PixelFormat;
 import android.graphics.drawable.ColorDrawable;
 import android.media.AudioManager;
 import android.media.AudioSystem;
@@ -54,6 +55,7 @@
 import android.util.Slog;
 import android.util.SparseBooleanArray;
 import android.view.ContextThemeWrapper;
+import android.view.Gravity;
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.View.AccessibilityDelegate;
@@ -66,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;
@@ -107,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();
@@ -173,10 +178,17 @@
                 | 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();
+        lp.format = PixelFormat.TRANSLUCENT;
+        lp.setTitle(VolumeDialogImpl.class.getSimpleName());
+        lp.gravity = Gravity.RIGHT | Gravity.CENTER_VERTICAL;
+        lp.windowAnimations = -1;
+        mWindow.setAttributes(lp);
+        mWindow.setLayout(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
 
+        mDialog.setCanceledOnTouchOutside(true);
         mDialog.setContentView(R.layout.volume_dialog);
         mDialog.setOnShowListener(dialog -> {
             mDialogView.setTranslationX(mDialogView.getWidth() / 2);
@@ -199,13 +211,15 @@
             rescheduleTimeoutH();
             return true;
         });
-        VolumeUiLayout hardwareLayout = VolumeUiLayout.get(mDialogView);
-        hardwareLayout.setOutsideTouchListener(view -> dismiss(DISMISS_REASON_TOUCH_OUTSIDE));
+        VolumeUiLayout uiLayout = VolumeUiLayout.get(mDialogView);
+        uiLayout.updateRotation();
 
         mDialogRowsView = mDialog.findViewById(R.id.volume_dialog_rows);
         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,
@@ -339,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;
@@ -394,15 +409,12 @@
             final boolean hasVibrator = mController.hasVibrator();
             if (mState.ringerModeInternal == AudioManager.RINGER_MODE_NORMAL) {
                 if (hasVibrator) {
+                    mController.vibrate();
                     mController.setRingerMode(AudioManager.RINGER_MODE_VIBRATE, false);
                 } else {
-                    final boolean wasZero = ss.level == 0;
-                    mController.setStreamVolume(AudioManager.STREAM_RING, wasZero ? 1 : 0);
                     mController.setRingerMode(AudioManager.RINGER_MODE_SILENT, false);
                 }
             } else if (mState.ringerModeInternal == AudioManager.RINGER_MODE_VIBRATE) {
-                final boolean wasZero = ss.level == 0;
-                mController.setStreamVolume(AudioManager.STREAM_RING, wasZero ? 1 : 0);
                 mController.setRingerMode(AudioManager.RINGER_MODE_SILENT, false);
             } else {
                 mController.setRingerMode(AudioManager.RINGER_MODE_NORMAL, false);
@@ -479,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) {
@@ -553,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);
@@ -597,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--) {
@@ -634,6 +661,8 @@
             updateVolumeRowH(row);
         }
         updateRingerH();
+        mWindow.setTitle(mContext.getString(R.string.volume_dialog_title,
+                getStreamLabelH(getActiveRow().ss)));
     }
 
     private void updateVolumeRowH(VolumeRow row) {
@@ -742,6 +771,7 @@
         if (zenMuted) {
             row.tracking = false;
         }
+        enableVolumeRowViewsH(row, !zenMuted);
 
         // update slider
         final boolean enableSlider = !zenMuted;
@@ -1019,20 +1049,10 @@
         }
 
         @Override
-        public boolean dispatchPopulateAccessibilityEvent(@NonNull AccessibilityEvent event) {
-            event.setClassName(getClass().getSuperclass().getName());
-            event.setPackageName(mContext.getPackageName());
-
-            ViewGroup.LayoutParams params = getWindow().getAttributes();
-            boolean isFullScreen = (params.width == ViewGroup.LayoutParams.MATCH_PARENT) &&
-                    (params.height == ViewGroup.LayoutParams.MATCH_PARENT);
-            event.setFullScreen(isFullScreen);
-
-            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)));
+        public boolean onTouchEvent(MotionEvent event) {
+            if (isShowing()) {
+                if (event.getAction() == MotionEvent.ACTION_OUTSIDE) {
+                    dismissH(Events.DISMISS_REASON_TOUCH_OUTSIDE);
                     return true;
                 }
             }
@@ -1166,5 +1186,6 @@
         private int lastAudibleLevel = 1;
         private View outputChooser;
         private TextView connectedDevice;
+        private ImageView dndIcon;
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeUiLayout.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeUiLayout.java
index 3d44381..0a3a2ab 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeUiLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeUiLayout.java
@@ -37,10 +37,6 @@
 public class VolumeUiLayout extends FrameLayout  {
 
     private View mChild;
-    private int mOldHeight;
-    private boolean mAnimating;
-    private AnimatorSet mAnimation;
-    private boolean mHasOutsideTouch;
     private int mRotation = ROTATION_NONE;
     @Nullable
     private DisplayCutout mDisplayCutout;
@@ -52,13 +48,11 @@
     @Override
     protected void onAttachedToWindow() {
         super.onAttachedToWindow();
-        getViewTreeObserver().addOnComputeInternalInsetsListener(mInsetsListener);
     }
 
     @Override
     protected void onDetachedFromWindow() {
         super.onDetachedFromWindow();
-        getViewTreeObserver().removeOnComputeInternalInsetsListener(mInsetsListener);
         mDisplayCutout = null;
     }
 
@@ -68,16 +62,11 @@
         if (mChild == null) {
             if (getChildCount() != 0) {
                 mChild = getChildAt(0);
-                mOldHeight = mChild.getMeasuredHeight();
                 updateRotation();
             } else {
                 return;
             }
         }
-        int newHeight = mChild.getMeasuredHeight();
-        if (newHeight != mOldHeight) {
-            animateChild(mOldHeight, newHeight);
-        }
     }
 
     @Override
@@ -95,8 +84,13 @@
         }
     }
 
-    private void updateRotation() {
+    public void updateRotation() {
         setDisplayCutout();
+        if (mChild == null) {
+            if (getChildCount() != 0) {
+                mChild = getChildAt(0);
+            }
+        }
         int rotation = RotationUtils.getRotation(getContext());
         if (rotation != mRotation) {
             updateSafeInsets(rotation);
@@ -144,43 +138,11 @@
         return r.bottom - r.top;
     }
 
-
-    private void animateChild(int oldHeight, int newHeight) {
-        if (true) return;
-        if (mAnimating) {
-            mAnimation.cancel();
-        }
-        mAnimating = true;
-        mAnimation = new AnimatorSet();
-        mAnimation.addListener(new AnimatorListenerAdapter() {
-            @Override
-            public void onAnimationEnd(Animator animation) {
-                mAnimating = false;
-            }
-        });
-        int fromTop = mChild.getTop();
-        int fromBottom = mChild.getBottom();
-        int toTop = fromTop - ((newHeight - oldHeight) / 2);
-        int toBottom = fromBottom + ((newHeight - oldHeight) / 2);
-        ObjectAnimator top = ObjectAnimator.ofInt(mChild, "top", fromTop, toTop);
-        mAnimation.playTogether(top,
-                ObjectAnimator.ofInt(mChild, "bottom", fromBottom, toBottom));
-    }
-
-
     @Override
     public ViewOutlineProvider getOutlineProvider() {
         return super.getOutlineProvider();
     }
 
-    public void setOutsideTouchListener(OnClickListener onClickListener) {
-        mHasOutsideTouch = true;
-        requestLayout();
-        setOnClickListener(onClickListener);
-        setClickable(true);
-        setFocusable(true);
-    }
-
     public static VolumeUiLayout get(View v) {
         if (v instanceof VolumeUiLayout) return (VolumeUiLayout) v;
         if (v.getParent() instanceof View) {
@@ -188,16 +150,4 @@
         }
         return null;
     }
-
-    private final ViewTreeObserver.OnComputeInternalInsetsListener mInsetsListener = inoutInfo -> {
-        if (mHasOutsideTouch || (mChild == null)) {
-            inoutInfo.setTouchableInsets(
-                    ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME);
-            return;
-        }
-        inoutInfo.setTouchableInsets(
-                ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_CONTENT);
-        inoutInfo.contentInsets.set(mChild.getLeft(), mChild.getTop(),
-                0, getBottom() - mChild.getBottom());
-    };
 }
diff --git a/packages/SystemUI/tests/Android.mk b/packages/SystemUI/tests/Android.mk
index 936ff51..552784a 100644
--- a/packages/SystemUI/tests/Android.mk
+++ b/packages/SystemUI/tests/Android.mk
@@ -56,16 +56,22 @@
 LOCAL_STATIC_JAVA_LIBRARIES := \
     metrics-helper-lib \
     android-support-test \
-    mockito-target-minus-junit4 \
+    mockito-target-inline-minus-junit4 \
     SystemUI-proto \
     SystemUI-tags \
     testables \
     truth-prebuilt \
 
+LOCAL_MULTILIB := both
+
+LOCAL_JNI_SHARED_LIBRARIES := \
+    libdexmakerjvmtiagent \
+    libmultiplejvmtiagentsinterferenceagent
+
+
 LOCAL_JAVA_LIBRARIES := \
     android.test.runner \
     telephony-common \
-    android.car \
     android.test.base \
 
 
diff --git a/packages/SystemUI/tests/AndroidManifest.xml b/packages/SystemUI/tests/AndroidManifest.xml
index f5e079c..767a24a 100644
--- a/packages/SystemUI/tests/AndroidManifest.xml
+++ b/packages/SystemUI/tests/AndroidManifest.xml
@@ -48,8 +48,9 @@
     <uses-permission android:name="android.permission.REAL_GET_TASKS" />
     <uses-permission android:name="android.permission.INTERNAL_SYSTEM_WINDOW" />
     <uses-permission android:name="android.permission.NETWORK_SETTINGS" />
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
 
-    <application>
+    <application android:debuggable="true">
         <uses-library android:name="android.test.runner" />
         <activity android:name="com.android.systemui.screenshot.ScreenshotStubActivity" />
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStateTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStateTest.java
index 521d2e3..8c4fd73 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStateTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStateTest.java
@@ -28,6 +28,7 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.when;
 
 import android.os.Looper;
 import android.support.test.filters.SmallTest;
@@ -35,11 +36,14 @@
 import android.view.Display;
 
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.statusbar.phone.DozeParameters;
 import com.android.systemui.utils.os.FakeHandler;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
 
 @RunWith(AndroidJUnit4.class)
 @SmallTest
@@ -48,12 +52,16 @@
     DozeServiceFake mServiceFake;
     DozeScreenState mScreen;
     FakeHandler mHandlerFake;
+    @Mock
+    DozeParameters mDozeParameters;
 
     @Before
     public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        when(mDozeParameters.getDisplayNeedsBlanking()).thenReturn(true);
         mServiceFake = new DozeServiceFake();
         mHandlerFake = new FakeHandler(Looper.getMainLooper());
-        mScreen = new DozeScreenState(mServiceFake, mHandlerFake);
+        mScreen = new DozeScreenState(mServiceFake, mHandlerFake, mDozeParameters);
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/power/PowerNotificationWarningsTest.java b/packages/SystemUI/tests/src/com/android/systemui/power/PowerNotificationWarningsTest.java
index 3e37cfe..bf6cc53 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/power/PowerNotificationWarningsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/power/PowerNotificationWarningsTest.java
@@ -151,22 +151,4 @@
         verify(mMockNotificationManager, times(1)).cancelAsUser(anyString(),
                 eq(SystemMessage.NOTE_THERMAL_SHUTDOWN), any());
     }
-
-    @Test
-    public void testGetTimeRemainingFormatted_roundsDownTo15() {
-        mPowerNotificationWarnings.updateEstimate(
-                new Estimate(TimeUnit.MINUTES.toMillis(57), true));
-        String time = mPowerNotificationWarnings.getTimeRemainingFormatted();
-
-        assertTrue("time:" + time + ", expected: " + FORMATTED_45M, time.equals(FORMATTED_45M));
-    }
-
-    @Test
-    public void testGetTimeRemainingFormatted_keepsMinutesWhenZero() {
-        mPowerNotificationWarnings.updateEstimate(
-                new Estimate(TimeUnit.MINUTES.toMillis(65), true));
-        String time = mPowerNotificationWarnings.getTimeRemainingFormatted();
-
-        assertTrue("time:" + time + ", expected: " + FORMATTED_HOUR, time.equals(FORMATTED_HOUR));
-    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java b/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java
index 0a51e5a..4b455ba 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java
@@ -155,7 +155,7 @@
         // hybrid but the threshold has been overriden to be too low
         boolean shouldShow =
                 mPowerUI.shouldShowLowBatteryWarning(UNPLUGGED, UNPLUGGED, ABOVE_WARNING_BUCKET,
-                        ABOVE_WARNING_BUCKET, Long.MAX_VALUE, BELOW_HYBRID_THRESHOLD,
+                        ABOVE_WARNING_BUCKET, BELOW_HYBRID_THRESHOLD,
                         POWER_SAVER_OFF, BatteryManager.BATTERY_HEALTH_GOOD);
         assertFalse(shouldShow);
     }
@@ -172,7 +172,7 @@
         // hybrid since the threshold has been overriden to be much higher
         boolean shouldShow =
                 mPowerUI.shouldShowLowBatteryWarning(UNPLUGGED, UNPLUGGED, ABOVE_WARNING_BUCKET,
-                        ABOVE_WARNING_BUCKET, Long.MAX_VALUE, ABOVE_HYBRID_THRESHOLD,
+                        ABOVE_WARNING_BUCKET, ABOVE_HYBRID_THRESHOLD,
                         POWER_SAVER_OFF, BatteryManager.BATTERY_HEALTH_GOOD);
         assertTrue(shouldShow);
     }
@@ -188,7 +188,7 @@
         // hybrid
         boolean shouldShow =
                 mPowerUI.shouldShowLowBatteryWarning(UNPLUGGED, UNPLUGGED, ABOVE_WARNING_BUCKET,
-                        ABOVE_WARNING_BUCKET, Long.MAX_VALUE, BELOW_HYBRID_THRESHOLD,
+                        ABOVE_WARNING_BUCKET, BELOW_HYBRID_THRESHOLD,
                         POWER_SAVER_OFF, BatteryManager.BATTERY_HEALTH_GOOD);
         assertTrue(shouldShow);
     }
@@ -203,7 +203,7 @@
         // unplugged device that would show the non-hybrid notification and the hybrid
         boolean shouldShow =
                 mPowerUI.shouldShowLowBatteryWarning(UNPLUGGED, UNPLUGGED, ABOVE_WARNING_BUCKET,
-                        BELOW_WARNING_BUCKET, Long.MAX_VALUE, BELOW_HYBRID_THRESHOLD,
+                        BELOW_WARNING_BUCKET, BELOW_HYBRID_THRESHOLD,
                         POWER_SAVER_OFF, BatteryManager.BATTERY_HEALTH_GOOD);
         assertTrue(shouldShow);
     }
@@ -218,7 +218,7 @@
         // unplugged device that would show the non-hybrid but not the hybrid
         boolean shouldShow =
                 mPowerUI.shouldShowLowBatteryWarning(UNPLUGGED, UNPLUGGED, ABOVE_WARNING_BUCKET,
-                        BELOW_WARNING_BUCKET, Long.MAX_VALUE, ABOVE_HYBRID_THRESHOLD,
+                        BELOW_WARNING_BUCKET, ABOVE_HYBRID_THRESHOLD,
                         POWER_SAVER_OFF, BatteryManager.BATTERY_HEALTH_GOOD);
         assertTrue(shouldShow);
     }
@@ -233,7 +233,7 @@
         // unplugged device that would show the neither due to battery level being good
         boolean shouldShow =
                 mPowerUI.shouldShowLowBatteryWarning(UNPLUGGED, UNPLUGGED, ABOVE_WARNING_BUCKET,
-                        ABOVE_WARNING_BUCKET, ABOVE_HYBRID_THRESHOLD, ABOVE_HYBRID_THRESHOLD,
+                        ABOVE_WARNING_BUCKET, ABOVE_HYBRID_THRESHOLD,
                         POWER_SAVER_OFF, BatteryManager.BATTERY_HEALTH_GOOD);
         assertFalse(shouldShow);
     }
@@ -248,7 +248,7 @@
         // plugged device that would show the neither due to being plugged
         boolean shouldShow =
                 mPowerUI.shouldShowLowBatteryWarning(!UNPLUGGED, UNPLUGGED, ABOVE_WARNING_BUCKET,
-                        BELOW_WARNING_BUCKET, ABOVE_HYBRID_THRESHOLD, BELOW_HYBRID_THRESHOLD,
+                        BELOW_WARNING_BUCKET, BELOW_HYBRID_THRESHOLD,
                         POWER_SAVER_OFF, BatteryManager.BATTERY_HEALTH_GOOD);
         assertFalse(shouldShow);
    }
@@ -263,7 +263,7 @@
         // Unknown battery status device that would show the neither due
         boolean shouldShow =
                 mPowerUI.shouldShowLowBatteryWarning(UNPLUGGED, UNPLUGGED, ABOVE_WARNING_BUCKET,
-                        BELOW_WARNING_BUCKET, ABOVE_HYBRID_THRESHOLD, BELOW_HYBRID_THRESHOLD,
+                        BELOW_WARNING_BUCKET, BELOW_HYBRID_THRESHOLD,
                         !POWER_SAVER_OFF, BatteryManager.BATTERY_STATUS_UNKNOWN);
         assertFalse(shouldShow);
     }
@@ -278,12 +278,31 @@
         // BatterySaverEnabled device that would show the neither due to battery saver
         boolean shouldShow =
                 mPowerUI.shouldShowLowBatteryWarning(UNPLUGGED, UNPLUGGED, ABOVE_WARNING_BUCKET,
-                        BELOW_WARNING_BUCKET, ABOVE_HYBRID_THRESHOLD, BELOW_HYBRID_THRESHOLD,
+                        BELOW_WARNING_BUCKET, BELOW_HYBRID_THRESHOLD,
                         !POWER_SAVER_OFF, BatteryManager.BATTERY_HEALTH_GOOD);
         assertFalse(shouldShow);
     }
 
     @Test
+    public void testShouldShowLowBatteryWarning_onlyShowsOncePerChargeCycle() {
+        mPowerUI.start();
+        when(mEnhancedEstimates.isHybridNotificationEnabled()).thenReturn(true);
+        when(mEnhancedEstimates.getLowWarningThreshold()).thenReturn(PowerUI.THREE_HOURS_IN_MILLIS);
+        when(mEnhancedEstimates.getSevereWarningThreshold()).thenReturn(ONE_HOUR_MILLIS);
+        when(mEnhancedEstimates.getEstimate())
+                .thenReturn(new Estimate(BELOW_HYBRID_THRESHOLD, true));
+        mPowerUI.mBatteryStatus = BatteryManager.BATTERY_HEALTH_GOOD;
+
+        mPowerUI.maybeShowBatteryWarning(UNPLUGGED, UNPLUGGED, ABOVE_WARNING_BUCKET,
+                ABOVE_WARNING_BUCKET);
+        boolean shouldShow =
+                mPowerUI.shouldShowLowBatteryWarning(UNPLUGGED, UNPLUGGED, ABOVE_WARNING_BUCKET,
+                        ABOVE_WARNING_BUCKET, BELOW_HYBRID_THRESHOLD,
+                        POWER_SAVER_OFF, BatteryManager.BATTERY_HEALTH_GOOD);
+        assertFalse(shouldShow);
+    }
+
+    @Test
     public void testShouldDismissLowBatteryWarning_dismissWhenPowerSaverEnabled() {
         mPowerUI.start();
         when(mEnhancedEstimates.isHybridNotificationEnabled()).thenReturn(true);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/SlashImageViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/SlashImageViewTest.java
index 98ca1b4..e2159d2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/SlashImageViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/SlashImageViewTest.java
@@ -27,8 +27,14 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
 
 @SmallTest
@@ -80,13 +86,12 @@
     public void testSetImageDrawableUsesDrawableLevel() {
         SlashImageView iv = new SlashImageView(mContext);
         Drawable mockDrawable = mock(Drawable.class);
-        mockDrawable.setLevel(2);
-        assertTrue(mockDrawable.getLevel() == 2);
+        when(mockDrawable.getLevel()).thenReturn(2);
 
         iv.setImageDrawable(mockDrawable);
 
         // Make sure setting the drawable didn't reset its level to 0
-        assertTrue(mockDrawable.getLevel() == 2);
+        verify(mockDrawable).setLevel(eq(2));
     }
 
     // Expose getSlashDrawable
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/NotificationTestHelper.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java
index 6e7477f..f3c1171 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java
@@ -32,6 +32,7 @@
 import com.android.systemui.statusbar.notification.AboveShelfObserver;
 import com.android.systemui.statusbar.notification.InflationException;
 import com.android.systemui.statusbar.notification.NotificationInflaterTest;
+import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
 import com.android.systemui.statusbar.phone.NotificationGroupManager;
 import com.android.systemui.statusbar.policy.HeadsUpManager;
 
@@ -51,7 +52,7 @@
     public NotificationTestHelper(Context context) {
         mContext = context;
         mInstrumentation = InstrumentationRegistry.getInstrumentation();
-        mHeadsUpManager = new HeadsUpManager(mContext, null, mGroupManager);
+        mHeadsUpManager = new HeadsUpManagerPhone(mContext, null, mGroupManager, null, null);
     }
 
     public ExpandableNotificationRow createRow() throws Exception {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhoneTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhoneTest.java
new file mode 100644
index 0000000..aa991cb
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhoneTest.java
@@ -0,0 +1,216 @@
+/*
+ * 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.phone;
+
+import android.app.ActivityManager;
+import android.app.Instrumentation;
+import android.app.Notification;
+import android.os.UserHandle;
+import android.view.View;
+import android.service.notification.StatusBarNotification;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+
+import com.android.systemui.R;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.statusbar.ExpandableNotificationRow;
+import com.android.systemui.statusbar.NotificationData;
+import com.android.systemui.statusbar.StatusBarIconView;
+import com.android.systemui.statusbar.notification.VisualStabilityManager;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+
+import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.assertNull;
+import static junit.framework.Assert.assertTrue;
+import static junit.framework.Assert.assertFalse;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
+public class HeadsUpManagerPhoneTest extends SysuiTestCase {
+    @Rule public MockitoRule rule = MockitoJUnit.rule();
+
+    private static final String TEST_PACKAGE_NAME = "test";
+    private static final int TEST_UID = 0;
+
+    private HeadsUpManagerPhone mHeadsUpManager;
+
+    private NotificationData.Entry mEntry;
+    private StatusBarNotification mSbn;
+
+    @Mock private NotificationGroupManager mGroupManager;
+    @Mock private View mStatusBarWindowView;
+    @Mock private StatusBar mBar;
+    @Mock private ExpandableNotificationRow mRow;
+    @Mock private VisualStabilityManager mVSManager;
+
+    @Before
+    public void setUp() {
+        when(mVSManager.isReorderingAllowed()).thenReturn(true);
+
+        mHeadsUpManager = new HeadsUpManagerPhone(
+                mContext, mStatusBarWindowView, mGroupManager, mBar, mVSManager);
+
+        Notification.Builder n = new Notification.Builder(mContext, "")
+                .setSmallIcon(R.drawable.ic_person)
+                .setContentTitle("Title")
+                .setContentText("Text");
+        mSbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME, 0, null, TEST_UID,
+             0, n.build(), new UserHandle(ActivityManager.getCurrentUser()), null, 0);
+
+        mEntry = new NotificationData.Entry(mSbn);
+        mEntry.row = mRow;
+        mEntry.expandedIcon = mock(StatusBarIconView.class);
+    }
+
+    @Test
+    public void testBasicOperations() {
+        // Check the initial state.
+        assertNull(mHeadsUpManager.getEntry(mEntry.key));
+        assertNull(mHeadsUpManager.getTopEntry());
+        assertEquals(0, mHeadsUpManager.getAllEntries().count());
+        assertFalse(mHeadsUpManager.hasHeadsUpNotifications());
+
+        // Add a notification.
+        mHeadsUpManager.showNotification(mEntry);
+
+        assertEquals(mEntry, mHeadsUpManager.getEntry(mEntry.key));
+        assertEquals(mEntry, mHeadsUpManager.getTopEntry());
+        assertEquals(1, mHeadsUpManager.getAllEntries().count());
+        assertTrue(mHeadsUpManager.hasHeadsUpNotifications());
+
+        // Update the notification.
+        mHeadsUpManager.updateNotification(mEntry, false);
+
+        assertEquals(mEntry, mHeadsUpManager.getEntry(mEntry.key));
+        assertEquals(mEntry, mHeadsUpManager.getTopEntry());
+        assertEquals(1, mHeadsUpManager.getAllEntries().count());
+        assertTrue(mHeadsUpManager.hasHeadsUpNotifications());
+
+        // Try to remove but defer, since the notification is currenlt visible on display.
+        mHeadsUpManager.removeNotification(mEntry.key, false /* ignoreEarliestRemovalTime */);
+
+        assertEquals(mEntry, mHeadsUpManager.getEntry(mEntry.key));
+        assertEquals(mEntry, mHeadsUpManager.getTopEntry());
+        assertEquals(1, mHeadsUpManager.getAllEntries().count());
+        assertTrue(mHeadsUpManager.hasHeadsUpNotifications());
+
+        // Remove forcibly with ignoreEarliestRemovalTime = true.
+        mHeadsUpManager.removeNotification(mEntry.key, true /* ignoreEarliestRemovalTime */);
+
+        // Check the initial state.
+        assertNull(mHeadsUpManager.getEntry(mEntry.key));
+        assertNull(mHeadsUpManager.getTopEntry());
+        assertEquals(0, mHeadsUpManager.getAllEntries().count());
+        assertFalse(mHeadsUpManager.hasHeadsUpNotifications());
+    }
+
+    @Test
+    public void testsTimeoutRemoval() {
+        mHeadsUpManager.removeMinimumDisplayTimeForTesting();
+
+        // Check the initial state.
+        assertNull(mHeadsUpManager.getEntry(mEntry.key));
+        assertNull(mHeadsUpManager.getTopEntry());
+        assertEquals(0, mHeadsUpManager.getAllEntries().count());
+        assertFalse(mHeadsUpManager.hasHeadsUpNotifications());
+
+        Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
+
+        // Run the code on the main thready, not to run an async operations.
+        instrumentation.runOnMainSync(() -> {
+            // Add a notification.
+            mHeadsUpManager.showNotification(mEntry);
+
+            // Ensure the head up is visible before timeout.
+            assertNotNull(mHeadsUpManager.getEntry(mEntry.key));
+            assertNotNull(mHeadsUpManager.getTopEntry());
+            assertEquals(1, mHeadsUpManager.getAllEntries().count());
+            assertTrue(mHeadsUpManager.hasHeadsUpNotifications());
+        });
+        // Wait for the async operations, which removes the heads up notification.
+        waitForIdleSync();
+
+        assertNull(mHeadsUpManager.getEntry(mEntry.key));
+        assertNull(mHeadsUpManager.getTopEntry());
+        assertEquals(0, mHeadsUpManager.getAllEntries().count());
+        assertFalse(mHeadsUpManager.hasHeadsUpNotifications());
+    }
+
+    @Test
+    public void releaseImmediately() {
+        // Check the initial state.
+        assertNull(mHeadsUpManager.getEntry(mEntry.key));
+        assertNull(mHeadsUpManager.getTopEntry());
+        assertEquals(0, mHeadsUpManager.getAllEntries().count());
+        assertFalse(mHeadsUpManager.hasHeadsUpNotifications());
+
+        // Add a notification.
+        mHeadsUpManager.showNotification(mEntry);
+
+        assertEquals(mEntry, mHeadsUpManager.getEntry(mEntry.key));
+        assertEquals(mEntry, mHeadsUpManager.getTopEntry());
+        assertEquals(1, mHeadsUpManager.getAllEntries().count());
+        assertTrue(mHeadsUpManager.hasHeadsUpNotifications());
+
+        // Remove but defer, since the notification is visible on display.
+        mHeadsUpManager.releaseImmediately(mEntry.key);
+
+        assertNull(mHeadsUpManager.getEntry(mEntry.key));
+        assertNull(mHeadsUpManager.getTopEntry());
+        assertEquals(0, mHeadsUpManager.getAllEntries().count());
+        assertFalse(mHeadsUpManager.hasHeadsUpNotifications());
+    }
+
+    @Test
+    public void releaseAllImmediately() {
+        // Check the initial state.
+        assertNull(mHeadsUpManager.getEntry(mEntry.key));
+        assertNull(mHeadsUpManager.getTopEntry());
+        assertEquals(0, mHeadsUpManager.getAllEntries().count());
+        assertFalse(mHeadsUpManager.hasHeadsUpNotifications());
+
+        // Add a notification.
+        mHeadsUpManager.showNotification(mEntry);
+
+        assertEquals(mEntry, mHeadsUpManager.getEntry(mEntry.key));
+        assertEquals(mEntry, mHeadsUpManager.getTopEntry());
+        assertEquals(1, mHeadsUpManager.getAllEntries().count());
+        assertTrue(mHeadsUpManager.hasHeadsUpNotifications());
+
+        // Remove but defer, since the notification is visible on display.
+        mHeadsUpManager.releaseAllImmediately();
+
+        assertNull(mHeadsUpManager.getEntry(mEntry.key));
+        assertNull(mHeadsUpManager.getTopEntry());
+        assertEquals(0, mHeadsUpManager.getAllEntries().count());
+        assertFalse(mHeadsUpManager.hasHeadsUpNotifications());
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java
index 4cc83f6..17df800 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java
@@ -27,6 +27,7 @@
 
 import com.android.systemui.Dependency;
 
+import com.android.systemui.OverviewProxyService;
 import com.android.systemui.SysuiBaseFragmentTest;
 import com.android.systemui.recents.Recents;
 import com.android.systemui.stackdivider.Divider;
@@ -61,6 +62,7 @@
         mSysuiContext.putComponent(Recents.class, mock(Recents.class));
         mSysuiContext.putComponent(Divider.class, mock(Divider.class));
         injectLeakCheckedDependencies(ALL_SUPPORTED_CLASSES);
+        mDependency.injectMockDependency(OverviewProxyService.class);
         WindowManager windowManager = mock(WindowManager.class);
         Display defaultDisplay = mContext.getSystemService(WindowManager.class).getDefaultDisplay();
         when(windowManager.getDefaultDisplay()).thenReturn(
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 6d2691c..43e16db 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
@@ -38,6 +38,7 @@
 import android.support.test.filters.SmallTest;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
+import android.view.Choreographer;
 import android.view.View;
 
 import com.android.keyguard.KeyguardUpdateMonitor;
@@ -374,7 +375,6 @@
             onPreDraw();
 
             // Force finish screen blanking.
-            endAnimation(mScrimInFront, TAG_KEY_ANIM_BLANK);
             mHandler.dispatchQueuedMessages();
             // Force finish all animations.
             endAnimation(mScrimBehind, TAG_KEY_ANIM);
@@ -401,6 +401,15 @@
         protected WakeLock createWakeLock() {
             return mWakeLock;
         }
+
+        /**
+         * Do not wait for a frame since we're in a test environment.
+         * @param callback What to execute.
+         */
+        @Override
+        protected void doOnTheNextFrame(Choreographer.FrameCallback callback) {
+            callback.doFrame(0);
+        }
     }
 
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
index bdf9b1f..31442af 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
@@ -86,8 +86,8 @@
 import com.android.systemui.statusbar.StatusBarState;
 import com.android.systemui.statusbar.notification.ActivityLaunchAnimator;
 import com.android.systemui.statusbar.notification.VisualStabilityManager;
+import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
 import com.android.systemui.statusbar.policy.DeviceProvisionedController;
-import com.android.systemui.statusbar.policy.HeadsUpManager;
 import com.android.systemui.statusbar.policy.KeyguardMonitor;
 import com.android.systemui.statusbar.policy.KeyguardMonitorImpl;
 import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
@@ -110,7 +110,7 @@
     @Mock private UnlockMethodCache mUnlockMethodCache;
     @Mock private KeyguardIndicationController mKeyguardIndicationController;
     @Mock private NotificationStackScrollLayout mStackScroller;
-    @Mock private HeadsUpManager mHeadsUpManager;
+    @Mock private HeadsUpManagerPhone mHeadsUpManager;
     @Mock private SystemServicesProxy mSystemServicesProxy;
     @Mock private NotificationPanelView mNotificationPanelView;
     @Mock private IStatusBarService mBarService;
@@ -588,7 +588,7 @@
     static class TestableStatusBar extends StatusBar {
         public TestableStatusBar(StatusBarKeyguardViewManager man,
                 UnlockMethodCache unlock, KeyguardIndicationController key,
-                NotificationStackScrollLayout stack, HeadsUpManager hum,
+                NotificationStackScrollLayout stack, HeadsUpManagerPhone hum,
                 PowerManager pm, NotificationPanelView panelView,
                 IStatusBarService barService, NotificationListener notificationListener,
                 NotificationLogger notificationLogger,
@@ -650,7 +650,7 @@
         public void setUpForTest(NotificationPresenter presenter,
                 NotificationListContainer listContainer,
                 Callback callback,
-                HeadsUpManager headsUpManager,
+                HeadsUpManagerPhone headsUpManager,
                 NotificationData notificationData) {
             super.setUpWithPresenter(presenter, listContainer, callback, headsUpManager);
             mNotificationData = notificationData;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/LocationControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/LocationControllerImplTest.java
index a10bebf..e1b97bda 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/LocationControllerImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/LocationControllerImplTest.java
@@ -29,12 +29,14 @@
 import com.android.systemui.statusbar.policy.LocationController.LocationChangeCallback;
 
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
 @RunWith(AndroidTestingRunner.class)
 @RunWithLooper
 @SmallTest
+@Ignore
 public class LocationControllerImplTest extends SysuiTestCase {
 
     private LocationControllerImpl mLocationController;
@@ -79,4 +81,4 @@
 
         TestableLooper.get(this).processAllMessages();
     }
-}
\ No newline at end of file
+}
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 a8e8540..54ba375 100755
--- 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/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java
index 0c3637d..58abf19 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java
@@ -14,16 +14,27 @@
 
 package com.android.systemui.statusbar.policy;
 
+import static android.view.View.MeasureSpec;
+
 import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertTrue;
+import static junit.framework.Assert.fail;
 
 import android.app.PendingIntent;
 import android.app.RemoteInput;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.res.Resources;
 import android.support.test.filters.SmallTest;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.LinearLayout;
 
+import com.android.systemui.R;
 import com.android.systemui.SysuiTestCase;
 
 import org.junit.Before;
@@ -34,30 +45,40 @@
 @TestableLooper.RunWithLooper
 @SmallTest
 public class SmartReplyViewTest extends SysuiTestCase {
-
     private static final String TEST_RESULT_KEY = "test_result_key";
     private static final String TEST_ACTION = "com.android.ACTION";
+
     private static final String[] TEST_CHOICES = new String[]{"Hello", "What's up?", "I'm here"};
 
+    private static final int WIDTH_SPEC = MeasureSpec.makeMeasureSpec(500, MeasureSpec.EXACTLY);
+    private static final int HEIGHT_SPEC = MeasureSpec.makeMeasureSpec(400, MeasureSpec.AT_MOST);
+
     private BlockingQueueIntentReceiver mReceiver;
     private SmartReplyView mView;
 
+    private int mSingleLinePaddingHorizontal;
+    private int mDoubleLinePaddingHorizontal;
+    private int mSpacing;
+
     @Before
     public void setUp() {
         mReceiver = new BlockingQueueIntentReceiver();
         mContext.registerReceiver(mReceiver, new IntentFilter(TEST_ACTION));
 
         mView = SmartReplyView.inflate(mContext, null);
+
+
+        final Resources res = mContext.getResources();
+        mSingleLinePaddingHorizontal = res.getDimensionPixelSize(
+                R.dimen.smart_reply_button_padding_horizontal_single_line);
+        mDoubleLinePaddingHorizontal = res.getDimensionPixelSize(
+                R.dimen.smart_reply_button_padding_horizontal_double_line);
+        mSpacing = res.getDimensionPixelSize(R.dimen.smart_reply_button_spacing);
     }
 
     @Test
     public void testSendSmartReply_intentContainsResultsAndSource() throws InterruptedException {
-        PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0,
-                new Intent(TEST_ACTION), 0);
-        RemoteInput input = new RemoteInput.Builder(TEST_RESULT_KEY).setChoices(
-                TEST_CHOICES).build();
-
-        mView.setRepliesFromRemoteInput(input, pendingIntent);
+        setRepliesFromRemoteInput(TEST_CHOICES);
 
         mView.getChildAt(2).performClick();
 
@@ -66,4 +87,259 @@
                 RemoteInput.getResultsFromIntent(resultIntent).get(TEST_RESULT_KEY));
         assertEquals(RemoteInput.SOURCE_CHOICE, RemoteInput.getResultsSource(resultIntent));
     }
+
+    @Test
+    public void testMeasure_empty() {
+        mView.measure(WIDTH_SPEC, HEIGHT_SPEC);
+        assertEquals(500, mView.getMeasuredWidthAndState());
+        assertEquals(0, mView.getMeasuredHeightAndState());
+    }
+
+    @Test
+    public void testLayout_empty() {
+        mView.measure(WIDTH_SPEC, HEIGHT_SPEC);
+        mView.layout(0, 0, 500, 0);
+    }
+
+
+    // Instead of manually calculating the expected measurement/layout results, we build the
+    // expectations as ordinary linear layouts and then check that the relevant parameters in the
+    // corresponding SmartReplyView and LinearView are equal.
+
+    @Test
+    public void testMeasure_shortChoices() {
+        final CharSequence[] choices = new CharSequence[]{"Hi", "Hello", "Bye"};
+
+        // All choices should be displayed as SINGLE-line smart reply buttons.
+        ViewGroup expectedView = buildExpectedView(choices, 1);
+        expectedView.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
+
+        setRepliesFromRemoteInput(choices);
+        mView.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
+
+        assertEqualMeasures(expectedView, mView);
+        assertReplyButtonShownWithEqualMeasures(expectedView.getChildAt(0), mView.getChildAt(0));
+        assertReplyButtonShownWithEqualMeasures(expectedView.getChildAt(1), mView.getChildAt(1));
+        assertReplyButtonShownWithEqualMeasures(expectedView.getChildAt(2), mView.getChildAt(2));
+    }
+
+    @Test
+    public void testLayout_shortChoices() {
+        final CharSequence[] choices = new CharSequence[]{"Hi", "Hello", "Bye"};
+
+        // All choices should be displayed as SINGLE-line smart reply buttons.
+        ViewGroup expectedView = buildExpectedView(choices, 1);
+        expectedView.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
+        expectedView.layout(10, 10, 10 + expectedView.getMeasuredWidth(),
+                10 + expectedView.getMeasuredHeight());
+
+        setRepliesFromRemoteInput(choices);
+        mView.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
+        mView.layout(10, 10, 10 + mView.getMeasuredWidth(), 10 + mView.getMeasuredHeight());
+
+        assertEqualLayouts(expectedView, mView);
+        assertEqualLayouts(expectedView.getChildAt(0), mView.getChildAt(0));
+        assertEqualLayouts(expectedView.getChildAt(1), mView.getChildAt(1));
+        assertEqualLayouts(expectedView.getChildAt(2), mView.getChildAt(2));
+    }
+
+    @Test
+    public void testMeasure_choiceWithTwoLines() {
+        final CharSequence[] choices = new CharSequence[]{"Hi", "Hello\neveryone", "Bye"};
+
+        // All choices should be displayed as DOUBLE-line smart reply buttons.
+        ViewGroup expectedView = buildExpectedView(choices, 2);
+        expectedView.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
+
+        setRepliesFromRemoteInput(choices);
+        mView.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
+
+        assertEqualMeasures(expectedView, mView);
+        assertReplyButtonShownWithEqualMeasures(expectedView.getChildAt(0), mView.getChildAt(0));
+        assertReplyButtonShownWithEqualMeasures(expectedView.getChildAt(1), mView.getChildAt(1));
+        assertReplyButtonShownWithEqualMeasures(expectedView.getChildAt(2), mView.getChildAt(2));
+    }
+
+    @Test
+    public void testLayout_choiceWithTwoLines() {
+        final CharSequence[] choices = new CharSequence[]{"Hi", "Hello\neveryone", "Bye"};
+
+        // All choices should be displayed as DOUBLE-line smart reply buttons.
+        ViewGroup expectedView = buildExpectedView(choices, 2);
+        expectedView.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
+        expectedView.layout(10, 10, 10 + expectedView.getMeasuredWidth(),
+                10 + expectedView.getMeasuredHeight());
+
+        setRepliesFromRemoteInput(choices);
+        mView.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
+        mView.layout(10, 10, 10 + mView.getMeasuredWidth(), 10 + mView.getMeasuredHeight());
+
+        assertEqualLayouts(expectedView, mView);
+        assertEqualLayouts(expectedView.getChildAt(0), mView.getChildAt(0));
+        assertEqualLayouts(expectedView.getChildAt(1), mView.getChildAt(1));
+        assertEqualLayouts(expectedView.getChildAt(2), mView.getChildAt(2));
+    }
+
+    @Test
+    public void testMeasure_choiceWithThreeLines() {
+        final CharSequence[] choices = new CharSequence[]{"Hi", "Hello\nevery\nbody", "Bye"};
+
+        // The choice with three lines should NOT be displayed. All other choices should be
+        // displayed as SINGLE-line smart reply buttons.
+        ViewGroup expectedView = buildExpectedView(new CharSequence[]{"Hi", "Bye"}, 1);
+        expectedView.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
+
+        setRepliesFromRemoteInput(choices);
+        mView.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
+
+        assertEqualMeasures(expectedView, mView);
+        assertReplyButtonShownWithEqualMeasures(expectedView.getChildAt(0), mView.getChildAt(0));
+        assertReplyButtonHidden(mView.getChildAt(1));
+        assertReplyButtonShownWithEqualMeasures(expectedView.getChildAt(1), mView.getChildAt(2));
+    }
+
+    @Test
+    public void testLayout_choiceWithThreeLines() {
+        final CharSequence[] choices = new CharSequence[]{"Hi", "Hello\nevery\nbody", "Bye"};
+
+        // The choice with three lines should NOT be displayed. All other choices should be
+        // displayed as SINGLE-line smart reply buttons.
+        ViewGroup expectedView = buildExpectedView(new CharSequence[]{"Hi", "Bye"}, 1);
+        expectedView.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
+        expectedView.layout(10, 10, 10 + expectedView.getMeasuredWidth(),
+                10 + expectedView.getMeasuredHeight());
+
+        setRepliesFromRemoteInput(choices);
+        mView.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
+        mView.layout(10, 10, 10 + mView.getMeasuredWidth(), 10 + mView.getMeasuredHeight());
+
+        assertEqualLayouts(expectedView, mView);
+        assertEqualLayouts(expectedView.getChildAt(0), mView.getChildAt(0));
+        // We don't care about mView.getChildAt(1)'s layout because it's hidden (see
+        // testMeasure_choiceWithThreeLines).
+        assertEqualLayouts(expectedView.getChildAt(1), mView.getChildAt(2));
+    }
+
+    @Test
+    public void testMeasure_squeezeLongest() {
+        final CharSequence[] choices = new CharSequence[]{"Short", "Short", "Looooooong replyyyyy"};
+
+        // All choices should be displayed as DOUBLE-line smart reply buttons.
+        ViewGroup expectedView = buildExpectedView(
+                new CharSequence[]{"Short", "Short", "Looooooong \nreplyyyyy"}, 2);
+        expectedView.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
+
+        setRepliesFromRemoteInput(choices);
+        mView.measure(
+                MeasureSpec.makeMeasureSpec(expectedView.getMeasuredWidth(), MeasureSpec.AT_MOST),
+                MeasureSpec.UNSPECIFIED);
+
+        assertEqualMeasures(expectedView, mView);
+        assertReplyButtonShownWithEqualMeasures(expectedView.getChildAt(0), mView.getChildAt(0));
+        assertReplyButtonShownWithEqualMeasures(expectedView.getChildAt(1), mView.getChildAt(1));
+        assertReplyButtonShownWithEqualMeasures(expectedView.getChildAt(2), mView.getChildAt(2));
+    }
+
+    @Test
+    public void testLayout_squeezeLongest() {
+        final CharSequence[] choices = new CharSequence[]{"Short", "Short", "Looooooong replyyyyy"};
+
+        // All choices should be displayed as DOUBLE-line smart reply buttons.
+        ViewGroup expectedView = buildExpectedView(
+                new CharSequence[]{"Short", "Short", "Looooooong \nreplyyyyy"}, 2);
+        expectedView.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
+        expectedView.layout(10, 10, 10 + expectedView.getMeasuredWidth(),
+                10 + expectedView.getMeasuredHeight());
+
+        setRepliesFromRemoteInput(choices);
+        mView.measure(
+                MeasureSpec.makeMeasureSpec(expectedView.getMeasuredWidth(), MeasureSpec.AT_MOST),
+                MeasureSpec.UNSPECIFIED);
+        mView.layout(10, 10, 10 + mView.getMeasuredWidth(), 10 + mView.getMeasuredHeight());
+
+        assertEqualLayouts(expectedView, mView);
+        assertEqualLayouts(expectedView.getChildAt(0), mView.getChildAt(0));
+        assertEqualLayouts(expectedView.getChildAt(1), mView.getChildAt(1));
+        assertEqualLayouts(expectedView.getChildAt(2), mView.getChildAt(2));
+    }
+
+    private void setRepliesFromRemoteInput(CharSequence[] choices) {
+        PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0,
+                new Intent(TEST_ACTION), 0);
+        RemoteInput input = new RemoteInput.Builder(TEST_RESULT_KEY).setChoices(choices).build();
+        mView.setRepliesFromRemoteInput(input, pendingIntent);
+    }
+
+    /** Builds a {@link ViewGroup} whose measures and layout mirror a {@link SmartReplyView}. */
+    private ViewGroup buildExpectedView(CharSequence[] choices, int lineCount) {
+        LinearLayout layout = new LinearLayout(mContext);
+        layout.setOrientation(LinearLayout.HORIZONTAL);
+
+        // Baseline alignment causes expected heights to be off by one or two pixels on some
+        // devices.
+        layout.setBaselineAligned(false);
+
+        final boolean isRtl = mView.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL;
+        final int paddingHorizontal;
+        switch (lineCount) {
+            case 1:
+                paddingHorizontal = mSingleLinePaddingHorizontal;
+                break;
+            case 2:
+                paddingHorizontal = mDoubleLinePaddingHorizontal;
+                break;
+            default:
+                fail("Invalid line count " + lineCount);
+                return null;
+        }
+
+        Button previous = null;
+        for (CharSequence choice : choices) {
+            Button current = SmartReplyView.inflateReplyButton(mContext, mView, choice, null, null);
+            current.setPadding(paddingHorizontal, current.getPaddingTop(), paddingHorizontal,
+                    current.getPaddingBottom());
+            if (previous != null) {
+                ViewGroup.MarginLayoutParams lp =
+                        (ViewGroup.MarginLayoutParams) previous.getLayoutParams();
+                if (isRtl) {
+                    lp.leftMargin = mSpacing;
+                } else {
+                    lp.rightMargin = mSpacing;
+                }
+            }
+            layout.addView(current);
+            previous = current;
+        }
+
+        return layout;
+    }
+
+    private static void assertEqualMeasures(View expected, View actual) {
+        assertEquals(expected.getMeasuredWidth(), actual.getMeasuredWidth());
+        assertEquals(expected.getMeasuredHeight(), actual.getMeasuredHeight());
+    }
+
+    private static void assertReplyButtonShownWithEqualMeasures(View expected, View actual) {
+        assertReplyButtonShown(actual);
+        assertEqualMeasures(expected, actual);
+        assertEquals(expected.getPaddingLeft(), actual.getPaddingLeft());
+        assertEquals(expected.getPaddingTop(), actual.getPaddingTop());
+        assertEquals(expected.getPaddingRight(), actual.getPaddingRight());
+        assertEquals(expected.getPaddingBottom(), actual.getPaddingBottom());
+    }
+
+    private static void assertReplyButtonShown(View view) {
+        assertTrue(((SmartReplyView.LayoutParams) view.getLayoutParams()).isShown());
+    }
+
+    private static void assertReplyButtonHidden(View view) {
+        assertFalse(((SmartReplyView.LayoutParams) view.getLayoutParams()).isShown());
+    }
+
+    private static void assertEqualLayouts(View expected, View actual) {
+        assertEquals(expected.getLeft(), actual.getLeft());
+        assertEquals(expected.getTop(), actual.getTop());
+        assertEquals(expected.getRight(), actual.getRight());
+        assertEquals(expected.getBottom(), actual.getBottom());
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/tuner/TunablePaddingTest.java b/packages/SystemUI/tests/src/com/android/systemui/tuner/TunablePaddingTest.java
index 9fd8cc3..3bfefe7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/tuner/TunablePaddingTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/tuner/TunablePaddingTest.java
@@ -45,7 +45,8 @@
     @Before
     public void setup() {
         injectLeakCheckedDependencies(ALL_SUPPORTED_CLASSES);
-        mView = mock(View.class, withSettings().spiedInstance(new View(mContext)));
+        mView = mock(View.class);
+        when(mView.getContext()).thenReturn(mContext);
 
         mTunerService = mDependency.injectMockDependency(TunerService.class);
         Tracker tracker = mLeakCheck.getTracker("tuner");
diff --git a/packages/SystemUI/tests/src/com/android/systemui/volume/OutputChooserDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/volume/OutputChooserDialogTest.java
index f7bb065..922bde7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/volume/OutputChooserDialogTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/volume/OutputChooserDialogTest.java
@@ -16,6 +16,8 @@
 
 package com.android.systemui.volume;
 
+import static com.android.systemui.volume.OutputChooserDialog.INCLUDE_MEDIA_ROUTES;
+
 import static junit.framework.Assert.assertTrue;
 
 import static org.mockito.ArgumentMatchers.any;
@@ -149,19 +151,13 @@
     }
 
     @Test
-    public void testMediaScanIfNotInCall() {
-        mDialog.setIsInCall(false);
-        mDialog.onAttachedToWindow();
-
-        verify(mRouter, times(1)).addCallback(any(), any(), anyInt());
-    }
-
-    @Test
     public void testRegisterCallbacks() {
         mDialog.setIsInCall(false);
         mDialog.onAttachedToWindow();
 
-        verify(mRouter, times(1)).addCallback(any(), any(), anyInt());
+        if (INCLUDE_MEDIA_ROUTES) {
+            verify(mRouter, times(1)).addCallback(any(), any(), anyInt());
+        }
         verify(mController, times(1)).addCallback(any());
         verify(mVolumeController, times(1)).addCallback(any(), any());
     }
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/packages/overlays/DisplayCutoutEmulationNarrowOverlay/AndroidManifest.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/AndroidManifest.xml
index 71ce6b4..426aae9 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/AndroidManifest.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/AndroidManifest.xml
@@ -2,7 +2,9 @@
         package="com.android.internal.display.cutout.emulation.narrow"
         android:versionCode="1"
         android:versionName="1.0">
-    <overlay android:targetPackage="android" android:priority="1"/>
+    <overlay android:targetPackage="android"
+        android:category="com.android.internal.display_cutout_emulation"
+        android:priority="1"/>
 
     <application android:label="@string/display_cutout_emulation_overlay" android:hasCode="false"/>
 </manifest>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/AndroidManifest.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/AndroidManifest.xml
index 5a93cfb..368a2d5 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/AndroidManifest.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/AndroidManifest.xml
@@ -18,7 +18,9 @@
         package="com.android.internal.display.cutout.emulation.tall"
         android:versionCode="1"
         android:versionName="1.0">
-    <overlay android:targetPackage="android" android:priority="1"/>
+    <overlay android:targetPackage="android"
+            android:category="com.android.internal.display_cutout_emulation"
+            android:priority="1"/>
 
     <application android:label="@string/display_cutout_emulation_overlay" android:hasCode="false"/>
 </manifest>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/AndroidManifest.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/AndroidManifest.xml
index 96bd060..b721efe 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/AndroidManifest.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/AndroidManifest.xml
@@ -18,7 +18,9 @@
         package="com.android.internal.display.cutout.emulation.wide"
         android:versionCode="1"
         android:versionName="1.0">
-    <overlay android:targetPackage="android" android:priority="1"/>
+    <overlay android:targetPackage="android"
+        android:category="com.android.internal.display_cutout_emulation"
+        android:priority="1"/>
 
     <application android:label="@string/display_cutout_emulation_overlay" android:hasCode="false"/>
 </manifest>
diff --git a/pathmap.mk b/pathmap.mk
index c241d99..8b77e62 100644
--- a/pathmap.mk
+++ b/pathmap.mk
@@ -20,11 +20,6 @@
 # directories, despite the fact that it was historically used for that!
 #
 
-# Import path mappings from the support library project. This will set up
-# FRAMEWORKS_SUPPORT_JAVA_SRC_DIRS and FRAMEWORKS_SUPPORT_JAVA_LIBRARIES for
-# use later in this file.
-include $(LOCAL_PATH)/../support/pathmap.mk
-
 #
 # A list of all source roots under frameworks/multidex.
 #
diff --git a/proto/Android.bp b/proto/Android.bp
index 95f453c..f3811bd 100644
--- a/proto/Android.bp
+++ b/proto/Android.bp
@@ -6,6 +6,8 @@
     },
     srcs: ["src/**/*.proto"],
     no_framework_libs: true,
+    // Pin java_version until jarjar is certified to support later versions. http://b/72703434
+    java_version: "1.8",
     target: {
         android: {
             jarjar_rules: "jarjar-rules.txt",
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index 01714cf..e118c49 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -3985,6 +3985,8 @@
     // Package: Package of app that was autofilled
     // Tag FIELD_AUTOFILL_FILTERTEXT_LEN: The length of the filter text
     // Tag FIELD_AUTOFILL_NUM_DATASETS: The number of datasets shown
+    // NOTE: starting on OS P, it also added the following field:
+    // Tag FIELD_AUTOFILL_SERVICE: Package of service that processed the request
     AUTOFILL_FILL_UI = 910;
 
     // Tag of a field for the length of the filter text
@@ -4011,7 +4013,9 @@
     // Type TYPE_CLOSE: UI was destroyed without influence of the user
     // Type TYPE_ACTION: data was saved
     // Package: Package of app that was autofilled
-    // Tag FIELD_AUTOFILL_NUM_ID: The number of ids that are saved
+    // Tag FIELD_AUTOFILL_NUM_IDS: The number of ids that are saved
+    // NOTE: starting on OS P, it also added the following field:
+    // Tag FIELD_AUTOFILL_SERVICE: Package of service that processed the request
     AUTOFILL_SAVE_UI = 916;
 
     // Tag of a field for the number of saveable ids
@@ -5083,7 +5087,8 @@
 
     // An autofill service updated its user data
     // Package: Package of the autofill service that updated the user data
-    // Counter: number of fields added (or 0 if reset)
+    // Tag FIELD_AUTOFILL_NUM_VALUES: number of fields added (or 0 if reset)
+    // Tag FIELD_AUTOFILL_SERVICE: Package of service that processed the request
     // OS: P
     AUTOFILL_USERDATA_UPDATED = 1272;
 
@@ -5185,6 +5190,94 @@
     // OS: P
     USB_DEVICE_DETAILS = 1291;
 
+    // OPEN: Settings > Accessibility > Vibration
+    // CATEGORY: SETTINGS
+    // OS: P
+    ACCESSIBILITY_VIBRATION = 1292;
+
+    // OPEN: Settings > Accessibility > Vibration > Ring & notification vibration
+    // CATEGORY: SETTINGS
+    // OS: P
+    ACCESSIBILITY_VIBRATION_NOTIFICATION = 1293;
+
+    // OPEN: Settings > Accessibility > Vibration > Touch vibration
+    // CATEGORY: SETTINGS
+    // OS: P
+    ACCESSIBILITY_VIBRATION_TOUCH = 1294;
+
+    // OPEN: Volume panel > output chooser dialog
+    // OS: P
+    OUTPUT_CHOOSER = 1295;
+
+    // Action: Volume panel > output chooser dialog > tap on device
+    // OS: P
+    ACTION_OUTPUT_CHOOSER_CONNECT = 1296;
+
+    // Action: Volume panel > output chooser dialog > tap on X next to connected device
+    // OS: P
+    ACTION_OUTPUT_CHOOSER_DISCONNECT = 1297;
+
+    // OPEN: TV Settings > Home theater control
+    // OS: P
+    SETTINGS_TV_HOME_THEATER_CONTROL_CATEGORY = 1298;
+
+    // OPEN: TV Settings > TV Inputs (Inputs & Devices)
+    // OS: P
+    SETTINGS_TV_INPUTS_CATEGORY = 1299;
+
+    // OPEN: TV Settings > Device
+    // OS: P
+    SETTINGS_TV_DEVICE_CATEGORY = 1300;
+
+    // OPEN: TV Settings > Network > Proxy settings
+    // OS: P
+    DIALOG_TV_NETWORK_PROXY = 1301;
+
+    // Events for battery saver turning on/off and/or the interactive state changes.
+    // OS: P
+    BATTERY_SAVER = 1302;
+
+    // Device interactive state -- i.e. the screen ON (=1) or OFF (=1)
+    // OS: P
+    FIELD_INTERACTIVE = 1303;
+
+    // Time spent in milliseconds in the current mode.
+    // OS: P
+    FIELD_DURATION_MILLIS = 1304;
+
+    // Battery level in uA (0 - ~3,000,000 depending on device) when the current "mode" started.
+    // OS: P
+    FIELD_START_BATTERY_UA = 1305;
+
+    // Battery level in uA (0 - ~3,000,000 depending on device) when this event was created.
+    // OS: P
+    FIELD_END_BATTERY_UA = 1306;
+
+    // Battery level in % (0-100) when the current "mode" started.
+    // OS: P
+    FIELD_START_BATTERY_PERCENT = 1307;
+
+    // Battery level in % (0-100) when this event was created.
+    // OS: P
+    FIELD_END_BATTERY_PERCENT = 1308;
+
+    // ACTION: Settings > Display > Night Light
+    // SUBTYPE: com.android.server.display.ColorDisplayService.AutoMode value
+    // CATEGORY: SETTINGS
+    // OS: P
+    ACTION_NIGHT_DISPLAY_AUTO_MODE_CHANGED = 1309;
+
+    // ACTION: Settings > Display > Night Light
+    // CATEGORY: SETTINGS
+    // SUBTYPE: 0 is starting time, 1 is ending time
+    // OS: P
+    ACTION_NIGHT_DISPLAY_AUTO_MODE_CUSTOM_TIME_CHANGED = 1310;
+
+    // FIELD: Current mode corresponding to a QS tile
+    // CATEGORY: QUICK SETTINGS
+    // OS: P
+    FIELD_QS_MODE = 1311;
+
     // ---- End P Constants, all P constants go above this line ----
     // Add new aosp constants above this line.
     // END OF AOSP CONSTANTS
diff --git a/proto/src/system_messages.proto b/proto/src/system_messages.proto
index 08fdb97..608970f 100644
--- a/proto/src/system_messages.proto
+++ b/proto/src/system_messages.proto
@@ -204,6 +204,10 @@
     // Package: android
     NOTE_USB_TETHER = 47;
 
+    // Inform that DND settings have changed on OS upgrade
+    // Package: android
+    NOTE_ZEN_UPGRADE = 48;
+
     // ADD_NEW_IDS_ABOVE_THIS_LINE
     // Legacy IDs with arbitrary values appear below
     // Legacy IDs existed as stable non-conflicting constants prior to the O release
@@ -253,6 +257,7 @@
 
     // Notify the user about public volume state changes..
     // Package: com.android.systemui
+
     NOTE_STORAGE_PUBLIC = 0x53505542;  // 1397773634
 
     // Notify the user about private volume state changes.
diff --git a/rs/OWNERS b/rs/OWNERS
new file mode 100644
index 0000000..61853d3
--- /dev/null
+++ b/rs/OWNERS
@@ -0,0 +1,5 @@
+butlermichael@google.com
+dgross@google.com
+jeanluc@google.com
+miaowang@google.com
+yangni@google.com
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index fc6058c..eba9830 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -1020,7 +1020,7 @@
 
             // Disconnect from services for the old user.
             UserState oldUserState = getCurrentUserStateLocked();
-            oldUserState.onSwitchToAnotherUser();
+            oldUserState.onSwitchToAnotherUserLocked();
 
             // Disable the local managers for the old user.
             if (oldUserState.mUserClients.getRegisteredCallbackCount() > 0) {
@@ -1349,21 +1349,29 @@
     private void updateRelevantEventsLocked(UserState userState) {
         mMainHandler.post(() -> {
             broadcastToClients(userState, ignoreRemoteException(client -> {
-                int relevantEventTypes = computeRelevantEventTypes(userState, client);
+                int relevantEventTypes;
+                boolean changed = false;
+                synchronized (mLock) {
+                    relevantEventTypes = computeRelevantEventTypesLocked(userState, client);
 
-                if (client.mLastSentRelevantEventTypes != relevantEventTypes) {
-                    client.mLastSentRelevantEventTypes = relevantEventTypes;
+                    if (client.mLastSentRelevantEventTypes != relevantEventTypes) {
+                        client.mLastSentRelevantEventTypes = relevantEventTypes;
+                        changed = true;
+                    }
+                }
+                if (changed) {
                     client.mCallback.setRelevantEventTypes(relevantEventTypes);
                 }
             }));
         });
     }
 
-    private int computeRelevantEventTypes(UserState userState, Client client) {
+    private int computeRelevantEventTypesLocked(UserState userState, Client client) {
         int relevantEventTypes = 0;
 
-        // Use iterator for thread-safety
-        for (AccessibilityServiceConnection service : userState.mBoundServices) {
+        int serviceCount = userState.mBoundServices.size();
+        for (int i = 0; i < serviceCount; i++) {
+            AccessibilityServiceConnection service = userState.mBoundServices.get(i);
             relevantEventTypes |= isClientInPackageWhitelist(service.getServiceInfo(), client)
                     ? service.getRelevantEventTypes()
                     : 0;
@@ -3616,7 +3624,9 @@
         private Client(IAccessibilityManagerClient callback, int clientUid, UserState userState) {
             mCallback = callback;
             mPackageNames = mPackageManager.getPackagesForUid(clientUid);
-            mLastSentRelevantEventTypes = computeRelevantEventTypes(userState, this);
+            synchronized (mLock) {
+                mLastSentRelevantEventTypes = computeRelevantEventTypesLocked(userState, this);
+            }
         }
     }
 
@@ -3635,8 +3645,7 @@
 
         // Transient state.
 
-        public final CopyOnWriteArrayList<AccessibilityServiceConnection> mBoundServices =
-                new CopyOnWriteArrayList<>();
+        public final ArrayList<AccessibilityServiceConnection> mBoundServices = new ArrayList<>();
 
         public final Map<ComponentName, AccessibilityServiceConnection> mComponentNameToServiceMap =
                 new HashMap<>();
@@ -3698,7 +3707,7 @@
             return !mBoundServices.isEmpty() || !mBindingServices.isEmpty();
         }
 
-        public void onSwitchToAnotherUser() {
+        public void onSwitchToAnotherUserLocked() {
             // Unbind all services.
             unbindAllServicesLocked(this);
 
diff --git a/services/accessibility/java/com/android/server/accessibility/MagnificationController.java b/services/accessibility/java/com/android/server/accessibility/MagnificationController.java
index a70b88e..5b5d18f 100644
--- a/services/accessibility/java/com/android/server/accessibility/MagnificationController.java
+++ b/services/accessibility/java/com/android/server/accessibility/MagnificationController.java
@@ -446,8 +446,10 @@
             mMagnificationRegion.getBounds(viewport);
             final MagnificationSpec spec = mCurrentMagnificationSpec;
             final float oldScale = spec.scale;
-            final float oldCenterX = (viewport.width() / 2.0f - spec.offsetX) / oldScale;
-            final float oldCenterY = (viewport.height() / 2.0f - spec.offsetY) / oldScale;
+            final float oldCenterX
+                    = (viewport.width() / 2.0f - spec.offsetX + viewport.left) / oldScale;
+            final float oldCenterY
+                    = (viewport.height() / 2.0f - spec.offsetY + viewport.top) / oldScale;
             final float normPivotX = (pivotX - spec.offsetX) / oldScale;
             final float normPivotY = (pivotY - spec.offsetY) / oldScale;
             final float offsetX = (oldCenterX - normPivotX) * (oldScale / scale);
@@ -901,6 +903,7 @@
             }
         }
 
+        @GuardedBy("mLock")
         private void setMagnificationSpecLocked(MagnificationSpec spec) {
             if (mEnabled) {
                 if (DEBUG_SET_MAGNIFICATION_SPEC) {
diff --git a/services/accessibility/java/com/android/server/accessibility/MagnificationGestureHandler.java b/services/accessibility/java/com/android/server/accessibility/MagnificationGestureHandler.java
index 52ab85c..6c6dd5b 100644
--- a/services/accessibility/java/com/android/server/accessibility/MagnificationGestureHandler.java
+++ b/services/accessibility/java/com/android/server/accessibility/MagnificationGestureHandler.java
@@ -402,9 +402,9 @@
                     com.android.internal.R.dimen.config_screen_magnification_scaling_threshold,
                     scaleValue, false);
             mScalingThreshold = scaleValue.getFloat();
-            mScaleGestureDetector = new ScaleGestureDetector(context, this);
+            mScaleGestureDetector = new ScaleGestureDetector(context, this, Handler.getMain());
             mScaleGestureDetector.setQuickScaleEnabled(false);
-            mScrollGestureDetector = new GestureDetector(context, this);
+            mScrollGestureDetector = new GestureDetector(context, this, Handler.getMain());
         }
 
         @Override
@@ -638,7 +638,7 @@
 
         @VisibleForTesting boolean mShortcutTriggered;
 
-        @VisibleForTesting Handler mHandler = new Handler(this);
+        @VisibleForTesting Handler mHandler = new Handler(Looper.getMainLooper(), this);
 
         public DetectingState(Context context) {
             mLongTapMinDelay = ViewConfiguration.getLongPressTimeout();
@@ -654,7 +654,9 @@
             final int type = message.what;
             switch (type) {
                 case MESSAGE_ON_TRIPLE_TAP_AND_HOLD: {
-                    onTripleTapAndHold(/* down */ (MotionEvent) message.obj);
+                    MotionEvent down = (MotionEvent) message.obj;
+                    transitionToViewportDraggingStateAndClear(down);
+                    down.recycle();
                 }
                 break;
                 case MESSAGE_TRANSITION_TO_DELEGATING_STATE: {
@@ -720,8 +722,7 @@
                         // over insta-delegating on 3tap&swipe
                         // (which is a rare combo to be used aside from magnification)
                         if (isMultiTapTriggered(2 /* taps */)) {
-                            transitionTo(mViewportDraggingState);
-                            clear();
+                            transitionToViewportDraggingStateAndClear(event);
                         } else {
                             transitionToDelegatingStateAndClear();
                         }
@@ -806,7 +807,8 @@
         /** -> {@link ViewportDraggingState} */
         public void afterLongTapTimeoutTransitionToDraggingState(MotionEvent event) {
             mHandler.sendMessageDelayed(
-                    mHandler.obtainMessage(MESSAGE_ON_TRIPLE_TAP_AND_HOLD, event),
+                    mHandler.obtainMessage(MESSAGE_ON_TRIPLE_TAP_AND_HOLD,
+                            MotionEvent.obtain(event)),
                     ViewConfiguration.getLongPressTimeout());
         }
 
@@ -890,7 +892,7 @@
             }
         }
 
-        void onTripleTapAndHold(MotionEvent down) {
+        void transitionToViewportDraggingStateAndClear(MotionEvent down) {
 
             if (DEBUG_DETECTING) Slog.i(LOG_TAG, "onTripleTapAndHold()");
             clear();
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
index 72c3c94..db62961 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
@@ -24,7 +24,6 @@
 import static com.android.server.autofill.Helper.sPartitionMaxCount;
 import static com.android.server.autofill.Helper.sVerbose;
 
-import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.UserIdInt;
@@ -56,7 +55,12 @@
 import android.provider.Settings;
 import android.service.autofill.FillEventHistory;
 import android.service.autofill.UserData;
+import android.text.TextUtils;
+import android.text.TextUtils.SimpleStringSplitter;
+import android.util.ArrayMap;
+import android.util.ArraySet;
 import android.util.LocalLog;
+import android.util.Pair;
 import android.util.Slog;
 import android.util.SparseArray;
 import android.util.SparseBooleanArray;
@@ -84,6 +88,7 @@
 import java.util.Arrays;
 import java.util.List;
 import java.util.Objects;
+import java.util.Set;
 
 /**
  * Entry point service for autofill management.
@@ -98,6 +103,8 @@
 
     static final String RECEIVER_BUNDLE_EXTRA_SESSIONS = "sessions";
 
+    private static final char COMPAT_PACKAGE_DELIMITER = ':';
+
     private final Context mContext;
     private final AutoFillUI mUi;
 
@@ -123,6 +130,9 @@
     private final LocalLog mUiLatencyHistory = new LocalLog(20);
     private final LocalLog mWtfHistory = new LocalLog(50);
 
+    private final AutofillCompatState mAutofillCompatState = new AutofillCompatState();
+    private final LocalService mLocalService = new LocalService();
+
     private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
@@ -271,7 +281,7 @@
     @Override
     public void onStart() {
         publishBinderService(AUTOFILL_MANAGER_SERVICE, new AutoFillManagerServiceStub());
-        publishLocalService(AutofillManagerInternal.class, new LocalService());
+        publishLocalService(AutofillManagerInternal.class, mLocalService);
     }
 
     @Override
@@ -306,6 +316,7 @@
      *
      * @return service instance.
      */
+    @GuardedBy("mLock")
     @NonNull
     AutofillManagerServiceImpl getServiceForUserLocked(int userId) {
         final int resolvedUserId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
@@ -316,6 +327,7 @@
                     mUiLatencyHistory, mWtfHistory, resolvedUserId, mUi,
                     mDisabledUsers.get(resolvedUserId));
             mServicesCache.put(userId, service);
+            addCompatibilityModeRequestsLocked(service, userId);
         }
         return service;
     }
@@ -325,6 +337,7 @@
      *
      * @return service instance or {@code null} if not already present
      */
+    @GuardedBy("mLock")
     @Nullable
     AutofillManagerServiceImpl peekServiceForUserLocked(int userId) {
         final int resolvedUserId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
@@ -474,17 +487,20 @@
     /**
      * Removes a cached service for a given user.
      */
+    @GuardedBy("mLock")
     private void removeCachedServiceLocked(int userId) {
         final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
         if (service != null) {
             mServicesCache.delete(userId);
             service.destroyLocked();
+            mAutofillCompatState.removeCompatibilityModeRequests(userId);
         }
     }
 
     /**
      * Updates a cached service for a given user.
      */
+    @GuardedBy("mLock")
     private void updateCachedServiceLocked(int userId) {
         updateCachedServiceLocked(userId, mDisabledUsers.get(userId));
     }
@@ -492,6 +508,7 @@
     /**
      * Updates a cached service for a given user.
      */
+    @GuardedBy("mLock")
     private void updateCachedServiceLocked(int userId, boolean disabled) {
         AutofillManagerServiceImpl service = getServiceForUserLocked(userId);
         if (service != null) {
@@ -499,12 +516,53 @@
             service.updateLocked(disabled);
             if (!service.isEnabledLocked()) {
                 removeCachedServiceLocked(userId);
+            } else {
+                addCompatibilityModeRequestsLocked(service, userId);
             }
         }
     }
 
-    private final class LocalService extends AutofillManagerInternal {
+    private void addCompatibilityModeRequestsLocked(@NonNull AutofillManagerServiceImpl service
+            , int userId) {
+        final ArrayMap<String, Pair<Long, String>> compatPackages =
+                service.getCompatibilityPackagesLocked();
+        if (compatPackages == null || compatPackages.isEmpty()) {
+            return;
+        }
+        final Set<String> whiteListedPackages = getWhitelistedCompatModePackages();
+        final int compatPackageCount = compatPackages.size();
+        for (int i = 0; i < compatPackageCount; i++) {
+            final String packageName = compatPackages.keyAt(i);
+            if (whiteListedPackages == null || !whiteListedPackages.contains(packageName)) {
+                Slog.w(TAG, "Ignoring not whitelisted compat package " + packageName);
+                continue;
+            }
+            final Long maxVersionCode = compatPackages.valueAt(i).first;
+            if (maxVersionCode != null) {
+                mAutofillCompatState.addCompatibilityModeRequest(packageName,
+                        maxVersionCode, userId);
+            }
+        }
+    }
 
+    private @Nullable Set<String> getWhitelistedCompatModePackages() {
+        final String compatPackagesSetting = Settings.Global.getString(
+                mContext.getContentResolver(),
+                Settings.Global.AUTOFILL_COMPAT_ALLOWED_PACKAGES);
+        if (TextUtils.isEmpty(compatPackagesSetting)) {
+            return null;
+        }
+        final Set<String> compatPackages = new ArraySet<>();
+        final SimpleStringSplitter splitter = new SimpleStringSplitter(
+                COMPAT_PACKAGE_DELIMITER);
+        splitter.setString(compatPackagesSetting);
+        while (splitter.hasNext()) {
+            compatPackages.add(splitter.next());
+        }
+        return compatPackages;
+    }
+
+    private final class LocalService extends AutofillManagerInternal {
         @Override
         public void onBackKeyPressed() {
             if (sDebug) Slog.d(TAG, "onBackKeyPressed()");
@@ -514,13 +572,59 @@
         @Override
         public boolean isCompatibilityModeRequested(@NonNull String packageName,
                 long versionCode, @UserIdInt int userId) {
+            return mAutofillCompatState.isCompatibilityModeRequested(
+                    packageName, versionCode, userId);
+        }
+    }
+
+    private static final class AutofillCompatState {
+        private final Object mLock = new Object();
+
+        @GuardedBy("mLock")
+        private SparseArray<ArrayMap<String, Long>> mUserSpecs;
+
+        boolean isCompatibilityModeRequested(@NonNull String packageName,
+                long versionCode, @UserIdInt int userId) {
             synchronized (mLock) {
-                final AutofillManagerServiceImpl service = getServiceForUserLocked(userId);
-                if (service != null) {
-                    return service.isCompatibilityModeRequestedLocked(packageName, versionCode);
+                if (mUserSpecs == null) {
+                    return false;
+                }
+                final ArrayMap<String, Long> userSpec = mUserSpecs.get(userId);
+                if (userSpec == null) {
+                    return false;
+                }
+                final Long maxVersionCode = userSpec.get(packageName);
+                if (maxVersionCode == null) {
+                    return false;
+                }
+                return versionCode <= maxVersionCode;
+            }
+        }
+
+        void addCompatibilityModeRequest(@NonNull String packageName,
+                long versionCode, @UserIdInt int userId) {
+            synchronized (mLock) {
+                if (mUserSpecs == null) {
+                    mUserSpecs = new SparseArray<>();
+                }
+                ArrayMap<String, Long> userSpec = mUserSpecs.get(userId);
+                if (userSpec == null) {
+                    userSpec = new ArrayMap<>();
+                    mUserSpecs.put(userId, userSpec);
+                }
+                userSpec.put(packageName, versionCode);
+            }
+        }
+
+        void removeCompatibilityModeRequests(@UserIdInt int userId) {
+            synchronized (mLock) {
+                if (mUserSpecs != null) {
+                    mUserSpecs.remove(userId);
+                    if (mUserSpecs.size() <= 0) {
+                        mUserSpecs = null;
+                    }
                 }
             }
-            return false;
         }
     }
 
@@ -575,7 +679,7 @@
         @Override
         public int startSession(IBinder activityToken, IBinder appCallback, AutofillId autofillId,
                 Rect bounds, AutofillValue value, int userId, boolean hasCallback, int flags,
-                ComponentName componentName) {
+                ComponentName componentName, boolean compatMode) {
 
             activityToken = Preconditions.checkNotNull(activityToken, "activityToken");
             appCallback = Preconditions.checkNotNull(appCallback, "appCallback");
@@ -594,7 +698,7 @@
             synchronized (mLock) {
                 final AutofillManagerServiceImpl service = getServiceForUserLocked(userId);
                 return service.startSessionLocked(activityToken, getCallingUid(), appCallback,
-                        autofillId, bounds, value, hasCallback, flags, componentName);
+                        autofillId, bounds, value, hasCallback, flags, componentName, compatMode);
             }
         }
 
@@ -765,7 +869,7 @@
         public int updateOrRestartSession(IBinder activityToken, IBinder appCallback,
                 AutofillId autoFillId, Rect bounds, AutofillValue value, int userId,
                 boolean hasCallback, int flags, ComponentName componentName, int sessionId,
-                int action) {
+                int action, boolean compatMode) {
             boolean restart = false;
             synchronized (mLock) {
                 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
@@ -778,7 +882,7 @@
             }
             if (restart) {
                 return startSession(activityToken, appCallback, autoFillId, bounds, value, userId,
-                        hasCallback, flags, componentName);
+                        hasCallback, flags, componentName, compatMode);
             }
 
             // Nothing changed...
@@ -909,6 +1013,8 @@
                         }
                     }
                     mUi.dump(pw);
+                    pw.print("Autofill Compat State: ");
+                    pw.println(mAutofillCompatState.mUserSpecs);
                 }
                 if (showHistory) {
                     pw.println(); pw.println("Requests history:"); pw.println();
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
index 297dcf1..c201de4 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
@@ -40,7 +40,6 @@
 import android.metrics.LogMaker;
 import android.os.AsyncTask;
 import android.os.Binder;
-import android.os.Build;
 import android.os.Bundle;
 import android.os.IBinder;
 import android.os.Looper;
@@ -64,6 +63,7 @@
 import android.util.ArraySet;
 import android.util.DebugUtils;
 import android.util.LocalLog;
+import android.util.Pair;
 import android.util.Slog;
 import android.util.SparseArray;
 import android.util.TimeUtils;
@@ -211,6 +211,7 @@
         }
     }
 
+    @GuardedBy("mLock")
     private int getServiceUidLocked() {
         if (mInfo == null) {
             Slog.w(TAG,  "getServiceUidLocked(): no mInfo");
@@ -219,6 +220,17 @@
         return mInfo.getServiceInfo().applicationInfo.uid;
     }
 
+
+    @GuardedBy("mLock")
+    @Nullable
+    String getUrlBarResourceIdForCompatModeLocked(@NonNull String packageName) {
+        if (mInfo == null) {
+            Slog.w(TAG,  "getUrlBarResourceIdForCompatModeLocked(): no mInfo");
+            return null;
+        }
+        return mInfo.getUrlBarResourceId(packageName);
+    }
+
     @Nullable
     String getServicePackageName() {
         final ComponentName serviceComponent = getServiceComponentName();
@@ -248,6 +260,7 @@
                 mContext.getContentResolver(), Settings.Secure.AUTOFILL_SERVICE, mUserId);
     }
 
+    @GuardedBy("mLock")
     void updateLocked(boolean disabled) {
         final boolean wasEnabled = isEnabledLocked();
         if (sVerbose) {
@@ -300,6 +313,7 @@
         }
     }
 
+    @GuardedBy("mLock")
     boolean addClientLocked(IAutoFillManagerClient client) {
         if (mClients == null) {
             mClients = new RemoteCallbackList<>();
@@ -308,12 +322,14 @@
         return isEnabledLocked();
     }
 
+    @GuardedBy("mLock")
     void removeClientLocked(IAutoFillManagerClient client) {
         if (mClients != null) {
             mClients.unregister(client);
         }
     }
 
+    @GuardedBy("mLock")
     void setAuthenticationResultLocked(Bundle data, int sessionId, int authenticationId, int uid) {
         if (!isEnabledLocked()) {
             return;
@@ -336,10 +352,11 @@
         }
     }
 
+    @GuardedBy("mLock")
     int startSessionLocked(@NonNull IBinder activityToken, int uid,
             @NonNull IBinder appCallbackToken, @NonNull AutofillId autofillId,
             @NonNull Rect virtualBounds, @Nullable AutofillValue value, boolean hasCallback,
-            int flags, @NonNull ComponentName componentName) {
+            int flags, @NonNull ComponentName componentName, boolean compatMode) {
         if (!isEnabledLocked()) {
             return 0;
         }
@@ -369,7 +386,7 @@
         pruneAbandonedSessionsLocked();
 
         final Session newSession = createSessionByTokenLocked(activityToken, uid, appCallbackToken,
-                hasCallback, componentName, flags);
+                hasCallback, componentName, compatMode, flags);
         if (newSession == null) {
             return NO_SESSION;
         }
@@ -389,6 +406,7 @@
     /**
      * Remove abandoned sessions if needed.
      */
+    @GuardedBy("mLock")
     private void pruneAbandonedSessionsLocked() {
         long now = System.currentTimeMillis();
         if (mLastPrune < now - MAX_ABANDONED_SESSION_MILLIS) {
@@ -400,6 +418,7 @@
         }
     }
 
+    @GuardedBy("mLock")
     void finishSessionLocked(int sessionId, int uid) {
         if (!isEnabledLocked()) {
             return;
@@ -423,6 +442,7 @@
         }
     }
 
+    @GuardedBy("mLock")
     void cancelSessionLocked(int sessionId, int uid) {
         if (!isEnabledLocked()) {
             return;
@@ -436,6 +456,7 @@
         session.removeSelfLocked();
     }
 
+    @GuardedBy("mLock")
     void disableOwnedAutofillServicesLocked(int uid) {
         Slog.i(TAG, "disableOwnedServices(" + uid + "): " + mInfo);
         if (mInfo == null) return;
@@ -468,9 +489,10 @@
         }
     }
 
+    @GuardedBy("mLock")
     private Session createSessionByTokenLocked(@NonNull IBinder activityToken, int uid,
             @NonNull IBinder appCallbackToken, boolean hasCallback,
-            @NonNull ComponentName componentName, int flags) {
+            @NonNull ComponentName componentName, boolean compatMode, int flags) {
         // use random ids so that one app cannot know that another app creates sessions
         int sessionId;
         int tries = 0;
@@ -488,7 +510,8 @@
 
         final Session newSession = new Session(this, mUi, mContext, mHandlerCaller, mUserId, mLock,
                 sessionId, uid, activityToken, appCallbackToken, hasCallback, mUiLatencyHistory,
-                mWtfHistory, mInfo.getServiceInfo().getComponentName(), componentName, flags);
+                mWtfHistory, mInfo.getServiceInfo().getComponentName(), componentName, compatMode,
+                flags);
         mSessions.put(newSession.id, newSession);
 
         return newSession;
@@ -546,6 +569,7 @@
     /**
      * Updates a session and returns whether it should be restarted.
      */
+    @GuardedBy("mLock")
     boolean updateSessionLocked(int sessionId, int uid, AutofillId autofillId, Rect virtualBounds,
             AutofillValue value, int action, int flags) {
         final Session session = mSessions.get(sessionId);
@@ -568,6 +592,7 @@
         return false;
     }
 
+    @GuardedBy("mLock")
     void removeSessionLocked(int sessionId) {
         mSessions.remove(sessionId);
     }
@@ -603,6 +628,7 @@
         }
     }
 
+    @GuardedBy("mLock")
     void destroyLocked() {
         if (sVerbose) Slog.v(TAG, "destroyLocked()");
 
@@ -655,6 +681,7 @@
         }
     }
 
+    @GuardedBy("mLock")
     private boolean isValidEventLocked(String method, int sessionId) {
         if (mEventHistory == null) {
             Slog.w(TAG, method + ": not logging event because history is null");
@@ -726,6 +753,7 @@
     /**
      * Updates the last fill response when an autofill context is committed.
      */
+    @GuardedBy("mLock")
     void logContextCommittedLocked(int sessionId, @Nullable Bundle clientState,
             @Nullable ArrayList<String> selectedDatasets,
             @Nullable ArraySet<String> ignoredDatasets,
@@ -739,6 +767,7 @@
                 manuallyFilledDatasetIds, null, null, appPackageName);
     }
 
+    @GuardedBy("mLock")
     void logContextCommittedLocked(int sessionId, @Nullable Bundle clientState,
             @Nullable ArrayList<String> selectedDatasets,
             @Nullable ArraySet<String> ignoredDatasets,
@@ -840,13 +869,14 @@
             }
             mUserData = userData;
             // Log it
-            int numberFields = mUserData == null ? 0: mUserData.getRemoteIds().length;
+            int numberFields = mUserData == null ? 0: mUserData.getCategoryIds().length;
             mMetricsLogger.write(Helper.newLogMaker(MetricsEvent.AUTOFILL_USERDATA_UPDATED,
                     getServicePackageName(), null)
-                    .setCounterValue(numberFields));
+                    .addTaggedData(MetricsEvent.FIELD_AUTOFILL_NUM_VALUES, numberFields));
         }
     }
 
+    @GuardedBy("mLock")
     private boolean isCalledByServiceLocked(String methodName, int callingUid) {
         if (getServiceUidLocked() != callingUid) {
             Slog.w(TAG, methodName + "() called by UID " + callingUid
@@ -856,13 +886,19 @@
         return true;
     }
 
+    @GuardedBy("mLock")
     void dumpLocked(String prefix, PrintWriter pw) {
         final String prefix2 = prefix + "  ";
 
         pw.print(prefix); pw.print("User: "); pw.println(mUserId);
         pw.print(prefix); pw.print("UID: "); pw.println(getServiceUidLocked());
-        pw.print(prefix); pw.print("Component: "); pw.println(mInfo != null
-                ? mInfo.getServiceInfo().getComponentName() : null);
+        pw.print(prefix); pw.print("Autofill Service Info: ");
+        if (mInfo == null) {
+            pw.println("N/A");
+        } else {
+            pw.println();
+            mInfo.dump(prefix2, pw);
+        }
         pw.print(prefix); pw.print("Component from settings: ");
             pw.println(getComponentNameFromSettings());
         pw.print(prefix); pw.print("Default component: ");
@@ -870,6 +906,13 @@
         pw.print(prefix); pw.print("Disabled: "); pw.println(mDisabled);
         pw.print(prefix); pw.print("Field classification enabled: ");
             pw.println(isFieldClassificationEnabledLocked());
+        pw.print(prefix); pw.print("Compat pkgs: ");
+        final ArrayMap<String, Pair<Long, String>> compatPkgs = getCompatibilityPackagesLocked();
+        if (compatPkgs == null) {
+            pw.println("N/A");
+        } else {
+            pw.println(compatPkgs);
+        }
         pw.print(prefix); pw.print("Setup complete: "); pw.println(mSetupComplete);
         pw.print(prefix); pw.print("Last prune: "); pw.println(mLastPrune);
 
@@ -959,6 +1002,7 @@
         mFieldClassificationStrategy.dump(prefix2, pw);
     }
 
+    @GuardedBy("mLock")
     void destroySessionsLocked() {
         if (mSessions.size() == 0) {
             mUi.destroyAll(null, null, false);
@@ -970,6 +1014,7 @@
     }
 
     // TODO(b/64940307): remove this method if SaveUI is refactored to be attached on activities
+    @GuardedBy("mLock")
     void destroyFinishedSessionsLocked() {
         final int sessionCount = mSessions.size();
         for (int i = sessionCount - 1; i >= 0; i--) {
@@ -981,6 +1026,7 @@
         }
     }
 
+    @GuardedBy("mLock")
     void listSessionsLocked(ArrayList<String> output) {
         final int numSessions = mSessions.size();
         for (int i = 0; i < numSessions; i++) {
@@ -989,19 +1035,12 @@
         }
     }
 
-    boolean isCompatibilityModeRequestedLocked(@NonNull String packageName,
-            long versionCode) {
-        if (mInfo == null || !mInfo.isCompatibilityModeRequested(packageName, versionCode)) {
-            return false;
+    @GuardedBy("mLock")
+    @Nullable ArrayMap<String, Pair<Long, String>> getCompatibilityPackagesLocked() {
+        if (mInfo != null) {
+            return mInfo.getCompatibilityPackages();
         }
-        if (!Build.IS_ENG) {
-            // TODO: Build a map and watch for settings changes (this is called on app start)
-            final String whiteListedPackages = Settings.Global.getString(
-                    mContext.getContentResolver(),
-                    Settings.Global.AUTOFILL_COMPAT_ALLOWED_PACKAGES);
-            return whiteListedPackages != null && whiteListedPackages.contains(packageName);
-        }
-        return true;
+        return null;
     }
 
     private void sendStateToClients(boolean resetClient) {
@@ -1050,6 +1089,7 @@
         }
     }
 
+    @GuardedBy("mLock")
     private boolean isClientSessionDestroyedLocked(IAutoFillManagerClient client) {
         final int sessionCount = mSessions.size();
         for (int i = 0; i < sessionCount; i++) {
@@ -1061,6 +1101,7 @@
         return true;
     }
 
+    @GuardedBy("mLock")
     boolean isEnabledLocked() {
         return mSetupComplete && mInfo != null && !mDisabled;
     }
@@ -1113,6 +1154,7 @@
     /**
      * Checks if autofill is disabled by service to the given activity.
      */
+    @GuardedBy("mLock")
     private boolean isAutofillDisabledLocked(@NonNull ComponentName componentName) {
         // Check activities first.
         long elapsedTime = 0;
diff --git a/services/autofill/java/com/android/server/autofill/Helper.java b/services/autofill/java/com/android/server/autofill/Helper.java
index 02a62e1..5ef467d 100644
--- a/services/autofill/java/com/android/server/autofill/Helper.java
+++ b/services/autofill/java/com/android/server/autofill/Helper.java
@@ -18,11 +18,14 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.app.assist.AssistStructure;
+import android.app.assist.AssistStructure.ViewNode;
 import android.metrics.LogMaker;
 import android.os.Bundle;
 import android.service.autofill.Dataset;
 import android.util.ArrayMap;
 import android.util.ArraySet;
+import android.util.Slog;
 import android.view.autofill.AutofillId;
 import android.view.autofill.AutofillValue;
 
@@ -31,11 +34,14 @@
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.LinkedList;
 import java.util.Objects;
 import java.util.Set;
 
 public final class Helper {
 
+    private static final String TAG = "AutofillHelper";
+
     /**
      * Defines a logging flag that can be dynamically changed at runtime using
      * {@code cmd autofill set log_level debug}.
@@ -121,4 +127,61 @@
             pw.print(text.length()); pw.println("_chars");
         }
     }
+
+    /**
+     * Finds the {@link ViewNode} that has the requested {@code autofillId}, if any.
+     */
+    @Nullable
+    public static ViewNode findViewNodeByAutofillId(@NonNull AssistStructure structure,
+            @NonNull AutofillId autofillId) {
+        return findViewNode(structure, (node) -> {
+            return autofillId.equals(node.getAutofillId());
+        });
+    }
+
+    private static ViewNode findViewNode(@NonNull AssistStructure structure,
+            @NonNull ViewNodeFilter filter) {
+        final LinkedList<ViewNode> nodesToProcess = new LinkedList<>();
+        final int numWindowNodes = structure.getWindowNodeCount();
+        for (int i = 0; i < numWindowNodes; i++) {
+            nodesToProcess.add(structure.getWindowNodeAt(i).getRootViewNode());
+        }
+        while (!nodesToProcess.isEmpty()) {
+            final ViewNode node = nodesToProcess.removeFirst();
+            if (filter.matches(node)) {
+                return node;
+            }
+            for (int i = 0; i < node.getChildCount(); i++) {
+                nodesToProcess.addLast(node.getChildAt(i));
+            }
+        }
+
+        return null;
+    }
+
+    /**
+     * Sanitize the {@code webDomain} property of the URL bar node on compat mode.
+     */
+    public static void sanitizeUrlBar(@NonNull AssistStructure structure,
+            @NonNull String urlBarId) {
+        final ViewNode urlBarNode = findViewNode(structure, (node) -> {
+            return urlBarId.equals(node.getIdEntry());
+        });
+        if (urlBarNode != null) {
+            final String domain = urlBarNode.getText().toString();
+            if (domain.isEmpty()) {
+                if (sDebug) Slog.d(TAG, "sanitizeUrlBar(): empty on " + urlBarId);
+                return;
+            }
+            urlBarNode.setWebDomain(domain);
+            if (sDebug) {
+                Slog.d(TAG, "sanitizeUrlBar(): id=" + urlBarId + ", domain="
+                        + urlBarNode.getWebDomain());
+            }
+        }
+    }
+
+    private interface ViewNodeFilter {
+        boolean matches(ViewNode node);
+    }
 }
diff --git a/services/autofill/java/com/android/server/autofill/RemoteFillService.java b/services/autofill/java/com/android/server/autofill/RemoteFillService.java
index aea9ad0..fe6d4c4 100644
--- a/services/autofill/java/com/android/server/autofill/RemoteFillService.java
+++ b/services/autofill/java/com/android/server/autofill/RemoteFillService.java
@@ -475,6 +475,7 @@
             return true;
         }
 
+        @GuardedBy("mLock")
         protected boolean isCancelledLocked() {
             return mCancelled;
         }
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 6108afa..ef6ed08 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -140,6 +140,9 @@
     /** Component that's being auto-filled */
     @NonNull private final ComponentName mComponentName;
 
+    /** Whether the app being autofilled is running in compat mode. */
+    private final boolean mCompatMode;
+
     @GuardedBy("mLock")
     private final ArrayMap<AutofillId, ViewState> mViewStates = new ArrayMap<>();
 
@@ -263,6 +266,15 @@
                                     componentNameFromApp == null ? "null"
                                             : componentNameFromApp.flattenToShortString()));
                 }
+                if (mCompatMode) {
+                    // Sanitize URL bar, if needed
+                    final String urlBarId = mService.getUrlBarResourceIdForCompatModeLocked(
+                            mComponentName.getPackageName());
+                    if (sDebug) Slog.d(TAG, "url_bar in compat mode: " + urlBarId);
+                    if (urlBarId != null) {
+                        Helper.sanitizeUrlBar(structure, urlBarId);
+                    }
+                }
                 structure.sanitizeForParceling(true);
 
                 // Flags used to start the session.
@@ -300,6 +312,7 @@
     /**
      * Returns the ids of all entries in {@link #mViewStates} in the same order.
      */
+    @GuardedBy("mLock")
     private AutofillId[] getIdsOfAllViewStatesLocked() {
         final int numViewState = mViewStates.size();
         final AutofillId[] ids = new AutofillId[numViewState];
@@ -346,6 +359,7 @@
      * <p>Gets the value of a field, using either the {@code viewStates} or the {@code mContexts},
      * or {@code null} when not found on either of them.
      */
+    @GuardedBy("mLock")
     private AutofillValue findValueLocked(@NonNull AutofillId id) {
         final ViewState state = mViewStates.get(id);
         if (state == null) {
@@ -362,6 +376,7 @@
 
     /**
      * Updates values of the nodes in the context's structure so that:
+     *
      * - proper node is focused
      * - autofillValue is sent back to service when it was previously autofilled
      * - autofillValue is sent in the view used to force a request
@@ -369,6 +384,7 @@
      * @param fillContext The context to be filled
      * @param flags The flags that started the session
      */
+    @GuardedBy("mLock")
     private void fillContextWithAllowedValuesLocked(@NonNull FillContext fillContext, int flags) {
         final ViewNode[] nodes = fillContext
                 .findViewNodesByAutofillIds(getIdsOfAllViewStatesLocked());
@@ -380,7 +396,8 @@
             final ViewNode node = nodes[i];
             if (node == null) {
                 if (sVerbose) {
-                    Slog.v(TAG, "fillStructureWithAllowedValues(): no node for " + viewState.id);
+                    Slog.v(TAG,
+                            "fillContextWithAllowedValuesLocked(): no node for " + viewState.id);
                 }
                 continue;
             }
@@ -409,6 +426,7 @@
     /**
      * Cancels the last request sent to the {@link #mRemoteFillService}.
      */
+    @GuardedBy("mLock")
     private void cancelCurrentRequestLocked() {
         final int canceledRequest = mRemoteFillService.cancelCurrentRequest();
 
@@ -430,6 +448,7 @@
     /**
      * Reads a new structure and then request a new fill response from the fill service.
      */
+    @GuardedBy("mLock")
     private void requestNewFillResponseLocked(int flags) {
         int requestId;
 
@@ -471,7 +490,7 @@
             @NonNull IBinder client, boolean hasCallback, @NonNull LocalLog uiLatencyHistory,
             @NonNull LocalLog wtfHistory,
             @NonNull ComponentName serviceComponentName, @NonNull ComponentName componentName,
-            int flags) {
+            boolean compatMode, int flags) {
         id = sessionId;
         mFlags = flags;
         this.uid = uid;
@@ -486,6 +505,7 @@
         mUiLatencyHistory = uiLatencyHistory;
         mWtfHistory = wtfHistory;
         mComponentName = componentName;
+        mCompatMode = compatMode;
         mClient = IAutoFillManagerClient.Stub.asInterface(client);
 
         mMetricsLogger.write(newLogMaker(MetricsEvent.AUTOFILL_SESSION_STARTED)
@@ -497,6 +517,7 @@
      *
      * @return The activity token
      */
+    @GuardedBy("mLock")
     @NonNull IBinder getActivityTokenLocked() {
         return mActivityToken;
     }
@@ -663,6 +684,7 @@
      *
      * @return The context or {@code null} if there is no context
      */
+    @GuardedBy("mLock")
     @Nullable private FillContext getFillContextByRequestIdLocked(int requestId) {
         if (mContexts == null) {
             return null;
@@ -820,6 +842,7 @@
         });
     }
 
+    @GuardedBy("mLock")
     void setAuthenticationResultLocked(Bundle data, int authenticationId) {
         if (mDestroyed) {
             Slog.w(TAG, "Call to Session#setAuthenticationResultLocked() rejected - session: "
@@ -882,6 +905,7 @@
         }
     }
 
+    @GuardedBy("mLock")
     void setHasCallbackLocked(boolean hasIt) {
         if (mDestroyed) {
             Slog.w(TAG, "Call to Session#setHasCallbackLocked() rejected - session: "
@@ -891,6 +915,7 @@
         mHasCallback = hasIt;
     }
 
+    @GuardedBy("mLock")
     @Nullable
     private FillResponse getLastResponseLocked(@Nullable String logPrefix) {
         if (mContexts == null) {
@@ -923,6 +948,7 @@
         return response;
     }
 
+    @GuardedBy("mLock")
     @Nullable
     private SaveInfo getSaveInfoLocked() {
         final FillResponse response = getLastResponseLocked(null);
@@ -941,13 +967,14 @@
         });
     }
 
+    @GuardedBy("mLock")
     private void logContextCommittedLocked() {
         final FillResponse lastResponse = getLastResponseLocked("logContextCommited()");
         if (lastResponse == null) return;
 
         final int flags = lastResponse.getFlags();
         if ((flags & FillResponse.FLAG_TRACK_CONTEXT_COMMITED) == 0) {
-            if (sDebug) Slog.d(TAG, "logContextCommittedLocked(): ignored by flags " + flags);
+            if (sVerbose) Slog.v(TAG, "logContextCommittedLocked(): ignored by flags " + flags);
             return;
         }
 
@@ -1149,12 +1176,12 @@
             @NonNull UserData userData, @NonNull Collection<ViewState> viewStates) {
 
         final String[] userValues = userData.getValues();
-        final String[] remoteIds = userData.getRemoteIds();
+        final String[] categoryIds = userData.getCategoryIds();
 
         // Sanity check
-        if (userValues == null || remoteIds == null || userValues.length != remoteIds.length) {
+        if (userValues == null || categoryIds == null || userValues.length != categoryIds.length) {
             final int valuesLength = userValues == null ? -1 : userValues.length;
-            final int idsLength = remoteIds == null ? -1 : remoteIds.length;
+            final int idsLength = categoryIds == null ? -1 : categoryIds.length;
             Slog.w(TAG, "setScores(): user data mismatch: values.length = "
                     + valuesLength + ", ids.length = " + idsLength);
             return;
@@ -1171,12 +1198,12 @@
         final int viewsSize = viewStates.size();
 
         // First, we get all scores.
-        final AutofillId[] fieldIds = new AutofillId[viewsSize];
+        final AutofillId[] autofillIds = new AutofillId[viewsSize];
         final ArrayList<AutofillValue> currentValues = new ArrayList<>(viewsSize);
         int k = 0;
         for (ViewState viewState : viewStates) {
             currentValues.add(viewState.getCurrentValue());
-            fieldIds[k++] = viewState.id;
+            autofillIds[k++] = viewState.id;
         }
 
         // Then use the results, asynchronously
@@ -1196,32 +1223,53 @@
             }
             int i = 0, j = 0;
             try {
+                // Iteract over all autofill fields first
                 for (i = 0; i < viewsSize; i++) {
-                    final AutofillId fieldId = fieldIds[i];
+                    final AutofillId autofillId = autofillIds[i];
 
-                    ArrayList<Match> matches = null;
+                    // Search the best scores for each category (as some categories could have
+                    // multiple user values
+                    ArrayMap<String, Float> scoresByField = null;
                     for (j = 0; j < userValues.length; j++) {
-                        String remoteId = remoteIds[j];
+                        final String categoryId = categoryIds[j];
                         final float score = scores.scores[i][j];
                         if (score > 0) {
+                            if (scoresByField == null) {
+                                scoresByField = new ArrayMap<>(userValues.length);
+                            }
+                            final Float currentScore = scoresByField.get(categoryId);
+                            if (currentScore != null && currentScore > score) {
+                                if (sVerbose) {
+                                    Slog.v(TAG,  "skipping score " + score
+                                            + " because it's less than " + currentScore);
+                                }
+                                continue;
+                            }
                             if (sVerbose) {
                                 Slog.v(TAG, "adding score " + score + " at index " + j + " and id "
-                                        + fieldId);
+                                        + autofillId);
                             }
-                            if (matches == null) {
-                                matches = new ArrayList<>(userValues.length);
-                            }
-                            matches.add(new Match(remoteId, score));
+                            scoresByField.put(categoryId, score);
                         }
                         else if (sVerbose) {
-                            Slog.v(TAG, "skipping score 0 at index " + j + " and id " + fieldId);
+                            Slog.v(TAG, "skipping score 0 at index " + j + " and id " + autofillId);
                         }
                     }
-                    if (matches != null) {
-                        detectedFieldIds.add(fieldId);
-                        detectedFieldClassifications.add(new FieldClassification(matches));
+                    if (scoresByField == null) {
+                        if (sVerbose) Slog.v(TAG, "no score for autofillId=" + autofillId);
+                        continue;
                     }
-                }
+
+                    // Then create the matches for that autofill id
+                    final ArrayList<Match> matches = new ArrayList<>(scoresByField.size());
+                    for (j = 0; j < scoresByField.size(); j++) {
+                        final String fieldId = scoresByField.keyAt(j);
+                        final float score = scoresByField.valueAt(j);
+                        matches.add(new Match(fieldId, score));
+                    }
+                    detectedFieldIds.add(autofillId);
+                    detectedFieldClassifications.add(new FieldClassification(matches));
+                } // for i
             } catch (ArrayIndexOutOfBoundsException e) {
                 wtf(e, "Error accessing FC score at [%d, %d] (%s): %s", i, j, scores, e);
                 return;
@@ -1241,6 +1289,7 @@
      *
      * @return {@code true} if session is done, or {@code false} if it's pending user action.
      */
+    @GuardedBy("mLock")
     public boolean showSaveLocked() {
         if (mDestroyed) {
             Slog.w(TAG, "Call to Session#showSaveLocked() rejected - session: "
@@ -1431,7 +1480,10 @@
                     }
                 }
 
-                if (sDebug) Slog.d(TAG, "Good news, everyone! All checks passed, show save UI!");
+                if (sDebug) {
+                    Slog.d(TAG, "Good news, everyone! All checks passed, show save UI for "
+                            + id + "!");
+                }
 
                 // Use handler so logContextCommitted() is logged first
                 mHandlerCaller.getHandler().post(() -> mService.logSaveShown(id, mClientState));
@@ -1455,7 +1507,7 @@
         }
         // Nothing changed...
         if (sDebug) {
-            Slog.d(TAG, "showSaveLocked(): with no changes, comes no responsibilities."
+            Slog.d(TAG, "showSaveLocked(" + id +"): with no changes, comes no responsibilities."
                     + "allRequiredAreNotNull=" + allRequiredAreNotEmpty
                     + ", atLeastOneChanged=" + atLeastOneChanged);
         }
@@ -1507,6 +1559,7 @@
     /**
      * Returns whether the session is currently showing the save UI
      */
+    @GuardedBy("mLock")
     boolean isSavingLocked() {
         return mIsSaving;
     }
@@ -1514,12 +1567,13 @@
     /**
      * Gets the latest non-empty value for the given id in the autofill contexts.
      */
+    @GuardedBy("mLock")
     @Nullable
     private AutofillValue getValueFromContextsLocked(AutofillId id) {
         final int numContexts = mContexts.size();
         for (int i = numContexts - 1; i >= 0; i--) {
             final FillContext context = mContexts.get(i);
-            final ViewNode node = context.findViewNodeByAutofillId(id);
+            final ViewNode node = Helper.findViewNodeByAutofillId(context.getStructure(), id);
             if (node != null) {
                 final AutofillValue value = node.getAutofillValue();
                 if (sDebug) {
@@ -1536,13 +1590,14 @@
     /**
      * Gets the latest autofill options for the given id in the autofill contexts.
      */
+    @GuardedBy("mLock")
     @Nullable
     private CharSequence[] getAutofillOptionsFromContextsLocked(AutofillId id) {
         final int numContexts = mContexts.size();
 
         for (int i = numContexts - 1; i >= 0; i--) {
             final FillContext context = mContexts.get(i);
-            final ViewNode node = context.findViewNodeByAutofillId(id);
+            final ViewNode node = Helper.findViewNodeByAutofillId(context.getStructure(), id);
             if (node != null && node.getAutofillOptions() != null) {
                 return node.getAutofillOptions();
             }
@@ -1553,6 +1608,7 @@
     /**
      * Calls service when user requested save.
      */
+    @GuardedBy("mLock")
     void callSaveLocked() {
         if (mDestroyed) {
             Slog.w(TAG, "Call to Session#callSaveLocked() rejected - session: "
@@ -1643,6 +1699,7 @@
      * @param viewState The view that is entered.
      * @param flags The flag that was passed by the AutofillManager.
      */
+    @GuardedBy("mLock")
     private void requestNewFillResponseOnViewEnteredIfNecessaryLocked(@NonNull AutofillId id,
             @NonNull ViewState viewState, int flags) {
         if ((flags & FLAG_MANUAL_REQUEST) != 0) {
@@ -1670,6 +1727,7 @@
      *
      * @return {@code true} iff a new partition should be started
      */
+    @GuardedBy("mLock")
     private boolean shouldStartNewPartitionLocked(@NonNull AutofillId id) {
         if (mResponses == null) {
             return true;
@@ -1718,6 +1776,7 @@
         return true;
     }
 
+    @GuardedBy("mLock")
     void updateLocked(AutofillId id, Rect virtualBounds, AutofillValue value, int action,
             int flags) {
         if (mDestroyed) {
@@ -1827,6 +1886,7 @@
     /**
      * Checks whether a view should be ignored.
      */
+    @GuardedBy("mLock")
     private boolean isIgnoredLocked(AutofillId id) {
         // Always check the latest response only
         final FillResponse response = getLastResponseLocked(null);
@@ -1907,6 +1967,7 @@
         }
     }
 
+    @GuardedBy("mLock")
     private void updateTrackedIdsLocked() {
         // Only track the views of the last response as only those are reported back to the
         // service, see #showSaveLocked
@@ -1970,7 +2031,7 @@
         try {
             if (sVerbose) {
                 Slog.v(TAG, "updateTrackedIdsLocked(): " + trackedViews + " => " + fillableIds
-                        + " (triggering on " + saveTriggerId + ")");
+                        + " triggerId: " + saveTriggerId + " saveOnFinish:" + saveOnFinish);
             }
             mClient.setTrackedViews(id, toArray(trackedViews), saveOnAllViewsInvisible,
                     saveOnFinish, toArray(fillableIds), saveTriggerId);
@@ -1979,6 +2040,7 @@
         }
     }
 
+    @GuardedBy("mLock")
     private void replaceResponseLocked(@NonNull FillResponse oldResponse,
             @NonNull FillResponse newResponse, @Nullable Bundle newClientState) {
         // Disassociate view states with the old response
@@ -2002,6 +2064,7 @@
         removeSelf();
     }
 
+    @GuardedBy("mLock")
     private void processResponseLocked(@NonNull FillResponse newResponse,
             @Nullable Bundle newClientState, int flags) {
         // Make sure we are hiding the UI which will be shown
@@ -2039,6 +2102,7 @@
     /**
      * Sets the state of all views in the given response.
      */
+    @GuardedBy("mLock")
     private void setViewStatesLocked(FillResponse response, int state, boolean clearResponse) {
         final List<Dataset> datasets = response.getDatasets();
         if (datasets != null) {
@@ -2087,6 +2151,7 @@
     /**
      * Sets the state of all views in the given dataset and response.
      */
+    @GuardedBy("mLock")
     private void setViewStatesLocked(@Nullable FillResponse response, @NonNull Dataset dataset,
             int state, boolean clearResponse) {
         final ArrayList<AutofillId> ids = dataset.getFieldIds();
@@ -2107,6 +2172,7 @@
         }
     }
 
+    @GuardedBy("mLock")
     private ViewState createOrUpdateViewStateLocked(@NonNull AutofillId id, int state,
             @Nullable AutofillValue value) {
         ViewState viewState = mViewStates.get(id);
@@ -2168,6 +2234,7 @@
     }
 
     // TODO: this should never be null, but we got at least one occurrence, probably due to a race.
+    @GuardedBy("mLock")
     @Nullable
     private Intent createAuthFillInIntentLocked(int requestId, Bundle extras) {
         final Intent fillInIntent = new Intent();
@@ -2200,6 +2267,7 @@
         return "Session: [id=" + id + ", component=" + mComponentName + "]";
     }
 
+    @GuardedBy("mLock")
     void dumpLocked(String prefix, PrintWriter pw) {
         final String prefix2 = prefix + "  ";
         pw.print(prefix); pw.print("id: "); pw.println(id);
@@ -2256,6 +2324,7 @@
         pw.print(prefix); pw.print("mHasCallback: "); pw.println(mHasCallback);
         pw.print(prefix); pw.print("mClientState: "); pw.println(
                 Helper.bundleToString(mClientState));
+        pw.print(prefix); pw.print("mCompatMode: "); pw.println(mCompatMode);
         pw.print(prefix); pw.print("mSelectedDatasetIds: "); pw.println(mSelectedDatasetIds);
         mRemoteFillService.dump(prefix, pw);
     }
@@ -2329,6 +2398,7 @@
      *       disabled it).
      * </ul>
      */
+    @GuardedBy("mLock")
     RemoteFillService destroyLocked() {
         if (mDestroyed) {
             return null;
@@ -2344,6 +2414,7 @@
      * Cleans up this session and remove it from the service always, even if it does have a pending
      * Save UI.
      */
+    @GuardedBy("mLock")
     void forceRemoveSelfLocked() {
         if (sVerbose) Slog.v(TAG, "forceRemoveSelfLocked(): " + mPendingSaveUi);
 
@@ -2373,6 +2444,7 @@
      * Cleans up this session and remove it from the service, but but only if it does not have a
      * pending Save UI.
      */
+    @GuardedBy("mLock")
     void removeSelfLocked() {
         if (sVerbose) Slog.v(TAG, "removeSelfLocked(): " + mPendingSaveUi);
         if (mDestroyed) {
@@ -2401,6 +2473,7 @@
      * a specific {@code token} created by
      * {@link PendingUi#PendingUi(IBinder, int, IAutoFillManagerClient)}.
      */
+    @GuardedBy("mLock")
     boolean isSaveUiPendingForTokenLocked(@NonNull IBinder token) {
         return isSaveUiPendingLocked() && token.equals(mPendingSaveUi.getToken());
     }
@@ -2408,10 +2481,12 @@
     /**
      * Checks whether this session is hiding the Save UI to handle a custom description link.
      */
+    @GuardedBy("mLock")
     private boolean isSaveUiPendingLocked() {
         return mPendingSaveUi != null && mPendingSaveUi.getState() == PendingUi.STATE_PENDING;
     }
 
+    @GuardedBy("mLock")
     private int getLastResponseIndexLocked() {
         // The response ids are monotonically increasing so
         // we just find the largest id which is the last. We
diff --git a/services/autofill/java/com/android/server/autofill/ui/FillUi.java b/services/autofill/java/com/android/server/autofill/ui/FillUi.java
index 8240e4b..c504465 100644
--- a/services/autofill/java/com/android/server/autofill/ui/FillUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/FillUi.java
@@ -24,6 +24,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentSender;
+import android.content.pm.PackageManager;
 import android.graphics.Point;
 import android.graphics.Rect;
 import android.service.autofill.Dataset;
@@ -37,6 +38,7 @@
 import android.view.View;
 import android.view.View.MeasureSpec;
 import android.view.ViewGroup;
+import android.view.ViewGroup.LayoutParams;
 import android.view.WindowManager;
 import android.view.accessibility.AccessibilityManager;
 import android.view.autofill.AutofillId;
@@ -98,22 +100,28 @@
 
     private @Nullable AnnounceFilterResult mAnnounceFilterResult;
 
+    private final boolean mFullScreen;
     private int mContentWidth;
     private int mContentHeight;
 
     private boolean mDestroyed;
 
+    public static boolean isFullScreen(Context context) {
+        return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK);
+    }
+
     FillUi(@NonNull Context context, @NonNull FillResponse response,
-            @NonNull AutofillId focusedViewId, @NonNull @Nullable String filterText,
-            @NonNull OverlayControl overlayControl, @NonNull Callback callback) {
+           @NonNull AutofillId focusedViewId, @NonNull @Nullable String filterText,
+           @NonNull OverlayControl overlayControl, @NonNull Callback callback) {
         mContext = context;
         mCallback = callback;
+        mFullScreen = isFullScreen(context);
 
         final LayoutInflater inflater = LayoutInflater.from(context);
 
         final ViewGroup decor = (ViewGroup) inflater.inflate(
-                R.layout.autofill_dataset_picker, null);
-
+                mFullScreen ? R.layout.autofill_dataset_picker_fullscreen
+                        : R.layout.autofill_dataset_picker, null);
 
         final RemoteViews.OnClickHandler interceptionHandler = new RemoteViews.OnClickHandler() {
             @Override
@@ -130,31 +138,41 @@
             mListView = null;
             mAdapter = null;
 
+            // insert authentication item under autofill_dataset_container or decor
+            ViewGroup container = decor.findViewById(R.id.autofill_dataset_container);
+            if (container == null) {
+                container = decor;
+            }
             final View content;
             try {
                 content = response.getPresentation().apply(context, decor, interceptionHandler);
-                decor.addView(content);
+                container.addView(content);
             } catch (RuntimeException e) {
                 callback.onCanceled();
                 Slog.e(TAG, "Error inflating remote views", e);
                 mWindow = null;
                 return;
             }
+            decor.setFocusable(true);
+            decor.setOnClickListener(v -> mCallback.onResponsePicked(response));
 
             Point maxSize = mTempPoint;
             resolveMaxWindowSize(context, maxSize);
+            // fullScreen mode occupy the full width defined by autofill_dataset_picker_max_width
+            content.getLayoutParams().width = mFullScreen ? maxSize.x
+                    : ViewGroup.LayoutParams.WRAP_CONTENT;
+            content.getLayoutParams().height = ViewGroup.LayoutParams.WRAP_CONTENT;
             final int widthMeasureSpec = MeasureSpec.makeMeasureSpec(maxSize.x,
                     MeasureSpec.AT_MOST);
             final int heightMeasureSpec = MeasureSpec.makeMeasureSpec(maxSize.y,
                     MeasureSpec.AT_MOST);
 
             decor.measure(widthMeasureSpec, heightMeasureSpec);
-            decor.setOnClickListener(v -> mCallback.onResponsePicked(response));
             mContentWidth = content.getMeasuredWidth();
             mContentHeight = content.getMeasuredHeight();
 
             mWindow = new AnchoredWindow(decor, overlayControl);
-            mCallback.requestShowFillUi(mContentWidth, mContentHeight, mWindowPresenter);
+            requestShowFillUi();
         } else {
             final int datasetCount = response.getDatasets().size();
 
@@ -261,6 +279,15 @@
         }
     }
 
+    void requestShowFillUi() {
+        if (mFullScreen) {
+            mCallback.requestShowFillUi(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT,
+                    mWindowPresenter);
+        } else {
+            mCallback.requestShowFillUi(mContentWidth, mContentHeight, mWindowPresenter);
+        }
+    }
+
     /**
      * Creates a remoteview interceptor used to block clicks.
      */
@@ -289,7 +316,13 @@
                 mCallback.requestHideFillUi();
             } else {
                 if (updateContentSize()) {
-                    mCallback.requestShowFillUi(mContentWidth, mContentHeight, mWindowPresenter);
+                    if (mFullScreen) {
+                        LayoutParams lp = mListView.getLayoutParams();
+                        lp.width = mContentWidth;
+                        lp.height = mContentHeight;
+                        mListView.setLayoutParams(lp);
+                    }
+                    requestShowFillUi();
                 }
                 if (mAdapter.getCount() > VISIBLE_OPTIONS_MAX_COUNT) {
                     mListView.setVerticalScrollBarEnabled(true);
@@ -310,7 +343,7 @@
             // ViewState doesn't not support filtering - typically when it's for an authenticated
             // FillResponse.
             if (TextUtils.isEmpty(filterText)) {
-                mCallback.requestShowFillUi(mContentWidth, mContentHeight, mWindowPresenter);
+                requestShowFillUi();
             } else {
                 mCallback.requestHideFillUi();
             }
@@ -366,23 +399,39 @@
         final int heightMeasureSpec = MeasureSpec.makeMeasureSpec(maxSize.y,
                 MeasureSpec.AT_MOST);
         final int itemCount = mAdapter.getCount();
+        if (mFullScreen) {
+            // fullScreen mode occupy the full width defined by autofill_dataset_picker_max_width
+            changed = true;
+            mContentWidth = maxSize.x;
+        }
         for (int i = 0; i < itemCount; i++) {
             final View view = mAdapter.getItem(i).view;
             view.measure(widthMeasureSpec, heightMeasureSpec);
-            final int clampedMeasuredWidth = Math.min(view.getMeasuredWidth(), maxSize.x);
-            final int newContentWidth = Math.max(mContentWidth, clampedMeasuredWidth);
-            if (newContentWidth != mContentWidth) {
-                mContentWidth = newContentWidth;
-                changed = true;
-            }
-            // Update the width to fit only the first items up to max count
-            if (i < VISIBLE_OPTIONS_MAX_COUNT) {
-                final int clampedMeasuredHeight = Math.min(view.getMeasuredHeight(), maxSize.y);
-                final int newContentHeight = mContentHeight + clampedMeasuredHeight;
-                if (newContentHeight != mContentHeight) {
-                    mContentHeight = newContentHeight;
+            if (mFullScreen) {
+                // for fullscreen, add up all children height until hit max height.
+                final int newContentHeight = mContentHeight + view.getMeasuredHeight();
+                final int clampedNewHeight = Math.min(newContentHeight, maxSize.y);
+                if (clampedNewHeight != mContentHeight) {
+                    mContentHeight = clampedNewHeight;
+                } else if (view.getMeasuredHeight() > 0) {
+                    break;
+                }
+            } else {
+                final int clampedMeasuredWidth = Math.min(view.getMeasuredWidth(), maxSize.x);
+                final int newContentWidth = Math.max(mContentWidth, clampedMeasuredWidth);
+                if (newContentWidth != mContentWidth) {
+                    mContentWidth = newContentWidth;
                     changed = true;
                 }
+                // Update the width to fit only the first items up to max count
+                if (i < VISIBLE_OPTIONS_MAX_COUNT) {
+                    final int clampedMeasuredHeight = Math.min(view.getMeasuredHeight(), maxSize.y);
+                    final int newContentHeight = mContentHeight + clampedMeasuredHeight;
+                    if (newContentHeight != mContentHeight) {
+                        mContentHeight = newContentHeight;
+                        changed = true;
+                    }
+                }
             }
         }
         return changed;
@@ -575,6 +624,7 @@
 
     public void dump(PrintWriter pw, String prefix) {
         pw.print(prefix); pw.print("mCallback: "); pw.println(mCallback != null);
+        pw.print(prefix); pw.print("mFullScreen: "); pw.println(mFullScreen);
         pw.print(prefix); pw.print("mListView: "); pw.println(mListView);
         pw.print(prefix); pw.print("mAdapter: "); pw.println(mAdapter);
         pw.print(prefix); pw.print("mFilterText: ");
diff --git a/services/backup/OWNERS b/services/backup/OWNERS
new file mode 100644
index 0000000..1c9a43a
--- /dev/null
+++ b/services/backup/OWNERS
@@ -0,0 +1,7 @@
+artikz@google.com
+brufino@google.com
+bryanmawhinney@google.com
+ctate@google.com
+jorlow@google.com
+mkarpinski@google.com
+
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index 3b80f55..83367f3 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -1931,6 +1931,7 @@
     /**
      * Remove a package from the full-data queue.
      */
+    @GuardedBy("mQueueLock")
     private void dequeueFullBackupLocked(String packageName) {
         final int N = mFullBackupQueue.size();
         for (int i = N - 1; i >= 0; i--) {
diff --git a/services/backup/java/com/android/server/backup/TransportManager.java b/services/backup/java/com/android/server/backup/TransportManager.java
index 7e179e5..501ff29 100644
--- a/services/backup/java/com/android/server/backup/TransportManager.java
+++ b/services/backup/java/com/android/server/backup/TransportManager.java
@@ -26,6 +26,7 @@
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
+import android.os.Bundle;
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.util.ArrayMap;
@@ -57,6 +58,8 @@
     @VisibleForTesting
     public static final String SERVICE_ACTION_TRANSPORT_HOST = "android.backup.TRANSPORT_HOST";
 
+    private static final String EXTRA_TRANSPORT_REGISTRATION = "transport_registration";
+
     private final Intent mTransportServiceIntent = new Intent(SERVICE_ACTION_TRANSPORT_HOST);
     private final Context mContext;
     private final PackageManager mPackageManager;
@@ -582,8 +585,12 @@
 
         String transportString = transportComponent.flattenToShortString();
         String callerLogString = "TransportManager.registerTransport()";
-        TransportClient transportClient =
-                mTransportClientManager.getTransportClient(transportComponent, callerLogString);
+
+        Bundle extras = new Bundle();
+        extras.putBoolean(EXTRA_TRANSPORT_REGISTRATION, true);
+
+        TransportClient transportClient = mTransportClientManager.getTransportClient(
+            transportComponent, extras, callerLogString);
         final IBackupTransport transport;
         try {
             transport = transportClient.connectOrThrow(callerLogString);
diff --git a/services/backup/java/com/android/server/backup/transport/TransportClientManager.java b/services/backup/java/com/android/server/backup/transport/TransportClientManager.java
index 4041932..96e7d2f 100644
--- a/services/backup/java/com/android/server/backup/transport/TransportClientManager.java
+++ b/services/backup/java/com/android/server/backup/transport/TransportClientManager.java
@@ -22,10 +22,9 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
-
+import android.os.Bundle;
 import com.android.server.backup.TransportManager;
 import com.android.server.backup.transport.TransportUtils.Priority;
-
 import java.io.PrintWriter;
 import java.util.Map;
 import java.util.WeakHashMap;
@@ -59,6 +58,32 @@
     public TransportClient getTransportClient(ComponentName transportComponent, String caller) {
         Intent bindIntent =
                 new Intent(SERVICE_ACTION_TRANSPORT_HOST).setComponent(transportComponent);
+
+        return getTransportClient(transportComponent, caller, bindIntent);
+    }
+
+    /**
+     * Retrieves a {@link TransportClient} for the transport identified by {@param
+     * transportComponent} whose binding intent will have the {@param extras} extras.
+     *
+     * @param transportComponent The {@link ComponentName} of the transport.
+     * @param extras A {@link Bundle} of extras to pass to the binding intent.
+     * @param caller A {@link String} identifying the caller for logging/debugging purposes. Check
+     *     {@link TransportClient#connectAsync(TransportConnectionListener, String)} for more
+     *     details.
+     * @return A {@link TransportClient}.
+     */
+    public TransportClient getTransportClient(
+            ComponentName transportComponent, Bundle extras, String caller) {
+        Intent bindIntent =
+                new Intent(SERVICE_ACTION_TRANSPORT_HOST).setComponent(transportComponent);
+        bindIntent.putExtras(extras);
+
+        return getTransportClient(transportComponent, caller, bindIntent);
+    }
+
+    private TransportClient getTransportClient(
+            ComponentName transportComponent, String caller, Intent bindIntent) {
         synchronized (mTransportClientsLock) {
             TransportClient transportClient =
                     new TransportClient(
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index b4af432..9cd3621 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -16,6 +16,13 @@
 
 package com.android.server;
 
+import static android.app.AlarmManager.ELAPSED_REALTIME;
+import static android.app.AlarmManager.ELAPSED_REALTIME_WAKEUP;
+import static android.app.AlarmManager.FLAG_ALLOW_WHILE_IDLE;
+import static android.app.AlarmManager.FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED;
+import static android.app.AlarmManager.RTC;
+import static android.app.AlarmManager.RTC_WAKEUP;
+
 import android.annotation.UserIdInt;
 import android.app.Activity;
 import android.app.ActivityManager;
@@ -46,6 +53,7 @@
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Message;
+import android.os.ParcelableException;
 import android.os.PowerManager;
 import android.os.Process;
 import android.os.RemoteException;
@@ -55,12 +63,14 @@
 import android.os.UserHandle;
 import android.os.WorkSource;
 import android.provider.Settings;
+import android.system.Os;
 import android.text.TextUtils;
 import android.text.format.DateFormat;
 import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.KeyValueListParser;
 import android.util.Log;
+import android.util.NtpTrustedTime;
 import android.util.Pair;
 import android.util.Slog;
 import android.util.SparseArray;
@@ -69,10 +79,18 @@
 import android.util.TimeUtils;
 import android.util.proto.ProtoOutputStream;
 
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.DumpUtils;
+import com.android.internal.util.LocalLog;
+import com.android.server.AppStateTracker.Listener;
+
 import java.io.ByteArrayOutputStream;
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.text.SimpleDateFormat;
+import java.time.DateTimeException;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Calendar;
@@ -87,19 +105,6 @@
 import java.util.TreeSet;
 import java.util.function.Predicate;
 
-import static android.app.AlarmManager.FLAG_ALLOW_WHILE_IDLE;
-import static android.app.AlarmManager.RTC_WAKEUP;
-import static android.app.AlarmManager.RTC;
-import static android.app.AlarmManager.ELAPSED_REALTIME_WAKEUP;
-import static android.app.AlarmManager.ELAPSED_REALTIME;
-
-import com.android.internal.annotations.GuardedBy;
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.ArrayUtils;
-import com.android.internal.util.DumpUtils;
-import com.android.internal.util.LocalLog;
-import com.android.server.ForceAppStandbyTracker.Listener;
-
 /**
  * Alarm manager implementaion.
  *
@@ -157,6 +162,7 @@
     private long mNextNonWakeup;
     private long mLastWakeupSet;
     private long mLastWakeup;
+    private long mLastTrigger;
     private long mLastTickSet;
     private long mLastTickIssued; // elapsed
     private long mLastTickReceived;
@@ -249,7 +255,7 @@
     private final SparseArray<AlarmManager.AlarmClockInfo> mHandlerSparseAlarmClockArray =
             new SparseArray<>();
 
-    private final ForceAppStandbyTracker mForceAppStandbyTracker;
+    private AppStateTracker mAppStateTracker;
     private boolean mAppStandbyParole;
     private ArrayMap<Pair<String, Integer>, Long> mLastAlarmDeliveredForPackage = new ArrayMap<>();
 
@@ -707,9 +713,6 @@
         super(context);
         mConstants = new Constants(mHandler);
 
-        mForceAppStandbyTracker = ForceAppStandbyTracker.getInstance(context);
-        mForceAppStandbyTracker.addListener(mForceAppStandbyListener);
-
         publishLocalService(AlarmManagerInternal.class, new LocalService());
     }
 
@@ -1011,7 +1014,7 @@
             // Recurring alarms may have passed several alarm intervals while the
             // alarm was kept pending. Send the appropriate trigger count.
             if (alarm.repeatInterval > 0) {
-                alarm.count += (nowELAPSED - alarm.requestedWhenElapsed) / alarm.repeatInterval;
+                alarm.count += (nowELAPSED - alarm.expectedWhenElapsed) / alarm.repeatInterval;
                 // Also schedule its next recurrence
                 final long delta = alarm.count * alarm.repeatInterval;
                 final long nextElapsed = alarm.whenElapsed + delta;
@@ -1329,13 +1332,15 @@
     @Override
     public void onBootPhase(int phase) {
         if (phase == PHASE_SYSTEM_SERVICES_READY) {
-            mForceAppStandbyTracker.start();
             mConstants.start(getContext().getContentResolver());
             mAppOps = (AppOpsManager) getContext().getSystemService(Context.APP_OPS_SERVICE);
             mLocalDeviceIdleController
                     = LocalServices.getService(DeviceIdleController.LocalService.class);
             mUsageStatsManagerInternal = LocalServices.getService(UsageStatsManagerInternal.class);
             mUsageStatsManagerInternal.addAppIdleStateChangeListener(new AppStandbyTracker());
+
+            mAppStateTracker = LocalServices.getService(AppStateTracker.class);
+            mAppStateTracker.addListener(mForceAppStandbyListener);
         }
     }
 
@@ -1507,24 +1512,19 @@
      * Adjusts the alarm delivery time based on the current app standby bucket.
      * @param alarm The alarm to adjust
      * @return true if the alarm delivery time was updated.
-     * TODO: Reduce the number of calls to getAppStandbyBucket by batching the calls per
-     * {package, user} pairs
      */
     private boolean adjustDeliveryTimeBasedOnStandbyBucketLocked(Alarm alarm) {
-        if (alarm.alarmClock != null || UserHandle.isCore(alarm.creatorUid)) {
-            return false;
-        }
-        // TODO: short term fix for b/72816079, remove after a proper fix is in place
-        if ((alarm.flags & AlarmManager.FLAG_ALLOW_WHILE_IDLE) != 0) {
+        if (isExemptFromAppStandby(alarm)) {
             return false;
         }
         if (mAppStandbyParole) {
-            if (alarm.whenElapsed > alarm.requestedWhenElapsed) {
+            if (alarm.whenElapsed > alarm.expectedWhenElapsed) {
                 // We did defer this alarm earlier, restore original requirements
-                alarm.whenElapsed = alarm.requestedWhenElapsed;
-                alarm.maxWhenElapsed = alarm.requestedMaxWhenElapsed;
+                alarm.whenElapsed = alarm.expectedWhenElapsed;
+                alarm.maxWhenElapsed = alarm.expectedMaxWhenElapsed;
+                return true;
             }
-            return true;
+            return false;
         }
         final long oldWhenElapsed = alarm.whenElapsed;
         final long oldMaxWhenElapsed = alarm.maxWhenElapsed;
@@ -1538,13 +1538,13 @@
         final long lastElapsed = mLastAlarmDeliveredForPackage.getOrDefault(packageUser, 0L);
         if (lastElapsed > 0) {
             final long minElapsed = lastElapsed + getMinDelayForBucketLocked(standbyBucket);
-            if (alarm.requestedWhenElapsed < minElapsed) {
+            if (alarm.expectedWhenElapsed < minElapsed) {
                 alarm.whenElapsed = alarm.maxWhenElapsed = minElapsed;
             } else {
                 // app is now eligible to run alarms at the originally requested window.
                 // Restore original requirements in case they were changed earlier.
-                alarm.whenElapsed = alarm.requestedWhenElapsed;
-                alarm.maxWhenElapsed = alarm.requestedMaxWhenElapsed;
+                alarm.whenElapsed = alarm.expectedWhenElapsed;
+                alarm.maxWhenElapsed = alarm.expectedMaxWhenElapsed;
             }
         }
         return (oldWhenElapsed != alarm.whenElapsed || oldMaxWhenElapsed != alarm.maxWhenElapsed);
@@ -1728,8 +1728,9 @@
             // This means we will allow these alarms to go off as normal even while idle, with no
             // timing restrictions.
             } else if (workSource == null && (callingUid < Process.FIRST_APPLICATION_UID
-                    || callingUid == mSystemUiUid
-                    || mForceAppStandbyTracker.isUidPowerSaveWhitelisted(callingUid))) {
+                    || UserHandle.isSameApp(callingUid, mSystemUiUid)
+                    || ((mAppStateTracker != null)
+                        && mAppStateTracker.isUidPowerSaveWhitelisted(callingUid)))) {
                 flags |= AlarmManager.FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED;
                 flags &= ~AlarmManager.FLAG_ALLOW_WHILE_IDLE;
             }
@@ -1795,6 +1796,16 @@
         }
 
         @Override
+        public long currentNetworkTimeMillis() {
+            final NtpTrustedTime time = NtpTrustedTime.getInstance(getContext());
+            if (time.hasCache()) {
+                return time.currentTimeMillis();
+            } else {
+                throw new ParcelableException(new DateTimeException("Missing NTP fix"));
+            }
+        }
+
+        @Override
         protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
             if (!DumpUtils.checkDumpAndUsageStatsPermission(getContext(), TAG, pw)) return;
 
@@ -1812,8 +1823,10 @@
             mConstants.dump(pw);
             pw.println();
 
-            mForceAppStandbyTracker.dump(pw, "  ");
-            pw.println();
+            if (mAppStateTracker != null) {
+                mAppStateTracker.dump(pw, "  ");
+                pw.println();
+            }
 
             pw.println("  App Standby Parole: " + mAppStandbyParole);
             pw.println();
@@ -1840,27 +1853,32 @@
                 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);
             pw.print("  Next non-wakeup alarm: ");
                     TimeUtils.formatDuration(mNextNonWakeup, nowELAPSED, pw);
+                    pw.print(" = "); pw.print(mNextNonWakeup);
                     pw.print(" = "); pw.println(sdf.format(new Date(nextNonWakeupRTC)));
-            pw.print("  Next wakeup: "); TimeUtils.formatDuration(mNextWakeup, nowELAPSED, pw);
+            pw.print("  Next wakeup alarm: "); TimeUtils.formatDuration(mNextWakeup, nowELAPSED, pw);
+                    pw.print(" = "); pw.print(mNextWakeup);
                     pw.print(" = "); pw.println(sdf.format(new Date(nextWakeupRTC)));
+            pw.print("    set at "); TimeUtils.formatDuration(mLastWakeupSet, nowELAPSED, pw);
+                    pw.println();
             pw.print("  Last wakeup: "); TimeUtils.formatDuration(mLastWakeup, nowELAPSED, pw);
-            pw.print(" set at "); TimeUtils.formatDuration(mLastWakeupSet, nowELAPSED, pw);
-            pw.println();
+                    pw.print(" = "); pw.println(mLastWakeup);
+            pw.print("  Last trigger: "); TimeUtils.formatDuration(mLastTrigger, nowELAPSED, pw);
+                    pw.print(" = "); pw.println(mLastTrigger);
             pw.print("  Num time change events: "); pw.println(mNumTimeChanged);
 
             pw.println();
@@ -2161,8 +2179,10 @@
 
             mConstants.dumpProto(proto, AlarmManagerServiceProto.SETTINGS);
 
-            mForceAppStandbyTracker.dumpProto(proto,
-                    AlarmManagerServiceProto.FORCE_APP_STANDBY_TRACKER);
+            if (mAppStateTracker != null) {
+                mAppStateTracker.dumpProto(proto,
+                        AlarmManagerServiceProto.FORCE_APP_STANDBY_TRACKER);
+            }
 
             proto.write(AlarmManagerServiceProto.IS_INTERACTIVE, mInteractive);
             if (!mInteractive) {
@@ -2576,7 +2596,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);
@@ -2590,7 +2610,7 @@
                 nextNonWakeup = mNextNonWakeupDeliveryTime;
             }
         }
-        if (nextNonWakeup != 0 && mNextNonWakeup != nextNonWakeup) {
+        if (nextNonWakeup != 0) {
             mNextNonWakeup = nextNonWakeup;
             setLocked(ELAPSED_REALTIME, nextNonWakeup);
         }
@@ -2888,7 +2908,14 @@
                 alarmNanoseconds = (when % 1000) * 1000 * 1000;
             }
 
-            set(mNativeData, type, alarmSeconds, alarmNanoseconds);
+            final int result = set(mNativeData, type, alarmSeconds, alarmNanoseconds);
+            if (result != 0) {
+                final long nowElapsed = SystemClock.elapsedRealtime();
+                Slog.wtf(TAG, "Unable to set kernel alarm, now=" + nowElapsed
+                        + " type=" + type + " when=" + when
+                        + " @ (" + alarmSeconds + "," + alarmNanoseconds
+                        + "), ret = " + result + " = " + Os.strerror(result));
+            }
         } else {
             Message msg = Message.obtain();
             msg.what = ALARM_EVENT;
@@ -2942,20 +2969,21 @@
         }
         final String sourcePackage = alarm.sourcePackage;
         final int sourceUid = alarm.creatorUid;
-        return mForceAppStandbyTracker.areAlarmsRestricted(sourceUid, sourcePackage,
-                allowWhileIdle);
+        return (mAppStateTracker != null) &&
+                mAppStateTracker.areAlarmsRestricted(sourceUid, sourcePackage, allowWhileIdle);
     }
 
     private native long init();
     private native void close(long nativeData);
-    private native void set(long nativeData, int type, long seconds, long nanoseconds);
+    private native int set(long nativeData, int type, long seconds, long nanoseconds);
     private native int waitForAlarm(long nativeData);
     private native int setKernelTime(long nativeData, long millis);
     private native int setKernelTimezone(long nativeData, int minuteswest);
 
     private long getWhileIdleMinIntervalLocked(int uid) {
         final boolean dozing = mPendingIdleUntil != null;
-        final boolean ebs = mForceAppStandbyTracker.isForceAllAppsStandbyEnabled();
+        final boolean ebs = (mAppStateTracker != null)
+                && mAppStateTracker.isForceAllAppsStandbyEnabled();
         if (!dozing && !ebs) {
             return mConstants.ALLOW_WHILE_IDLE_SHORT_TIME;
         }
@@ -3000,10 +3028,11 @@
                         // Whoops, it hasn't been long enough since the last ALLOW_WHILE_IDLE
                         // alarm went off for this app.  Reschedule the alarm to be in the
                         // correct time period.
-                        alarm.whenElapsed = minTime;
+                        alarm.expectedWhenElapsed = alarm.whenElapsed = minTime;
                         if (alarm.maxWhenElapsed < minTime) {
                             alarm.maxWhenElapsed = minTime;
                         }
+                        alarm.expectedMaxWhenElapsed = alarm.maxWhenElapsed;
                         if (RECORD_DEVICE_IDLE_ALARMS) {
                             IdleDispatchEntry ent = new IdleDispatchEntry();
                             ent.uid = alarm.uid;
@@ -3053,7 +3082,7 @@
                 if (alarm.repeatInterval > 0) {
                     // this adjustment will be zero if we're late by
                     // less than one full repeat interval
-                    alarm.count += (nowELAPSED - alarm.requestedWhenElapsed) / alarm.repeatInterval;
+                    alarm.count += (nowELAPSED - alarm.expectedWhenElapsed) / alarm.repeatInterval;
 
                     // Also schedule its next recurrence
                     final long delta = alarm.count * alarm.repeatInterval;
@@ -3128,8 +3157,9 @@
         public long windowLength;
         public long whenElapsed;    // 'when' in the elapsed time base
         public long maxWhenElapsed; // also in the elapsed time base
-        public final long requestedWhenElapsed; // original expiry time requested by the app
-        public final long requestedMaxWhenElapsed;
+        // Expected alarm expiry time before app standby deferring is applied.
+        public long expectedWhenElapsed;
+        public long expectedMaxWhenElapsed;
         public long repeatInterval;
         public PriorityClass priorityClass;
 
@@ -3143,10 +3173,10 @@
                     || _type == AlarmManager.RTC_WAKEUP;
             when = _when;
             whenElapsed = _whenElapsed;
-            requestedWhenElapsed = _whenElapsed;
+            expectedWhenElapsed = _whenElapsed;
             windowLength = _windowLength;
             maxWhenElapsed = _maxWhen;
-            requestedMaxWhenElapsed = _maxWhen;
+            expectedMaxWhenElapsed = _maxWhen;
             repeatInterval = _interval;
             operation = _op;
             listener = _rec;
@@ -3205,10 +3235,14 @@
             final boolean isRtc = (type == RTC || type == RTC_WAKEUP);
             pw.print(prefix); pw.print("tag="); pw.println(statsTag);
             pw.print(prefix); pw.print("type="); pw.print(type);
-                    pw.print(" requestedWhenElapsed="); TimeUtils.formatDuration(
-                            requestedWhenElapsed, nowELAPSED, pw);
+                    pw.print(" expectedWhenElapsed="); TimeUtils.formatDuration(
+                    expectedWhenElapsed, nowELAPSED, pw);
+                    pw.print(" expectedMaxWhenElapsed="); TimeUtils.formatDuration(
+                    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)));
@@ -3344,6 +3378,11 @@
         }
     }
 
+    private boolean isExemptFromAppStandby(Alarm a) {
+        return a.alarmClock != null || UserHandle.isCore(a.creatorUid)
+                || (a.flags & FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED) != 0;
+    }
+
     private class AlarmThread extends Thread
     {
         public AlarmThread()
@@ -3358,12 +3397,14 @@
             while (true)
             {
                 int result = waitForAlarm(mNativeData);
-                mLastWakeup = SystemClock.elapsedRealtime();
-
-                triggerList.clear();
 
                 final long nowRTC = System.currentTimeMillis();
                 final long nowELAPSED = SystemClock.elapsedRealtime();
+                synchronized (mLock) {
+                    mLastWakeup = nowELAPSED;
+                }
+
+                triggerList.clear();
 
                 if ((result & TIME_CHANGED_MASK) != 0) {
                     // The kernel can give us spurious time change notifications due to
@@ -3429,6 +3470,7 @@
                             }
                         }
 
+                        mLastTrigger = nowELAPSED;
                         boolean hasWakeup = triggerAlarmsLocked(triggerList, nowELAPSED, nowRTC);
                         if (!hasWakeup && checkAllowNonWakeupDelayLocked(nowELAPSED)) {
                             // if there are no wakeup alarms and the screen is off, we can
@@ -3462,7 +3504,7 @@
                                     new ArraySet<>();
                             for (int i = 0; i < triggerList.size(); i++) {
                                 final Alarm a = triggerList.get(i);
-                                if (!UserHandle.isCore(a.creatorUid)) {
+                                if (!isExemptFromAppStandby(a)) {
                                     triggerPackages.add(Pair.create(
                                             a.sourcePackage, UserHandle.getUserId(a.creatorUid)));
                                 }
@@ -3528,10 +3570,15 @@
         public static final int REPORT_ALARMS_ACTIVE = 4;
         public static final int APP_STANDBY_BUCKET_CHANGED = 5;
         public static final int APP_STANDBY_PAROLE_CHANGED = 6;
+        public static final int REMOVE_FOR_STOPPED = 7;
 
         public AlarmHandler() {
         }
 
+        public void postRemoveForStopped(int uid) {
+            obtainMessage(REMOVE_FOR_STOPPED, uid, 0).sendToTarget();
+        }
+
         public void handleMessage(Message msg) {
             switch (msg.what) {
                 case ALARM_EVENT: {
@@ -3594,6 +3641,12 @@
                     }
                     break;
 
+                case REMOVE_FOR_STOPPED:
+                    synchronized (mLock) {
+                        removeForStoppedLocked(msg.arg1);
+                    }
+                    break;
+
                 default:
                     // nope, just ignore it
                     break;
@@ -3783,10 +3836,8 @@
         }
 
         @Override public void onUidGone(int uid, boolean disabled) {
-            synchronized (mLock) {
-                if (disabled) {
-                    removeForStoppedLocked(uid);
-                }
+            if (disabled) {
+                mHandler.postRemoveForStopped(uid);
             }
         }
 
@@ -3794,10 +3845,8 @@
         }
 
         @Override public void onUidIdle(int uid, boolean disabled) {
-            synchronized (mLock) {
-                if (disabled) {
-                    removeForStoppedLocked(uid);
-                }
+            if (disabled) {
+                mHandler.postRemoveForStopped(uid);
             }
         }
 
@@ -4049,6 +4098,7 @@
         /**
          * Deliver an alarm and set up the post-delivery handling appropriately
          */
+        @GuardedBy("mLock")
         public void deliverLocked(Alarm alarm, long nowELAPSED, boolean allowWhileIdle) {
             if (alarm.operation != null) {
                 // PendingIntent alarm
@@ -4126,7 +4176,8 @@
             if (allowWhileIdle) {
                 // Record the last time this uid handled an ALLOW_WHILE_IDLE alarm.
                 mLastAllowWhileIdleDispatch.put(alarm.creatorUid, nowELAPSED);
-                if (mForceAppStandbyTracker.isUidInForeground(alarm.creatorUid)) {
+                if ((mAppStateTracker == null)
+                        || mAppStateTracker.isUidInForeground(alarm.creatorUid)) {
                     mUseAllowWhileIdleShortTime.put(alarm.creatorUid, true);
                 } else {
                     mUseAllowWhileIdleShortTime.put(alarm.creatorUid, false);
@@ -4141,7 +4192,7 @@
                     mAllowWhileIdleDispatches.add(ent);
                 }
             }
-            if (!UserHandle.isCore(alarm.creatorUid)) {
+            if (!isExemptFromAppStandby(alarm)) {
                 final Pair<String, Integer> packageUser = Pair.create(alarm.sourcePackage,
                         UserHandle.getUserId(alarm.creatorUid));
                 mLastAlarmDeliveredForPackage.put(packageUser, nowELAPSED);
diff --git a/services/core/java/com/android/server/ForceAppStandbyTracker.java b/services/core/java/com/android/server/AppStateTracker.java
similarity index 91%
rename from services/core/java/com/android/server/ForceAppStandbyTracker.java
rename to services/core/java/com/android/server/AppStateTracker.java
index 339101f..9b29b32 100644
--- a/services/core/java/com/android/server/ForceAppStandbyTracker.java
+++ b/services/core/java/com/android/server/AppStateTracker.java
@@ -54,7 +54,6 @@
 import com.android.internal.app.IAppOpsService;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.Preconditions;
-import com.android.server.DeviceIdleController.LocalService;
 import com.android.server.ForceAppStandbyTrackerProto.ExemptedPackage;
 import com.android.server.ForceAppStandbyTrackerProto.RunAnyInBackgroundRestrictedPackages;
 
@@ -73,14 +72,14 @@
  * TODO: Make it a LocalService.
  *
  * Test:
-  atest $ANDROID_BUILD_TOP/frameworks/base/services/tests/servicestests/src/com/android/server/ForceAppStandbyTrackerTest.java
+  atest $ANDROID_BUILD_TOP/frameworks/base/services/tests/servicestests/src/com/android/server/AppStateTrackerTest.java
  */
-public class ForceAppStandbyTracker {
+public class AppStateTracker {
     private static final String TAG = "ForceAppStandbyTracker";
     private static final boolean DEBUG = true;
 
-    @GuardedBy("ForceAppStandbyTracker.class")
-    private static ForceAppStandbyTracker sInstance;
+    @GuardedBy("AppStateTracker.class")
+    private static AppStateTracker sInstance;
 
     private final Object mLock = new Object();
     private final Context mContext;
@@ -89,6 +88,7 @@
     static final int TARGET_OP = AppOpsManager.OP_RUN_ANY_IN_BACKGROUND;
 
     IActivityManager mIActivityManager;
+    ActivityManagerInternal mActivityManagerInternal;
     AppOpsManager mAppOpsManager;
     IAppOpsService mAppOpsService;
     PowerManagerInternal mPowerManagerInternal;
@@ -172,6 +172,9 @@
         int EXEMPT_CHANGED = 6;
         int FORCE_ALL_CHANGED = 7;
         int FORCE_APP_STANDBY_FEATURE_FLAG_CHANGED = 8;
+
+        int IS_UID_ACTIVE_CACHED = 9;
+        int IS_UID_ACTIVE_RAW = 10;
     }
 
     private final StatLogger mStatLogger = new StatLogger(new String[] {
@@ -184,6 +187,9 @@
             "EXEMPT_CHANGED",
             "FORCE_ALL_CHANGED",
             "FORCE_APP_STANDBY_FEATURE_FLAG_CHANGED",
+
+            "IS_UID_ACTIVE_CACHED",
+            "IS_UID_ACTIVE_RAW",
     });
 
     @VisibleForTesting
@@ -249,7 +255,7 @@
         /**
          * This is called when the OP_RUN_ANY_IN_BACKGROUND appops changed for a package.
          */
-        private void onRunAnyAppOpsChanged(ForceAppStandbyTracker sender,
+        private void onRunAnyAppOpsChanged(AppStateTracker sender,
                 int uid, @NonNull String packageName) {
             updateJobsForUidPackage(uid, packageName);
 
@@ -264,14 +270,14 @@
         /**
          * This is called when the foreground state changed for a UID.
          */
-        private void onUidForegroundStateChanged(ForceAppStandbyTracker sender, int uid) {
+        private void onUidForegroundStateChanged(AppStateTracker sender, int uid) {
             onUidForeground(uid, sender.isUidInForeground(uid));
         }
 
         /**
          * This is called when the active/idle state changed for a UID.
          */
-        private void onUidActiveStateChanged(ForceAppStandbyTracker sender, int uid) {
+        private void onUidActiveStateChanged(AppStateTracker sender, int uid) {
             updateJobsForUid(uid);
 
             if (sender.isUidActive(uid)) {
@@ -282,7 +288,7 @@
         /**
          * This is called when an app-id(s) is removed from the power save whitelist.
          */
-        private void onPowerSaveUnwhitelisted(ForceAppStandbyTracker sender) {
+        private void onPowerSaveUnwhitelisted(AppStateTracker sender) {
             updateAllJobs();
             unblockAllUnrestrictedAlarms();
         }
@@ -291,14 +297,14 @@
          * This is called when the power save whitelist changes, excluding the
          * {@link #onPowerSaveUnwhitelisted} case.
          */
-        private void onPowerSaveWhitelistedChanged(ForceAppStandbyTracker sender) {
+        private void onPowerSaveWhitelistedChanged(AppStateTracker sender) {
             updateAllJobs();
         }
 
         /**
          * This is called when the temp whitelist changes.
          */
-        private void onTempPowerSaveWhitelistChanged(ForceAppStandbyTracker sender) {
+        private void onTempPowerSaveWhitelistChanged(AppStateTracker sender) {
 
             // TODO This case happens rather frequently; consider optimizing and update jobs
             // only for affected app-ids.
@@ -311,7 +317,7 @@
         /**
          * This is called when the EXEMPT bucket is updated.
          */
-        private void onExemptChanged(ForceAppStandbyTracker sender) {
+        private void onExemptChanged(AppStateTracker sender) {
             // This doesn't happen very often, so just re-evaluate all jobs / alarms.
             updateAllJobs();
             unblockAllUnrestrictedAlarms();
@@ -320,7 +326,7 @@
         /**
          * This is called when the global "force all apps standby" flag changes.
          */
-        private void onForceAllAppsStandbyChanged(ForceAppStandbyTracker sender) {
+        private void onForceAllAppsStandbyChanged(AppStateTracker sender) {
             updateAllJobs();
 
             if (!sender.isForceAllAppsStandbyEnabled()) {
@@ -377,30 +383,15 @@
         }
     }
 
-    @VisibleForTesting
-    ForceAppStandbyTracker(Context context, Looper looper) {
+    public AppStateTracker(Context context, Looper looper) {
         mContext = context;
         mHandler = new MyHandler(looper);
     }
 
-    private ForceAppStandbyTracker(Context context) {
-        this(context, FgThread.get().getLooper());
-    }
-
-    /**
-     * Get the singleton instance.
-     */
-    public static synchronized ForceAppStandbyTracker getInstance(Context context) {
-        if (sInstance == null) {
-            sInstance = new ForceAppStandbyTracker(context);
-        }
-        return sInstance;
-    }
-
     /**
      * Call it when the system is ready.
      */
-    public void start() {
+    public void onSystemServicesReady() {
         synchronized (mLock) {
             if (mStarted) {
                 return;
@@ -408,6 +399,7 @@
             mStarted = true;
 
             mIActivityManager = Preconditions.checkNotNull(injectIActivityManager());
+            mActivityManagerInternal = Preconditions.checkNotNull(injectActivityManagerInternal());
             mAppOpsManager = Preconditions.checkNotNull(injectAppOpsManager());
             mAppOpsService = Preconditions.checkNotNull(injectIAppOpsService());
             mPowerManagerInternal = Preconditions.checkNotNull(injectPowerManagerInternal());
@@ -475,6 +467,11 @@
     }
 
     @VisibleForTesting
+    ActivityManagerInternal injectActivityManagerInternal() {
+        return LocalServices.getService(ActivityManagerInternal.class);
+    }
+
+    @VisibleForTesting
     PowerManagerInternal injectPowerManagerInternal() {
         return LocalServices.getService(PowerManagerInternal.class);
     }
@@ -497,6 +494,7 @@
     /**
      * Update {@link #mRunAnyRestrictedPackages} with the current app ops state.
      */
+    @GuardedBy("mLock")
     private void refreshForcedAppStandbyUidPackagesLocked() {
         mRunAnyRestrictedPackages.clear();
         final List<PackageOps> ops = mAppOpsManager.getPackagesForOps(
@@ -536,6 +534,7 @@
     /**
      * Update {@link #mForceAllAppsStandby} and notifies the listeners.
      */
+    @GuardedBy("mLock")
     private void toggleForceAllAppsStandbyLocked(boolean enable) {
         if (enable == mForceAllAppsStandby) {
             return;
@@ -545,6 +544,7 @@
         mHandler.notifyForceAllAppsStandbyChanged();
     }
 
+    @GuardedBy("mLock")
     private int findForcedAppStandbyUidPackageIndexLocked(int uid, @NonNull String packageName) {
         final int size = mRunAnyRestrictedPackages.size();
         if (size > 8) {
@@ -563,6 +563,7 @@
     /**
      * @return whether a uid package-name pair is in mRunAnyRestrictedPackages.
      */
+    @GuardedBy("mLock")
     boolean isRunAnyRestrictedLocked(int uid, @NonNull String packageName) {
         return findForcedAppStandbyUidPackageIndexLocked(uid, packageName) >= 0;
     }
@@ -570,6 +571,7 @@
     /**
      * Add to / remove from {@link #mRunAnyRestrictedPackages}.
      */
+    @GuardedBy("mLock")
     boolean updateForcedAppStandbyUidPackageLocked(int uid, @NonNull String packageName,
             boolean restricted) {
         final int index = findForcedAppStandbyUidPackageIndexLocked(uid, packageName);
@@ -614,48 +616,22 @@
     private final class UidObserver extends IUidObserver.Stub {
         @Override
         public void onUidStateChanged(int uid, int procState, long procStateSeq) {
-            synchronized (mLock) {
-                if (procState > ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND) {
-                    if (removeUidFromArray(mForegroundUids, uid, false)) {
-                        mHandler.notifyUidForegroundStateChanged(uid);
-                    }
-                } else {
-                    if (addUidToArray(mForegroundUids, uid)) {
-                        mHandler.notifyUidForegroundStateChanged(uid);
-                    }
-                }
-            }
-        }
-
-        @Override
-        public void onUidGone(int uid, boolean disabled) {
-            removeUid(uid, true);
+            mHandler.onUidStateChanged(uid, procState);
         }
 
         @Override
         public void onUidActive(int uid) {
-            synchronized (mLock) {
-                if (addUidToArray(mActiveUids, uid)) {
-                    mHandler.notifyUidActiveStateChanged(uid);
-                }
-            }
+            mHandler.onUidActive(uid);
+        }
+
+        @Override
+        public void onUidGone(int uid, boolean disabled) {
+            mHandler.onUidGone(uid, disabled);
         }
 
         @Override
         public void onUidIdle(int uid, boolean disabled) {
-            // Just to avoid excessive memcpy, don't remove from the array in this case.
-            removeUid(uid, false);
-        }
-
-        private void removeUid(int uid, boolean remove) {
-            synchronized (mLock) {
-                if (removeUidFromArray(mActiveUids, uid, remove)) {
-                    mHandler.notifyUidActiveStateChanged(uid);
-                }
-                if (removeUidFromArray(mForegroundUids, uid, remove)) {
-                    mHandler.notifyUidForegroundStateChanged(uid);
-                }
-            }
+            mHandler.onUidIdle(uid, disabled);
         }
 
         @Override
@@ -740,6 +716,11 @@
         private static final int MSG_FORCE_APP_STANDBY_FEATURE_FLAG_CHANGED = 9;
         private static final int MSG_EXEMPT_CHANGED = 10;
 
+        private static final int MSG_ON_UID_STATE_CHANGED = 11;
+        private static final int MSG_ON_UID_ACTIVE = 12;
+        private static final int MSG_ON_UID_GONE = 13;
+        private static final int MSG_ON_UID_IDLE = 14;
+
         public MyHandler(Looper looper) {
             super(looper);
         }
@@ -790,6 +771,22 @@
             obtainMessage(MSG_USER_REMOVED, userId, 0).sendToTarget();
         }
 
+        public void onUidStateChanged(int uid, int procState) {
+            obtainMessage(MSG_ON_UID_STATE_CHANGED, uid, procState).sendToTarget();
+        }
+
+        public void onUidActive(int uid) {
+            obtainMessage(MSG_ON_UID_ACTIVE, uid, 0).sendToTarget();
+        }
+
+        public void onUidGone(int uid, boolean disabled) {
+            obtainMessage(MSG_ON_UID_GONE, uid, disabled ? 1 : 0).sendToTarget();
+        }
+
+        public void onUidIdle(int uid, boolean disabled) {
+            obtainMessage(MSG_ON_UID_IDLE, uid, disabled ? 1 : 0).sendToTarget();
+        }
+
         @Override
         public void handleMessage(Message msg) {
             switch (msg.what) {
@@ -804,7 +801,7 @@
                     return;
                 }
             }
-            final ForceAppStandbyTracker sender = ForceAppStandbyTracker.this;
+            final AppStateTracker sender = AppStateTracker.this;
 
             long start = mStatLogger.getTime();
             switch (msg.what) {
@@ -883,6 +880,61 @@
                 case MSG_USER_REMOVED:
                     handleUserRemoved(msg.arg1);
                     return;
+
+                case MSG_ON_UID_STATE_CHANGED:
+                    handleUidStateChanged(msg.arg1, msg.arg2);
+                    return;
+                case MSG_ON_UID_ACTIVE:
+                    handleUidActive(msg.arg1);
+                    return;
+                case MSG_ON_UID_GONE:
+                    handleUidGone(msg.arg1, msg.arg1 != 0);
+                    return;
+                case MSG_ON_UID_IDLE:
+                    handleUidIdle(msg.arg1, msg.arg1 != 0);
+                    return;
+            }
+        }
+
+        public void handleUidStateChanged(int uid, int procState) {
+            synchronized (mLock) {
+                if (procState > ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND) {
+                    if (removeUidFromArray(mForegroundUids, uid, false)) {
+                        mHandler.notifyUidForegroundStateChanged(uid);
+                    }
+                } else {
+                    if (addUidToArray(mForegroundUids, uid)) {
+                        mHandler.notifyUidForegroundStateChanged(uid);
+                    }
+                }
+            }
+        }
+
+        public void handleUidActive(int uid) {
+            synchronized (mLock) {
+                if (addUidToArray(mActiveUids, uid)) {
+                    mHandler.notifyUidActiveStateChanged(uid);
+                }
+            }
+        }
+
+        public void handleUidGone(int uid, boolean disabled) {
+            removeUid(uid, true);
+        }
+
+        public void handleUidIdle(int uid, boolean disabled) {
+            // Just to avoid excessive memcpy, don't remove from the array in this case.
+            removeUid(uid, false);
+        }
+
+        private void removeUid(int uid, boolean remove) {
+            synchronized (mLock) {
+                if (removeUidFromArray(mActiveUids, uid, remove)) {
+                    mHandler.notifyUidActiveStateChanged(uid);
+                }
+                if (removeUidFromArray(mForegroundUids, uid, remove)) {
+                    mHandler.notifyUidForegroundStateChanged(uid);
+                }
             }
         }
     }
@@ -1039,11 +1091,11 @@
     }
 
     /**
-     * @return whether a UID is in active or not.
+     * @return whether a UID is in active or not *based on cached information.*
      *
      * Note this information is based on the UID proc state callback, meaning it's updated
      * asynchronously and may subtly be stale. If the fresh data is needed, use
-     * {@link ActivityManagerInternal#getUidProcessState} instead.
+     * {@link #isUidActiveSynced} instead.
      */
     public boolean isUidActive(int uid) {
         if (UserHandle.isCore(uid)) {
@@ -1055,6 +1107,23 @@
     }
 
     /**
+     * @return whether a UID is in active or not *right now.*
+     *
+     * This gives the fresh information, but may access the activity manager so is slower.
+     */
+    public boolean isUidActiveSynced(int uid) {
+        if (isUidActive(uid)) { // Use the cached one first.
+            return true;
+        }
+        final long start = mStatLogger.getTime();
+
+        final boolean ret = mActivityManagerInternal.isUidActive(uid);
+        mStatLogger.logDurationStat(Stats.IS_UID_ACTIVE_RAW, start);
+
+        return ret;
+    }
+
+    /**
      * @return whether a UID is in the foreground or not.
      *
      * Note this information is based on the UID proc state callback, meaning it's updated
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/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 3bfa31a..f633003 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -30,6 +30,7 @@
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
 import static android.net.NetworkCapabilities.TRANSPORT_VPN;
@@ -1290,11 +1291,7 @@
                         for (Network network : networks) {
                             nai = getNetworkAgentInfoForNetwork(network);
                             nc = getNetworkCapabilitiesInternal(nai);
-                            // nc is a copy of the capabilities in nai, so it's fine to mutate it
-                            // TODO : don't remove the UIDs when communicating with processes
-                            // that have the NETWORK_SETTINGS permission.
                             if (nc != null) {
-                                nc.setSingleUid(userId);
                                 result.put(network, nc);
                             }
                         }
@@ -1362,7 +1359,9 @@
         if (nai != null) {
             synchronized (nai) {
                 if (nai.networkCapabilities != null) {
-                    return new NetworkCapabilities(nai.networkCapabilities);
+                    // TODO : don't remove the UIDs when communicating with processes
+                    // that have the NETWORK_SETTINGS permission.
+                    return networkCapabilitiesWithoutUids(nai.networkCapabilities);
                 }
             }
         }
@@ -1375,6 +1374,10 @@
         return getNetworkCapabilitiesInternal(getNetworkAgentInfoForNetwork(network));
     }
 
+    private NetworkCapabilities networkCapabilitiesWithoutUids(NetworkCapabilities nc) {
+        return new NetworkCapabilities(nc).setUids(null);
+    }
+
     @Override
     public NetworkState[] getAllNetworkState() {
         // Require internal since we're handing out IMSI details
@@ -1384,6 +1387,10 @@
         for (Network network : getAllNetworks()) {
             final NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
             if (nai != null) {
+                // TODO (b/73321673) : NetworkState contains a copy of the
+                // NetworkCapabilities, which may contain UIDs of apps to which the
+                // network applies. Should the UIDs be cleared so as not to leak or
+                // interfere ?
                 result.add(nai.getNetworkState());
             }
         }
@@ -1402,7 +1409,8 @@
     public boolean isActiveNetworkMetered() {
         enforceAccessPermission();
 
-        final NetworkCapabilities caps = getNetworkCapabilities(getActiveNetwork());
+        final int uid = Binder.getCallingUid();
+        final NetworkCapabilities caps = getUnfilteredActiveNetworkState(uid).networkCapabilities;
         if (caps != null) {
             return !caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
         } else {
@@ -4541,10 +4549,12 @@
         lp.ensureDirectlyConnectedRoutes();
         // TODO: Instead of passing mDefaultRequest, provide an API to determine whether a Network
         // satisfies mDefaultRequest.
+        final NetworkCapabilities nc = new NetworkCapabilities(networkCapabilities);
         final NetworkAgentInfo nai = new NetworkAgentInfo(messenger, new AsyncChannel(),
-                new Network(reserveNetId()), new NetworkInfo(networkInfo), lp,
-                new NetworkCapabilities(networkCapabilities), currentScore,
+                new Network(reserveNetId()), new NetworkInfo(networkInfo), lp, nc, currentScore,
                 mContext, mTrackerHandler, new NetworkMisc(networkMisc), mDefaultRequest, this);
+        // Make sure the network capabilities reflect what the agent info says.
+        nai.networkCapabilities = mixInCapabilities(nai, nc);
         synchronized (this) {
             nai.networkMonitor.systemReady = mSystemReady;
         }
@@ -4773,6 +4783,11 @@
         } else {
             newNc.addCapability(NET_CAPABILITY_FOREGROUND);
         }
+        if (nai.isSuspended()) {
+            newNc.removeCapability(NET_CAPABILITY_NOT_SUSPENDED);
+        } else {
+            newNc.addCapability(NET_CAPABILITY_NOT_SUSPENDED);
+        }
 
         return newNc;
     }
@@ -4953,7 +4968,7 @@
         releasePendingNetworkRequestWithDelay(pendingIntent);
     }
 
-    private static void callCallbackForRequest(NetworkRequestInfo nri,
+    private void callCallbackForRequest(NetworkRequestInfo nri,
             NetworkAgentInfo networkAgent, int notificationType, int arg1) {
         if (nri.messenger == null) {
             return;  // Default request has no msgr
@@ -4966,16 +4981,19 @@
             putParcelable(bundle, networkAgent.network);
         }
         switch (notificationType) {
+            case ConnectivityManager.CALLBACK_AVAILABLE: {
+                putParcelable(bundle, new NetworkCapabilities(networkAgent.networkCapabilities));
+                putParcelable(bundle, new LinkProperties(networkAgent.linkProperties));
+                break;
+            }
             case ConnectivityManager.CALLBACK_LOSING: {
                 msg.arg1 = arg1;
                 break;
             }
             case ConnectivityManager.CALLBACK_CAP_CHANGED: {
+                // networkAgent can't be null as it has been accessed a few lines above.
                 final NetworkCapabilities nc =
-                        new NetworkCapabilities(networkAgent.networkCapabilities);
-                // TODO : don't remove the UIDs when communicating with processes
-                // that have the NETWORK_SETTINGS permission.
-                nc.setSingleUid(nri.mUid);
+                        networkCapabilitiesWithoutUids(networkAgent.networkCapabilities);
                 putParcelable(bundle, nc);
                 break;
             }
@@ -5508,6 +5526,10 @@
             if (networkAgent.getCurrentScore() != oldScore) {
                 rematchAllNetworksAndRequests(networkAgent, oldScore);
             }
+            updateCapabilities(networkAgent.getCurrentScore(), networkAgent,
+                    networkAgent.networkCapabilities);
+            // TODO (b/73132094) : remove this call once the few users of onSuspended and
+            // onResumed have been removed.
             notifyNetworkCallbacks(networkAgent, (state == NetworkInfo.State.SUSPENDED ?
                     ConnectivityManager.CALLBACK_SUSPENDED :
                     ConnectivityManager.CALLBACK_RESUMED));
@@ -5544,14 +5566,6 @@
         }
 
         callCallbackForRequest(nri, nai, ConnectivityManager.CALLBACK_AVAILABLE, 0);
-        // Whether a network is currently suspended is also an important
-        // element of state to be transferred (it would not otherwise be
-        // delivered by any currently available mechanism).
-        if (nai.networkInfo.getState() == NetworkInfo.State.SUSPENDED) {
-            callCallbackForRequest(nri, nai, ConnectivityManager.CALLBACK_SUSPENDED, 0);
-        }
-        callCallbackForRequest(nri, nai, ConnectivityManager.CALLBACK_CAP_CHANGED, 0);
-        callCallbackForRequest(nri, nai, ConnectivityManager.CALLBACK_IP_CHANGED, 0);
     }
 
     private void sendLegacyNetworkBroadcast(NetworkAgentInfo nai, DetailedState state, int type) {
diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/DeviceIdleController.java
index 44974ff..2b3c585 100644
--- a/services/core/java/com/android/server/DeviceIdleController.java
+++ b/services/core/java/com/android/server/DeviceIdleController.java
@@ -82,6 +82,7 @@
 import com.android.internal.os.BackgroundThread;
 import com.android.internal.util.DumpUtils;
 import com.android.internal.util.FastXmlSerializer;
+import com.android.internal.util.Preconditions;
 import com.android.internal.util.XmlUtils;
 import com.android.server.am.BatteryStatsService;
 import com.android.server.net.NetworkPolicyManagerInternal;
@@ -128,6 +129,7 @@
     private Intent mIdleIntent;
     private Intent mLightIdleIntent;
     private AnyMotionDetector mAnyMotionDetector;
+    private final AppStateTracker mAppStateTracker;
     private boolean mLightEnabled;
     private boolean mDeepEnabled;
     private boolean mForceIdle;
@@ -1371,6 +1373,8 @@
         super(context);
         mConfigFile = new AtomicFile(new File(getSystemDir(), "deviceidle.xml"));
         mHandler = new MyHandler(BackgroundThread.getHandler().getLooper());
+        mAppStateTracker = new AppStateTracker(context, FgThread.get().getLooper());
+        LocalServices.addService(AppStateTracker.class, mAppStateTracker);
     }
 
     boolean isAppOnWhitelistInternal(int appid) {
@@ -1501,6 +1505,8 @@
                         (PowerManager) getContext().getSystemService(Context.POWER_SERVICE),
                         mHandler, mSensorManager, this, angleThreshold);
 
+                mAppStateTracker.onSystemServicesReady();
+
                 mIdleIntent = new Intent(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED);
                 mIdleIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
                         | Intent.FLAG_RECEIVER_FOREGROUND);
@@ -2615,7 +2621,7 @@
     }
 
     private void passWhiteListToForceAppStandbyTrackerLocked() {
-        ForceAppStandbyTracker.getInstance(getContext()).setPowerSaveWhitelistAppIds(
+        mAppStateTracker.setPowerSaveWhitelistAppIds(
                 mPowerSaveWhitelistExceptIdleAppIdArray,
                 mTempWhitelistAppIdArray);
     }
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index 93f7f1d..7cd007b 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -120,7 +120,6 @@
 import android.service.vr.IVrStateCallbacks;
 import android.text.TextUtils;
 import android.text.style.SuggestionSpan;
-import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.AtomicFile;
 import android.util.EventLog;
@@ -183,7 +182,6 @@
 public class InputMethodManagerService extends IInputMethodManager.Stub
         implements ServiceConnection, Handler.Callback {
     static final boolean DEBUG = false;
-    static final boolean DEBUG_RESTORE = DEBUG || false;
     static final String TAG = "InputMethodManagerService";
 
     @Retention(SOURCE)
@@ -911,15 +909,6 @@
                     || Intent.ACTION_USER_REMOVED.equals(action)) {
                 updateCurrentProfileIds();
                 return;
-            } else if (Intent.ACTION_SETTING_RESTORED.equals(action)) {
-                final String name = intent.getStringExtra(Intent.EXTRA_SETTING_NAME);
-                if (Settings.Secure.ENABLED_INPUT_METHODS.equals(name)) {
-                    final String prevValue = intent.getStringExtra(
-                            Intent.EXTRA_SETTING_PREVIOUS_VALUE);
-                    final String newValue = intent.getStringExtra(
-                            Intent.EXTRA_SETTING_NEW_VALUE);
-                    restoreEnabledInputMethods(mContext, prevValue, newValue);
-                }
             } else if (Intent.ACTION_LOCALE_CHANGED.equals(action)) {
                 onActionLocaleChanged();
             } else if (ACTION_SHOW_INPUT_METHOD_PICKER.equals(action)) {
@@ -984,44 +973,6 @@
         }
     }
 
-    // Apply the results of a restore operation to the set of enabled IMEs.  Note that this
-    // does not attempt to validate on the fly with any installed device policy, so must only
-    // be run in the context of initial device setup.
-    //
-    // TODO: Move this method to InputMethodUtils with adding unit tests.
-    static void restoreEnabledInputMethods(Context context, String prevValue, String newValue) {
-        if (DEBUG_RESTORE) {
-            Slog.i(TAG, "Restoring enabled input methods:");
-            Slog.i(TAG, "prev=" + prevValue);
-            Slog.i(TAG, " new=" + newValue);
-        }
-        // 'new' is the just-restored state, 'prev' is what was in settings prior to the restore
-        ArrayMap<String, ArraySet<String>> prevMap =
-                InputMethodUtils.parseInputMethodsAndSubtypesString(prevValue);
-        ArrayMap<String, ArraySet<String>> newMap =
-                InputMethodUtils.parseInputMethodsAndSubtypesString(newValue);
-
-        // Merge the restored ime+subtype enabled states into the live state
-        for (ArrayMap.Entry<String, ArraySet<String>> entry : newMap.entrySet()) {
-            final String imeId = entry.getKey();
-            ArraySet<String> prevSubtypes = prevMap.get(imeId);
-            if (prevSubtypes == null) {
-                prevSubtypes = new ArraySet<>(2);
-                prevMap.put(imeId, prevSubtypes);
-            }
-            prevSubtypes.addAll(entry.getValue());
-        }
-
-        final String mergedImesAndSubtypesString =
-                InputMethodUtils.buildInputMethodsAndSubtypesString(prevMap);
-        if (DEBUG_RESTORE) {
-            Slog.i(TAG, "Merged IME string:");
-            Slog.i(TAG, "     " + mergedImesAndSubtypesString);
-        }
-        Settings.Secure.putString(context.getContentResolver(),
-                Settings.Secure.ENABLED_INPUT_METHODS, mergedImesAndSubtypesString);
-    }
-
     final class MyPackageMonitor extends PackageMonitor {
         /**
          * Package names that are known to contain {@link InputMethodService}.
@@ -1166,6 +1117,7 @@
             mImePackageAppeared = false;
         }
 
+        @GuardedBy("mMethodMap")
         private boolean shouldRebuildInputMethodListLocked() {
             // This method is guaranteed to be called only by getRegisteredHandler().
 
@@ -1467,6 +1419,7 @@
         setSelectedInputMethodAndSubtypeLocked(defIm, NOT_A_SUBTYPE_ID, false);
     }
 
+    @GuardedBy("mMethodMap")
     private void switchUserLocked(int newUserId) {
         if (DEBUG) Slog.d(TAG, "Switching user stage 1/3. newUserId=" + newUserId
                 + " currentUserId=" + mSettings.getCurrentUserId());
@@ -1575,7 +1528,6 @@
                 broadcastFilter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
                 broadcastFilter.addAction(Intent.ACTION_USER_ADDED);
                 broadcastFilter.addAction(Intent.ACTION_USER_REMOVED);
-                broadcastFilter.addAction(Intent.ACTION_SETTING_RESTORED);
                 broadcastFilter.addAction(Intent.ACTION_LOCALE_CHANGED);
                 broadcastFilter.addAction(ACTION_SHOW_INPUT_METHOD_PICKER);
                 mContext.registerReceiver(new ImmsBroadcastReceiver(), broadcastFilter);
@@ -1817,6 +1769,7 @@
         return flags;
     }
 
+    @GuardedBy("mMethodMap")
     @NonNull
     InputBindResult attachNewInputLocked(
             /* @InputMethodClient.StartInputReason */ final int startInputReason, boolean initial) {
@@ -1846,6 +1799,7 @@
                 mCurId, mCurSeq, mCurUserActionNotificationSequenceNumber);
     }
 
+    @GuardedBy("mMethodMap")
     @NonNull
     InputBindResult startInputLocked(
             /* @InputMethodClient.StartInputReason */ final int startInputReason,
@@ -1889,6 +1843,7 @@
                 controlFlags, startInputReason);
     }
 
+    @GuardedBy("mMethodMap")
     @NonNull
     InputBindResult startInputUncheckedLocked(@NonNull ClientState cs, IInputContext inputContext,
             /* @InputConnectionInspector.missingMethods */ final int missingMethods,
@@ -3642,6 +3597,7 @@
         return false;
     }
 
+    @GuardedBy("mMethodMap")
     void buildInputMethodListLocked(boolean resetDefaultEnabledIme) {
         if (DEBUG) {
             Slog.d(TAG, "--- re-buildInputMethodList reset = " + resetDefaultEnabledIme
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/NetworkTimeUpdateService.java b/services/core/java/com/android/server/NetworkTimeUpdateService.java
index 2c24798..b3a8fb6 100644
--- a/services/core/java/com/android/server/NetworkTimeUpdateService.java
+++ b/services/core/java/com/android/server/NetworkTimeUpdateService.java
@@ -23,7 +23,6 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.content.pm.PackageManager;
 import android.database.ContentObserver;
 import android.net.ConnectivityManager;
 import android.net.ConnectivityManager.NetworkCallback;
@@ -33,13 +32,12 @@
 import android.os.HandlerThread;
 import android.os.Looper;
 import android.os.Message;
-import android.os.SystemClock;
 import android.os.PowerManager;
+import android.os.SystemClock;
 import android.provider.Settings;
 import android.util.Log;
 import android.util.NtpTrustedTime;
 import android.util.TimeUtils;
-import android.util.TrustedTime;
 
 import com.android.internal.telephony.TelephonyIntents;
 import com.android.internal.util.DumpUtils;
@@ -75,19 +73,17 @@
     private long mNitzTimeSetTime = NOT_SET;
     private Network mDefaultNetwork = null;
 
-    private Context mContext;
-    private TrustedTime mTime;
+    private final Context mContext;
+    private final NtpTrustedTime mTime;
+    private final AlarmManager mAlarmManager;
+    private final ConnectivityManager mCM;
+    private final PendingIntent mPendingPollIntent;
+    private final PowerManager.WakeLock mWakeLock;
 
     // NTP lookup is done on this thread and handler
     private Handler mHandler;
-    private AlarmManager mAlarmManager;
-    private PendingIntent mPendingPollIntent;
     private SettingsObserver mSettingsObserver;
-    private ConnectivityManager mCM;
     private NetworkTimeUpdateCallback mNetworkTimeUpdateCallback;
-    // The last time that we successfully fetched the NTP time.
-    private long mLastNtpFetchTime = NOT_SET;
-    private final PowerManager.WakeLock mWakeLock;
 
     // Normal polling frequency
     private final long mPollingIntervalMs;
@@ -105,8 +101,9 @@
     public NetworkTimeUpdateService(Context context) {
         mContext = context;
         mTime = NtpTrustedTime.getInstance(context);
-        mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
-        mCM = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
+        mAlarmManager = mContext.getSystemService(AlarmManager.class);
+        mCM = mContext.getSystemService(ConnectivityManager.class);
+
         Intent pollIntent = new Intent(ACTION_POLL, null);
         mPendingPollIntent = PendingIntent.getBroadcast(mContext, POLL_REQUEST, pollIntent, 0);
 
@@ -119,7 +116,7 @@
         mTimeErrorThresholdMs = mContext.getResources().getInteger(
                 com.android.internal.R.integer.config_ntpThreshold);
 
-        mWakeLock = ((PowerManager) context.getSystemService(Context.POWER_SERVICE)).newWakeLock(
+        mWakeLock = context.getSystemService(PowerManager.class).newWakeLock(
                 PowerManager.PARTIAL_WAKE_LOCK, TAG);
     }
 
@@ -157,7 +154,7 @@
     private void onPollNetworkTime(int event) {
         // If Automatic time is not set, don't bother. Similarly, if we don't
         // have any default network, don't bother.
-        if (!isAutomaticTimeRequested() || mDefaultNetwork == null) return;
+        if (mDefaultNetwork == null) return;
         mWakeLock.acquire();
         try {
             onPollNetworkTimeUnderWakeLock(event);
@@ -167,61 +164,60 @@
     }
 
     private void onPollNetworkTimeUnderWakeLock(int event) {
-        final long refTime = SystemClock.elapsedRealtime();
-        // If NITZ time was received less than mPollingIntervalMs time ago,
-        // no need to sync to NTP.
-        if (mNitzTimeSetTime != NOT_SET && refTime - mNitzTimeSetTime < mPollingIntervalMs) {
-            resetAlarm(mPollingIntervalMs);
-            return;
+        // Force an NTP fix when outdated
+        if (mTime.getCacheAge() >= mPollingIntervalMs) {
+            if (DBG) Log.d(TAG, "Stale NTP fix; forcing refresh");
+            mTime.forceRefresh();
         }
-        final long currentTime = System.currentTimeMillis();
-        if (DBG) Log.d(TAG, "System time = " + currentTime);
-        // Get the NTP time
-        if (mLastNtpFetchTime == NOT_SET || refTime >= mLastNtpFetchTime + mPollingIntervalMs
-                || event == EVENT_AUTO_TIME_CHANGED) {
-            if (DBG) Log.d(TAG, "Before Ntp fetch");
 
-            // force refresh NTP cache when outdated
-            if (mTime.getCacheAge() >= mPollingIntervalMs) {
-                mTime.forceRefresh();
+        if (mTime.getCacheAge() < mPollingIntervalMs) {
+            // Obtained fresh fix; schedule next normal update
+            resetAlarm(mPollingIntervalMs);
+            if (isAutomaticTimeRequested()) {
+                updateSystemClock(event);
             }
 
-            // only update when NTP time is fresh
-            if (mTime.getCacheAge() < mPollingIntervalMs) {
-                final long ntp = mTime.currentTimeMillis();
-                mTryAgainCounter = 0;
-                // If the clock is more than N seconds off or this is the first time it's been
-                // fetched since boot, set the current time.
-                if (Math.abs(ntp - currentTime) > mTimeErrorThresholdMs
-                        || mLastNtpFetchTime == NOT_SET) {
-                    // Set the system time
-                    if (DBG && mLastNtpFetchTime == NOT_SET
-                            && Math.abs(ntp - currentTime) <= mTimeErrorThresholdMs) {
-                        Log.d(TAG, "For initial setup, rtc = " + currentTime);
-                    }
-                    if (DBG) Log.d(TAG, "Ntp time to be set = " + ntp);
-                    // Make sure we don't overflow, since it's going to be converted to an int
-                    if (ntp / 1000 < Integer.MAX_VALUE) {
-                        SystemClock.setCurrentTimeMillis(ntp);
-                    }
-                } else {
-                    if (DBG) Log.d(TAG, "Ntp time is close enough = " + ntp);
-                }
-                mLastNtpFetchTime = SystemClock.elapsedRealtime();
+        } else {
+            // No fresh fix; schedule retry
+            mTryAgainCounter++;
+            if (mTryAgainTimesMax < 0 || mTryAgainCounter <= mTryAgainTimesMax) {
+                resetAlarm(mPollingIntervalShorterMs);
             } else {
-                // Try again shortly
-                mTryAgainCounter++;
-                if (mTryAgainTimesMax < 0 || mTryAgainCounter <= mTryAgainTimesMax) {
-                    resetAlarm(mPollingIntervalShorterMs);
-                } else {
-                    // Try much later
-                    mTryAgainCounter = 0;
-                    resetAlarm(mPollingIntervalMs);
-                }
+                // Try much later
+                mTryAgainCounter = 0;
+                resetAlarm(mPollingIntervalMs);
+            }
+        }
+    }
+
+    private long getNitzAge() {
+        if (mNitzTimeSetTime == NOT_SET) {
+            return Long.MAX_VALUE;
+        } else {
+            return SystemClock.elapsedRealtime() - mNitzTimeSetTime;
+        }
+    }
+
+    /**
+     * Consider updating system clock based on current NTP fix, if requested by
+     * user, significant enough delta, and we don't have a recent NITZ.
+     */
+    private void updateSystemClock(int event) {
+        final boolean forceUpdate = (event == EVENT_AUTO_TIME_CHANGED);
+        if (!forceUpdate) {
+            if (getNitzAge() < mPollingIntervalMs) {
+                if (DBG) Log.d(TAG, "Ignoring NTP update due to recent NITZ");
+                return;
+            }
+
+            final long skew = Math.abs(mTime.currentTimeMillis() - System.currentTimeMillis());
+            if (skew < mTimeErrorThresholdMs) {
+                if (DBG) Log.d(TAG, "Ignoring NTP update due to low skew");
                 return;
             }
         }
-        resetAlarm(mPollingIntervalMs);
+
+        SystemClock.setCurrentTimeMillis(mTime.currentTimeMillis());
     }
 
     /**
@@ -326,8 +322,8 @@
         pw.print("TimeErrorThresholdMs: ");
         TimeUtils.formatDuration(mTimeErrorThresholdMs, pw);
         pw.println("\nTryAgainCounter: " + mTryAgainCounter);
-        pw.print("LastNtpFetchTime: ");
-        TimeUtils.formatDuration(mLastNtpFetchTime, pw);
+        pw.println("NTP cache age: " + mTime.getCacheAge());
+        pw.println("NTP cache certainty: " + mTime.getCacheCertainty());
         pw.println();
     }
 }
diff --git a/services/core/java/com/android/server/ServiceWatcher.java b/services/core/java/com/android/server/ServiceWatcher.java
index f4238f2..42c836e 100644
--- a/services/core/java/com/android/server/ServiceWatcher.java
+++ b/services/core/java/com/android/server/ServiceWatcher.java
@@ -199,6 +199,7 @@
      *            bound.
      * @returns {@code true} if a valid package was found to bind to.
      */
+    @GuardedBy("mLock")
     private boolean bindBestPackageLocked(String justCheckThisPackage, boolean forceRebind) {
         Intent intent = new Intent(mAction);
         if (justCheckThisPackage != null) {
@@ -273,6 +274,7 @@
         return true;
     }
 
+    @GuardedBy("mLock")
     private void unbindLocked() {
         ComponentName component;
         component = mBoundComponent;
@@ -287,6 +289,7 @@
         }
     }
 
+    @GuardedBy("mLock")
     private void bindToPackageLocked(ComponentName component, int version, int userId) {
         Intent intent = new Intent(mAction);
         intent.setComponent(component);
diff --git a/services/core/java/com/android/server/StatLogger.java b/services/core/java/com/android/server/StatLogger.java
index f211731..0e6f5e2 100644
--- a/services/core/java/com/android/server/StatLogger.java
+++ b/services/core/java/com/android/server/StatLogger.java
@@ -17,6 +17,7 @@
 package com.android.server;
 
 import android.os.SystemClock;
+import android.util.Slog;
 import android.util.proto.ProtoOutputStream;
 
 import com.android.internal.annotations.GuardedBy;
@@ -33,6 +34,8 @@
  * @hide
  */
 public class StatLogger {
+    private static final String TAG = "StatLogger";
+
     private final Object mLock = new Object();
 
     private final int SIZE;
@@ -66,8 +69,12 @@
      */
     public void logDurationStat(int eventId, long start) {
         synchronized (mLock) {
-            mCountStats[eventId]++;
-            mDurationStats[eventId] += (getTime() - start);
+            if (eventId >= 0 && eventId < SIZE) {
+                mCountStats[eventId]++;
+                mDurationStats[eventId] += (getTime() - start);
+            } else {
+                Slog.wtf(TAG, "Invalid event ID: " + eventId);
+            }
         }
     }
 
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index 84b93e3..7c109d5 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -16,6 +16,15 @@
 
 package com.android.server;
 
+import static android.os.storage.OnObbStateChangeListener.ERROR_ALREADY_MOUNTED;
+import static android.os.storage.OnObbStateChangeListener.ERROR_COULD_NOT_MOUNT;
+import static android.os.storage.OnObbStateChangeListener.ERROR_COULD_NOT_UNMOUNT;
+import static android.os.storage.OnObbStateChangeListener.ERROR_INTERNAL;
+import static android.os.storage.OnObbStateChangeListener.ERROR_NOT_MOUNTED;
+import static android.os.storage.OnObbStateChangeListener.ERROR_PERMISSION_DENIED;
+import static android.os.storage.OnObbStateChangeListener.MOUNTED;
+import static android.os.storage.OnObbStateChangeListener.UNMOUNTED;
+
 import static com.android.internal.util.XmlUtils.readBooleanAttribute;
 import static com.android.internal.util.XmlUtils.readIntAttribute;
 import static com.android.internal.util.XmlUtils.readLongAttribute;
@@ -60,7 +69,6 @@
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.IBinder;
-import android.os.IProgressListener;
 import android.os.IStoraged;
 import android.os.IVold;
 import android.os.IVoldListener;
@@ -87,7 +95,6 @@
 import android.os.storage.OnObbStateChangeListener;
 import android.os.storage.StorageManager;
 import android.os.storage.StorageManagerInternal;
-import android.os.storage.StorageResultCode;
 import android.os.storage.StorageVolume;
 import android.os.storage.VolumeInfo;
 import android.os.storage.VolumeRecord;
@@ -137,8 +144,7 @@
 import java.io.PrintWriter;
 import java.math.BigInteger;
 import java.nio.charset.StandardCharsets;
-import java.security.NoSuchAlgorithmException;
-import java.security.spec.InvalidKeySpecException;
+import java.security.GeneralSecurityException;
 import java.security.spec.KeySpec;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -809,6 +815,7 @@
         }
     }
 
+    @GuardedBy("mLock")
     private void addInternalVolumeLocked() {
         // Create a stub volume that represents internal storage
         final VolumeInfo internal = new VolumeInfo(VolumeInfo.ID_PRIVATE_INTERNAL,
@@ -1109,6 +1116,7 @@
         }
     };
 
+    @GuardedBy("mLock")
     private void onDiskScannedLocked(DiskInfo disk) {
         int volumeCount = 0;
         for (int i = 0; i < mVolumes.size(); i++) {
@@ -1134,6 +1142,7 @@
         mCallbacks.notifyDiskScanned(disk, volumeCount);
     }
 
+    @GuardedBy("mLock")
     private void onVolumeCreatedLocked(VolumeInfo vol) {
         if (mPms.isOnlyCoreApps()) {
             Slog.d(TAG, "System booted in core-only mode; ignoring volume " + vol.getId());
@@ -1209,6 +1218,7 @@
         return true;
     }
 
+    @GuardedBy("mLock")
     private void onVolumeStateChangedLocked(VolumeInfo vol, int oldState, int newState) {
         // Remember that we saw this volume so we're ready to accept user
         // metadata, or so we can annoy them when a private volume is ejected
@@ -1299,6 +1309,7 @@
         }
     }
 
+    @GuardedBy("mLock")
     private void onMoveStatusLocked(int status) {
         if (mMoveCallback == null) {
             Slog.w(TAG, "Odd, status but no move requested");
@@ -1515,6 +1526,7 @@
         }
     }
 
+    @GuardedBy("mLock")
     private void readSettingsLocked() {
         mRecords.clear();
         mPrimaryStorageUuid = getDefaultPrimaryStorageUuid();
@@ -1559,6 +1571,7 @@
         }
     }
 
+    @GuardedBy("mLock")
     private void writeSettingsLocked() {
         FileOutputStream fos = null;
         try {
@@ -3025,8 +3038,8 @@
                         // If this is the only one pending we might
                         // have to bind to the service again.
                         if (!connectToService()) {
-                            Slog.e(TAG, "Failed to bind to media container service");
-                            action.handleError();
+                            action.notifyObbStateChange(new ObbException(ERROR_INTERNAL,
+                                    "Failed to bind to media container service"));
                             return;
                         }
                     }
@@ -3042,10 +3055,10 @@
                     }
                     if (mContainerService == null) {
                         // Something seriously wrong. Bail out
-                        Slog.e(TAG, "Cannot bind to media container service");
                         for (ObbAction action : mActions) {
                             // Indicate service bind error
-                            action.handleError();
+                            action.notifyObbStateChange(new ObbException(ERROR_INTERNAL,
+                                    "Failed to bind to media container service"));
                         }
                         mActions.clear();
                     } else if (mActions.size() > 0) {
@@ -3067,10 +3080,10 @@
                             disconnectService();
                         }
                         if (!connectToService()) {
-                            Slog.e(TAG, "Failed to bind to media container service");
                             for (ObbAction action : mActions) {
                                 // Indicate service bind error
-                                action.handleError();
+                                action.notifyObbStateChange(new ObbException(ERROR_INTERNAL,
+                                        "Failed to bind to media container service"));
                             }
                             mActions.clear();
                         }
@@ -3160,6 +3173,20 @@
         }
     }
 
+    private static class ObbException extends Exception {
+        public final int status;
+
+        public ObbException(int status, String message) {
+            super(message);
+            this.status = status;
+        }
+
+        public ObbException(int status, Throwable cause) {
+            super(cause.getMessage(), cause);
+            this.status = status;
+        }
+    }
+
     abstract class ObbAction {
         private static final int MAX_RETRIES = 3;
         private int mRetries;
@@ -3176,46 +3203,44 @@
                     Slog.i(TAG, "Starting to execute action: " + toString());
                 mRetries++;
                 if (mRetries > MAX_RETRIES) {
-                    Slog.w(TAG, "Failed to invoke remote methods on default container service. Giving up");
                     mObbActionHandler.sendEmptyMessage(OBB_MCS_UNBIND);
-                    handleError();
+                    notifyObbStateChange(new ObbException(ERROR_INTERNAL,
+                            "Failed to bind to media container service"));
                 } else {
                     handleExecute();
                     if (DEBUG_OBB)
                         Slog.i(TAG, "Posting install MCS_UNBIND");
                     mObbActionHandler.sendEmptyMessage(OBB_MCS_UNBIND);
                 }
-            } catch (RemoteException e) {
-                if (DEBUG_OBB)
-                    Slog.i(TAG, "Posting install MCS_RECONNECT");
-                mObbActionHandler.sendEmptyMessage(OBB_MCS_RECONNECT);
-            } catch (Exception e) {
-                if (DEBUG_OBB)
-                    Slog.d(TAG, "Error handling OBB action", e);
-                handleError();
+            } catch (ObbException e) {
+                notifyObbStateChange(e);
                 mObbActionHandler.sendEmptyMessage(OBB_MCS_UNBIND);
             }
         }
 
-        abstract void handleExecute() throws RemoteException, IOException;
-        abstract void handleError();
+        abstract void handleExecute() throws ObbException;
 
-        protected ObbInfo getObbInfo() throws IOException {
-            ObbInfo obbInfo;
+        protected ObbInfo getObbInfo() throws ObbException {
+            final ObbInfo obbInfo;
             try {
                 obbInfo = mContainerService.getObbInfo(mObbState.canonicalPath);
-            } catch (RemoteException e) {
-                Slog.d(TAG, "Couldn't call DefaultContainerService to fetch OBB info for "
-                        + mObbState.canonicalPath);
-                obbInfo = null;
+            } catch (Exception e) {
+                throw new ObbException(ERROR_PERMISSION_DENIED, e);
             }
-            if (obbInfo == null) {
-                throw new IOException("Couldn't read OBB file: " + mObbState.canonicalPath);
+            if (obbInfo != null) {
+                return obbInfo;
+            } else {
+                throw new ObbException(ERROR_INTERNAL,
+                        "Missing OBB info for: " + mObbState.canonicalPath);
             }
-            return obbInfo;
         }
 
-        protected void sendNewStatusOrIgnore(int status) {
+        protected void notifyObbStateChange(ObbException e) {
+            Slog.w(TAG, e);
+            notifyObbStateChange(e.status);
+        }
+
+        protected void notifyObbStateChange(int status) {
             if (mObbState == null || mObbState.token == null) {
                 return;
             }
@@ -3239,16 +3264,14 @@
         }
 
         @Override
-        public void handleExecute() throws IOException, RemoteException {
+        public void handleExecute() throws ObbException {
             warnOnNotMounted();
 
             final ObbInfo obbInfo = getObbInfo();
 
             if (!isUidOwnerOfPackageOrSystem(obbInfo.packageName, mCallingUid)) {
-                Slog.w(TAG, "Denied attempt to mount OBB " + obbInfo.filename
-                        + " which is owned by " + obbInfo.packageName);
-                sendNewStatusOrIgnore(OnObbStateChangeListener.ERROR_PERMISSION_DENIED);
-                return;
+                throw new ObbException(ERROR_PERMISSION_DENIED, "Denied attempt to mount OBB "
+                        + obbInfo.filename + " which is owned by " + obbInfo.packageName);
             }
 
             final boolean isMounted;
@@ -3256,9 +3279,8 @@
                 isMounted = mObbPathToStateMap.containsKey(mObbState.rawPath);
             }
             if (isMounted) {
-                Slog.w(TAG, "Attempt to mount OBB which is already mounted: " + obbInfo.filename);
-                sendNewStatusOrIgnore(OnObbStateChangeListener.ERROR_ALREADY_MOUNTED);
-                return;
+                throw new ObbException(ERROR_ALREADY_MOUNTED,
+                        "Attempt to mount OBB which is already mounted: " + obbInfo.filename);
             }
 
             final String hashedKey;
@@ -3276,28 +3298,16 @@
                     BigInteger bi = new BigInteger(key.getEncoded());
                     hashedKey = bi.toString(16);
                     binderKey = hashedKey;
-                } catch (NoSuchAlgorithmException e) {
-                    Slog.e(TAG, "Could not load PBKDF2 algorithm", e);
-                    sendNewStatusOrIgnore(OnObbStateChangeListener.ERROR_INTERNAL);
-                    return;
-                } catch (InvalidKeySpecException e) {
-                    Slog.e(TAG, "Invalid key spec when loading PBKDF2 algorithm", e);
-                    sendNewStatusOrIgnore(OnObbStateChangeListener.ERROR_INTERNAL);
-                    return;
+                } catch (GeneralSecurityException e) {
+                    throw new ObbException(ERROR_INTERNAL, e);
                 }
             }
 
-            int rc = StorageResultCode.OperationSucceeded;
             try {
                 mObbState.volId = mVold.createObb(mObbState.canonicalPath, binderKey,
                         mObbState.ownerGid);
                 mVold.mount(mObbState.volId, 0, -1);
-            } catch (Exception e) {
-                Slog.w(TAG, e);
-                rc = StorageResultCode.OperationFailedInternalError;
-            }
 
-            if (rc == StorageResultCode.OperationSucceeded) {
                 if (DEBUG_OBB)
                     Slog.d(TAG, "Successfully mounted OBB " + mObbState.canonicalPath);
 
@@ -3305,20 +3315,13 @@
                     addObbStateLocked(mObbState);
                 }
 
-                sendNewStatusOrIgnore(OnObbStateChangeListener.MOUNTED);
-            } else {
-                Slog.e(TAG, "Couldn't mount OBB file: " + rc);
-
-                sendNewStatusOrIgnore(OnObbStateChangeListener.ERROR_COULD_NOT_MOUNT);
+                notifyObbStateChange(MOUNTED);
+            } catch (Exception e) {
+                throw new ObbException(ERROR_COULD_NOT_MOUNT, e);
             }
         }
 
         @Override
-        public void handleError() {
-            sendNewStatusOrIgnore(OnObbStateChangeListener.ERROR_INTERNAL);
-        }
-
-        @Override
         public String toString() {
             StringBuilder sb = new StringBuilder();
             sb.append("MountObbAction{");
@@ -3337,7 +3340,7 @@
         }
 
         @Override
-        public void handleExecute() throws IOException {
+        public void handleExecute() throws ObbException {
             warnOnNotMounted();
 
             final ObbState existingState;
@@ -3346,45 +3349,32 @@
             }
 
             if (existingState == null) {
-                sendNewStatusOrIgnore(OnObbStateChangeListener.ERROR_NOT_MOUNTED);
-                return;
+                throw new ObbException(ERROR_NOT_MOUNTED, "Missing existingState");
             }
 
             if (existingState.ownerGid != mObbState.ownerGid) {
-                Slog.w(TAG, "Permission denied attempting to unmount OBB " + existingState.rawPath
-                        + " (owned by GID " + existingState.ownerGid + ")");
-                sendNewStatusOrIgnore(OnObbStateChangeListener.ERROR_PERMISSION_DENIED);
+                notifyObbStateChange(new ObbException(ERROR_PERMISSION_DENIED,
+                        "Permission denied to unmount OBB " + existingState.rawPath
+                                + " (owned by GID " + existingState.ownerGid + ")"));
                 return;
             }
 
-            int rc = StorageResultCode.OperationSucceeded;
             try {
                 mVold.unmount(mObbState.volId);
                 mVold.destroyObb(mObbState.volId);
                 mObbState.volId = null;
-            } catch (Exception e) {
-                Slog.w(TAG, e);
-                rc = StorageResultCode.OperationFailedInternalError;
-            }
 
-            if (rc == StorageResultCode.OperationSucceeded) {
                 synchronized (mObbMounts) {
                     removeObbStateLocked(existingState);
                 }
 
-                sendNewStatusOrIgnore(OnObbStateChangeListener.UNMOUNTED);
-            } else {
-                Slog.w(TAG, "Could not unmount OBB: " + existingState);
-                sendNewStatusOrIgnore(OnObbStateChangeListener.ERROR_COULD_NOT_UNMOUNT);
+                notifyObbStateChange(UNMOUNTED);
+            } catch (Exception e) {
+                throw new ObbException(ERROR_COULD_NOT_UNMOUNT, e);
             }
         }
 
         @Override
-        public void handleError() {
-            sendNewStatusOrIgnore(OnObbStateChangeListener.ERROR_INTERNAL);
-        }
-
-        @Override
         public String toString() {
             StringBuilder sb = new StringBuilder();
             sb.append("UnmountObbAction{");
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index 6747be3..5e5eacb 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -64,6 +64,7 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
+import java.util.NoSuchElementException;
 
 /**
  * Since phone process can be restarted, this class provides a centralized place
@@ -90,6 +91,8 @@
 
         IBinder binder;
 
+        TelephonyRegistryDeathRecipient deathRecipient;
+
         IPhoneStateListener callback;
         IOnSubscriptionsChangedListener onSubscriptionsChangedListenerCallback;
 
@@ -251,6 +254,21 @@
         }
     };
 
+    private class TelephonyRegistryDeathRecipient implements IBinder.DeathRecipient {
+
+        private final IBinder binder;
+
+        TelephonyRegistryDeathRecipient(IBinder binder) {
+            this.binder = binder;
+        }
+
+        @Override
+        public void binderDied() {
+            if (DBG) log("binderDied " + binder);
+            remove(binder);
+        }
+    }
+
     private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
@@ -378,23 +396,14 @@
             }
         }
 
-        Record r;
 
         synchronized (mRecords) {
             // register
-            find_and_add: {
-                IBinder b = callback.asBinder();
-                final int N = mRecords.size();
-                for (int i = 0; i < N; i++) {
-                    r = mRecords.get(i);
-                    if (b == r.binder) {
-                        break find_and_add;
-                    }
-                }
-                r = new Record();
-                r.binder = b;
-                mRecords.add(r);
-                if (DBG) log("listen oscl: add new record");
+            IBinder b = callback.asBinder();
+            Record r = add(b);
+
+            if (r == null) {
+                return;
             }
 
             r.onSubscriptionsChangedListenerCallback = callback;
@@ -496,20 +505,11 @@
 
             synchronized (mRecords) {
                 // register
-                Record r;
-                find_and_add: {
-                    IBinder b = callback.asBinder();
-                    final int N = mRecords.size();
-                    for (int i = 0; i < N; i++) {
-                        r = mRecords.get(i);
-                        if (b == r.binder) {
-                            break find_and_add;
-                        }
-                    }
-                    r = new Record();
-                    r.binder = b;
-                    mRecords.add(r);
-                    if (DBG) log("listen: add new record");
+                IBinder b = callback.asBinder();
+                Record r = add(b);
+
+                if (r == null) {
+                    return;
                 }
 
                 r.callback = callback;
@@ -697,16 +697,57 @@
         return record.canReadPhoneState ? mCallIncomingNumber[phoneId] : "";
     }
 
+    private Record add(IBinder binder) {
+        Record r;
+
+        synchronized (mRecords) {
+            final int N = mRecords.size();
+            for (int i = 0; i < N; i++) {
+                r = mRecords.get(i);
+                if (binder == r.binder) {
+                    // Already existed.
+                    return r;
+                }
+            }
+            r = new Record();
+            r.binder = binder;
+            r.deathRecipient = new TelephonyRegistryDeathRecipient(binder);
+
+            try {
+                binder.linkToDeath(r.deathRecipient, 0);
+            } catch (RemoteException e) {
+                if (VDBG) log("LinkToDeath remote exception sending to r=" + r + " e=" + e);
+                // Binder already died. Return null.
+                return null;
+            }
+
+            mRecords.add(r);
+            if (DBG) log("add new record");
+        }
+
+        return r;
+    }
+
     private void remove(IBinder binder) {
         synchronized (mRecords) {
             final int recordCount = mRecords.size();
             for (int i = 0; i < recordCount; i++) {
-                if (mRecords.get(i).binder == binder) {
+                Record r = mRecords.get(i);
+                if (r.binder == binder) {
                     if (DBG) {
-                        Record r = mRecords.get(i);
-                        log("remove: binder=" + binder + "r.callingPackage" + r.callingPackage
-                                + "r.callback" + r.callback);
+                        log("remove: binder=" + binder + " r.callingPackage " + r.callingPackage
+                                + " r.callback " + r.callback);
                     }
+
+                    if (r.deathRecipient != null) {
+                        try {
+                            binder.unlinkToDeath(r.deathRecipient, 0);
+                        } catch (NoSuchElementException e) {
+                            if (VDBG) log("UnlinkToDeath NoSuchElementException sending to r="
+                                    + r + " e=" + e);
+                        }
+                    }
+
                     mRecords.remove(i);
                     return;
                 }
diff --git a/services/core/java/com/android/server/VibratorService.java b/services/core/java/com/android/server/VibratorService.java
index 48b5a58..7fe5d7c 100644
--- a/services/core/java/com/android/server/VibratorService.java
+++ b/services/core/java/com/android/server/VibratorService.java
@@ -25,7 +25,7 @@
 import android.content.res.Resources;
 import android.database.ContentObserver;
 import android.hardware.input.InputManager;
-import android.hardware.vibrator.V1_0.Constants.EffectStrength;
+import android.hardware.vibrator.V1_0.EffectStrength;
 import android.icu.text.DateFormat;
 import android.media.AudioManager;
 import android.os.PowerManager.ServiceType;
@@ -55,6 +55,7 @@
 import android.view.InputDevice;
 import android.media.AudioAttributes;
 
+import com.android.internal.annotations.GuardedBy;
 import com.android.internal.app.IAppOpsService;
 import com.android.internal.app.IBatteryStats;
 import com.android.internal.util.DumpUtils;
@@ -111,6 +112,7 @@
     private boolean mVibrateInputDevicesSetting; // guarded by mInputDeviceVibrators
     private boolean mInputDeviceListenerRegistered; // guarded by mInputDeviceVibrators
 
+    @GuardedBy("mLock")
     private Vibration mCurrentVibration;
     private int mCurVibUid = -1;
     private boolean mLowPowerMode;
@@ -435,45 +437,45 @@
 
         // If our current vibration is longer than the new vibration and is the same amplitude,
         // then just let the current one finish.
-        if (effect instanceof VibrationEffect.OneShot
-                && mCurrentVibration != null
-                && mCurrentVibration.effect instanceof VibrationEffect.OneShot) {
-            VibrationEffect.OneShot newOneShot = (VibrationEffect.OneShot) effect;
-            VibrationEffect.OneShot currentOneShot =
-                    (VibrationEffect.OneShot) mCurrentVibration.effect;
-            if (mCurrentVibration.hasTimeoutLongerThan(newOneShot.getDuration())
-                    && newOneShot.getAmplitude() == currentOneShot.getAmplitude()) {
+        synchronized (mLock) {
+            if (effect instanceof VibrationEffect.OneShot
+                    && mCurrentVibration != null
+                    && mCurrentVibration.effect instanceof VibrationEffect.OneShot) {
+                VibrationEffect.OneShot newOneShot = (VibrationEffect.OneShot) effect;
+                VibrationEffect.OneShot currentOneShot =
+                        (VibrationEffect.OneShot) mCurrentVibration.effect;
+                if (mCurrentVibration.hasTimeoutLongerThan(newOneShot.getDuration())
+                        && newOneShot.getAmplitude() == currentOneShot.getAmplitude()) {
+                    if (DEBUG) {
+                        Slog.d(TAG, "Ignoring incoming vibration in favor of current vibration");
+                    }
+                    return;
+                }
+            }
+
+            // If the current vibration is repeating and the incoming one is non-repeating, then
+            // ignore the non-repeating vibration. This is so that we don't cancel vibrations that
+            // are meant to grab the attention of the user, like ringtones and alarms, in favor of
+            // one-shot vibrations that are likely quite short.
+            if (!isRepeatingVibration(effect)
+                    && mCurrentVibration != null
+                    && isRepeatingVibration(mCurrentVibration.effect)) {
                 if (DEBUG) {
-                    Slog.d(TAG, "Ignoring incoming vibration in favor of current vibration");
+                    Slog.d(TAG, "Ignoring incoming vibration in favor of alarm vibration");
                 }
                 return;
             }
-        }
 
-        // If the current vibration is repeating and the incoming one is non-repeating, then ignore
-        // the non-repeating vibration. This is so that we don't cancel vibrations that are meant
-        // to grab the attention of the user, like ringtones and alarms, in favor of one-shot
-        // vibrations that are likely quite short.
-        if (!isRepeatingVibration(effect)
-                && mCurrentVibration != null && isRepeatingVibration(mCurrentVibration.effect)) {
-            if (DEBUG) {
-                Slog.d(TAG, "Ignoring incoming vibration in favor of alarm vibration");
-            }
-            return;
-        }
-
-        Vibration vib = new Vibration(token, effect, usageHint, uid, opPkg);
-        linkVibration(vib);
-
-        long ident = Binder.clearCallingIdentity();
-        try {
-            synchronized (mLock) {
+            Vibration vib = new Vibration(token, effect, usageHint, uid, opPkg);
+            linkVibration(vib);
+            long ident = Binder.clearCallingIdentity();
+            try {
                 doCancelVibrateLocked();
                 startVibrationLocked(vib);
                 addToPreviousVibrationsLocked(vib);
+            } finally {
+                Binder.restoreCallingIdentity(ident);
             }
-        } finally {
-            Binder.restoreCallingIdentity(ident);
         }
     }
 
@@ -516,6 +518,7 @@
         }
     };
 
+    @GuardedBy("mLock")
     private void doCancelVibrateLocked() {
         mH.removeCallbacks(mVibrationEndRunnable);
         if (mThread != null) {
@@ -538,6 +541,7 @@
         }
     }
 
+    @GuardedBy("mLock")
     private void startVibrationLocked(final Vibration vib) {
         if (!isAllowedToVibrateLocked(vib)) {
             return;
@@ -568,6 +572,7 @@
         startVibrationInnerLocked(vib);
     }
 
+    @GuardedBy("mLock")
     private void startVibrationInnerLocked(Vibration vib) {
         mCurrentVibration = vib;
         if (vib.effect instanceof VibrationEffect.OneShot) {
@@ -701,6 +706,7 @@
         return mode;
     }
 
+    @GuardedBy("mLock")
     private void reportFinishVibrationLocked() {
         if (mCurrentVibration != null) {
             try {
@@ -880,6 +886,7 @@
         }
     }
 
+    @GuardedBy("mLock")
     private long doVibratorPrebakedEffectLocked(Vibration vib) {
         final VibrationEffect.Prebaked prebaked = (VibrationEffect.Prebaked) vib.effect;
         final boolean usingInputDeviceVibrators;
@@ -905,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/Watchdog.java b/services/core/java/com/android/server/Watchdog.java
index 5215b6f..c8e0a5e 100644
--- a/services/core/java/com/android/server/Watchdog.java
+++ b/services/core/java/com/android/server/Watchdog.java
@@ -558,14 +558,7 @@
                 Slog.w(TAG, "Restart not allowed: Watchdog is *not* killing the system process");
             } else {
                 Slog.w(TAG, "*** WATCHDOG KILLING SYSTEM PROCESS: " + subject);
-                for (int i=0; i<blockedCheckers.size(); i++) {
-                    Slog.w(TAG, blockedCheckers.get(i).getName() + " stack trace:");
-                    StackTraceElement[] stackTrace
-                            = blockedCheckers.get(i).getThread().getStackTrace();
-                    for (StackTraceElement element: stackTrace) {
-                        Slog.w(TAG, "    at " + element);
-                    }
-                }
+                WatchdogDiagnostics.diagnoseCheckers(blockedCheckers);
                 Slog.w(TAG, "*** GOODBYE!");
                 Process.killProcess(Process.myPid());
                 System.exit(10);
diff --git a/services/core/java/com/android/server/WatchdogDiagnostics.java b/services/core/java/com/android/server/WatchdogDiagnostics.java
new file mode 100644
index 0000000..01db2d3
--- /dev/null
+++ b/services/core/java/com/android/server/WatchdogDiagnostics.java
@@ -0,0 +1,88 @@
+/*
+ * 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;
+
+import android.util.Log;
+import android.util.LogWriter;
+import android.util.Slog;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.Watchdog.HandlerChecker;
+
+import dalvik.system.AnnotatedStackTraceElement;
+import dalvik.system.VMStack;
+
+import java.io.PrintWriter;
+import java.util.List;
+
+/**
+ * Class to give diagnostic messages for Watchdogs.
+ */
+class WatchdogDiagnostics {
+    private static String getBlockedOnString(Object blockedOn) {
+        return String.format("- waiting to lock <0x%08x> (a %s)",
+                System.identityHashCode(blockedOn), blockedOn.getClass().getName());
+    }
+
+    private static String getLockedString(Object heldLock) {
+        return String.format("- locked <0x%08x> (a %s)", System.identityHashCode(heldLock),
+                heldLock.getClass().getName());
+    }
+
+    /**
+     * Print the annotated stack for the given thread. If the annotated stack cannot be retrieved,
+     * returns false.
+     */
+    @VisibleForTesting
+    public static boolean printAnnotatedStack(Thread thread, PrintWriter out) {
+        AnnotatedStackTraceElement stack[] = VMStack.getAnnotatedThreadStackTrace(thread);
+        if (stack == null) {
+            return false;
+        }
+        out.println(thread.getName() + " annotated stack trace:");
+        for (AnnotatedStackTraceElement element : stack) {
+            out.println("    at " + element.getStackTraceElement());
+            if (element.getBlockedOn() != null) {
+                out.println("    " + getBlockedOnString(element.getBlockedOn()));
+            }
+            if (element.getHeldLocks() != null) {
+                for (Object held : element.getHeldLocks()) {
+                    out.println("    " + getLockedString(held));
+                }
+            }
+        }
+        return true;
+    }
+
+    public static void diagnoseCheckers(final List<HandlerChecker> blockedCheckers) {
+        PrintWriter out = new PrintWriter(new LogWriter(Log.WARN, Watchdog.TAG, Log.LOG_ID_SYSTEM),
+                true);
+        for (int i=0; i<blockedCheckers.size(); i++) {
+            Thread blockedThread = blockedCheckers.get(i).getThread();
+            if (printAnnotatedStack(blockedThread, out)) {
+                continue;
+            }
+
+            // Fall back to "regular" stack trace, if necessary.
+            Slog.w(Watchdog.TAG, blockedThread.getName() + " stack trace:");
+            StackTraceElement[] stackTrace = blockedThread.getStackTrace();
+            for (StackTraceElement element : stackTrace) {
+                Slog.w(Watchdog.TAG, "    at " + element);
+            }
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/accounts/OWNERS b/services/core/java/com/android/server/accounts/OWNERS
new file mode 100644
index 0000000..ea5fd36
--- /dev/null
+++ b/services/core/java/com/android/server/accounts/OWNERS
@@ -0,0 +1,10 @@
+carlosvaldivia@google.com
+dementyev@google.com
+sandrakwan@google.com
+hackbod@google.com
+svetoslavganov@google.com
+moltmann@google.com
+fkupolov@google.com
+yamasani@google.com
+omakoto@google.com
+
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 7c032e7..f19b172 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -1099,7 +1099,7 @@
                     active.mNumActive++;
                 }
                 r.isForeground = true;
-                StatsLog.write(StatsLog.FOREGROUND_SERVICE_STATE_CHANGED, r.userId, r.shortName,
+                StatsLog.write(StatsLog.FOREGROUND_SERVICE_STATE_CHANGED, r.appInfo.uid, r.shortName,
                         StatsLog.FOREGROUND_SERVICE_STATE_CHANGED__STATE__ENTER);
             }
             r.postNotification();
@@ -1116,7 +1116,7 @@
                     decActiveForegroundAppLocked(smap, r);
                 }
                 r.isForeground = false;
-                StatsLog.write(StatsLog.FOREGROUND_SERVICE_STATE_CHANGED, r.userId, r.shortName,
+                StatsLog.write(StatsLog.FOREGROUND_SERVICE_STATE_CHANGED, r.appInfo.uid, r.shortName,
                         StatsLog.FOREGROUND_SERVICE_STATE_CHANGED__STATE__EXIT);
                 if (r.app != null) {
                     mAm.updateLruProcessLocked(r.app, false, null);
@@ -2607,7 +2607,7 @@
         cancelForegroundNotificationLocked(r);
         if (r.isForeground) {
             decActiveForegroundAppLocked(smap, r);
-            StatsLog.write(StatsLog.FOREGROUND_SERVICE_STATE_CHANGED, r.userId, r.shortName,
+            StatsLog.write(StatsLog.FOREGROUND_SERVICE_STATE_CHANGED, r.appInfo.uid, r.shortName,
                     StatsLog.FOREGROUND_SERVICE_STATE_CHANGED__STATE__EXIT);
         }
 
diff --git a/services/core/java/com/android/server/am/ActivityDisplay.java b/services/core/java/com/android/server/am/ActivityDisplay.java
index 220014f..608352b 100644
--- a/services/core/java/com/android/server/am/ActivityDisplay.java
+++ b/services/core/java/com/android/server/am/ActivityDisplay.java
@@ -657,6 +657,26 @@
         return false;
     }
 
+    void remove() {
+        final boolean destroyContentOnRemoval = shouldDestroyContentOnRemove();
+        while (getChildCount() > 0) {
+            final ActivityStack stack = getChildAt(0);
+            if (destroyContentOnRemoval) {
+                mSupervisor.moveStackToDisplayLocked(stack.mStackId, DEFAULT_DISPLAY,
+                        false /* onTop */);
+                stack.finishAllActivitiesLocked(true /* immediately */);
+            } else {
+                // Moving all tasks to fullscreen stack, because it's guaranteed to be
+                // a valid launch stack for all activities. This way the task history from
+                // external display will be preserved on primary after move.
+                mSupervisor.moveTasksToFullscreenStackLocked(stack, true /* onTop */);
+            }
+        }
+
+        mWindowContainerController.removeContainer();
+        mWindowContainerController = null;
+    }
+
     /** Update and get all UIDs that are present on the display and have access to it. */
     IntArray getPresentUIDs() {
         mDisplayAccessUIDs.clear();
@@ -666,7 +686,7 @@
         return mDisplayAccessUIDs;
     }
 
-    boolean shouldDestroyContentOnRemove() {
+    private boolean shouldDestroyContentOnRemove() {
         return mDisplay.getRemoveMode() == REMOVE_MODE_DESTROY_CONTENT;
     }
 
diff --git a/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java b/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java
index 0a7d3fd..8367916 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;
@@ -81,7 +81,7 @@
     static final boolean DEBUG_FOREGROUND_SERVICE = DEBUG_ALL || false;
     static final boolean DEBUG_SERVICE_EXECUTING = DEBUG_ALL || false;
     static final boolean DEBUG_STACK = DEBUG_ALL || false;
-    static final boolean DEBUG_STATES = DEBUG_ALL_ACTIVITIES || false;
+    static final boolean DEBUG_STATES = DEBUG_ALL_ACTIVITIES || true;
     static final boolean DEBUG_SWITCH = DEBUG_ALL || false;
     static final boolean DEBUG_TASKS = DEBUG_ALL || false;
     static final boolean DEBUG_TRANSITION = 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 be437a6..bb59317 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -38,7 +38,6 @@
 import static android.app.ActivityThread.PROC_START_SEQ_IDENT;
 import static android.app.AppOpsManager.OP_ASSIST_STRUCTURE;
 import static android.app.AppOpsManager.OP_NONE;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
@@ -193,6 +192,7 @@
 import static com.android.server.am.ActivityStackSupervisor.ON_TOP;
 import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS;
 import static com.android.server.am.ActivityStackSupervisor.REMOVE_FROM_RECENTS;
+import static com.android.server.am.MemoryStatUtil.readMemoryStatFromMemcg;
 import static com.android.server.am.TaskRecord.INVALID_TASK_ID;
 import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_DONT_LOCK;
 import static com.android.server.am.TaskRecord.REPARENT_KEEP_STACK_AT_FRONT;
@@ -249,6 +249,7 @@
 import android.app.NotificationManager;
 import android.app.PendingIntent;
 import android.app.PictureInPictureParams;
+import android.app.ProcessMemoryState;
 import android.app.ProfilerInfo;
 import android.app.RemoteAction;
 import android.app.WaitResult;
@@ -383,6 +384,7 @@
 import android.view.Gravity;
 import android.view.IRecentsAnimationRunner;
 import android.view.LayoutInflater;
+import android.view.RemoteAnimationAdapter;
 import android.view.RemoteAnimationDefinition;
 import android.view.View;
 import android.view.WindowManager;
@@ -440,6 +442,7 @@
 import com.android.server.ThreadPriorityBooster;
 import com.android.server.Watchdog;
 import com.android.server.am.ActivityStack.ActivityState;
+import com.android.server.am.MemoryStatUtil.MemoryStat;
 import com.android.server.am.proto.ActivityManagerServiceProto;
 import com.android.server.am.proto.BroadcastProto;
 import com.android.server.am.proto.GrantUriProto;
@@ -458,7 +461,6 @@
 import com.android.server.utils.PriorityDump;
 import com.android.server.vr.VrManagerInternal;
 import com.android.server.wm.PinnedStackWindowController;
-import com.android.server.wm.RecentsAnimationController;
 import com.android.server.wm.WindowManagerService;
 
 import dalvik.system.VMRuntime;
@@ -585,6 +587,10 @@
     // How long we wait until we timeout on key dispatching during instrumentation.
     static final int INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT = 60*1000;
 
+    // Disable hidden API checks for the newly started instrumentation.
+    // Must be kept in sync with Am.
+    private static final int INSTRUMENTATION_FLAG_DISABLE_HIDDEN_API_CHECKS = 1 << 0;
+
     // How long to wait in getAssistContextExtras for the activity and foreground services
     // to respond with the result.
     static final int PENDING_ASSIST_EXTRAS_TIMEOUT = 500;
@@ -609,6 +615,9 @@
     // as one line, but close enough for now.
     static final int RESERVED_BYTES_PER_LOGCAT_LINE = 100;
 
+    /** If a UID observer takes more than this long, send a WTF. */
+    private static final int SLOW_UID_OBSERVER_THRESHOLD_MS = 20;
+
     // Access modes for handleIncomingUser.
     static final int ALLOW_NON_FULL = 0;
     static final int ALLOW_NON_FULL_IN_PROFILE = 1;
@@ -790,6 +799,9 @@
     @VisibleForTesting
     long mWaitForNetworkTimeoutMs;
 
+    /** Total # of UID change events dispatched, shown in dumpsys. */
+    int mUidChangeDispatchCount;
+
     /**
      * Helper class which strips out priority and proto arguments then calls the dump function with
      * the appropriate arguments. If priority arguments are omitted, function calls the legacy
@@ -1712,6 +1724,15 @@
         final int which;
         final int cutpoint;
 
+        /**
+         * Total # of callback calls that took more than {@link #SLOW_UID_OBSERVER_THRESHOLD_MS}.
+         * We show it in dumpsys.
+         */
+        int mSlowDispatchCount;
+
+        /** Max time it took for each dispatch. */
+        int mMaxDispatchTime;
+
         final SparseIntArray lastProcStates;
 
         // Please keep the enum lists in sync
@@ -1867,7 +1888,6 @@
     static final int REPORT_MEM_USAGE_MSG = 33;
     static final int IMMERSIVE_MODE_LOCK_MSG = 37;
     static final int PERSIST_URI_GRANTS_MSG = 38;
-    static final int REQUEST_ALL_PSS_MSG = 39;
     static final int UPDATE_TIME_PREFERENCE_MSG = 41;
     static final int ENTER_ANIMATION_COMPLETE_MSG = 44;
     static final int FINISH_BOOTING_MSG = 45;
@@ -1936,6 +1956,9 @@
 
     final ActivityManagerConstants mConstants;
 
+    // Encapsulates the global setting "hidden_api_blacklist_exemptions"
+    final HiddenApiBlacklist mHiddenApiBlacklist;
+
     PackageManagerInternal mPackageManagerInt;
 
     // VoiceInteraction session ID that changes for each new request except when
@@ -2347,12 +2370,6 @@
                 writeGrantedUriPermissions();
                 break;
             }
-            case REQUEST_ALL_PSS_MSG: {
-                synchronized (ActivityManagerService.this) {
-                    requestPssAllProcsLocked(SystemClock.uptimeMillis(), true, false);
-                }
-                break;
-            }
             case UPDATE_TIME_PREFERENCE_MSG: {
                 // The user's time format preference might have changed.
                 // For convenience we re-use the Intent extra values.
@@ -2661,11 +2678,17 @@
                         procState = proc.pssProcState;
                         statType = proc.pssStatType;
                         lastPssTime = proc.lastPssTime;
+                        long now = SystemClock.uptimeMillis();
                         if (proc.thread != null && procState == proc.setProcState
                                 && (lastPssTime+ProcessList.PSS_SAFE_TIME_FROM_STATE_CHANGE)
-                                        < SystemClock.uptimeMillis()) {
+                                        < now) {
                             pid = proc.pid;
                         } else {
+                            ProcessList.abortNextPssTime(proc.procStateMemTracker);
+                            if (DEBUG_PSS) Slog.d(TAG_PSS, "Skipped pss collection of " + pid +
+                                    ": still need " +
+                                    (lastPssTime+ProcessList.PSS_SAFE_TIME_FROM_STATE_CHANGE-now) +
+                                    "ms until safe");
                             proc = null;
                             pid = 0;
                         }
@@ -2872,6 +2895,42 @@
         }
     }
 
+    /**
+     * Encapsulates the globla setting "hidden_api_blacklist_exemptions", including tracking the
+     * latest value via a content observer.
+     */
+    static class HiddenApiBlacklist extends ContentObserver {
+
+        private final Context mContext;
+        private boolean mBlacklistDisabled;
+
+        public HiddenApiBlacklist(Handler handler, Context context) {
+            super(handler);
+            mContext = context;
+        }
+
+        public void registerObserver() {
+            mContext.getContentResolver().registerContentObserver(
+                    Settings.Global.getUriFor(Settings.Global.HIDDEN_API_BLACKLIST_EXEMPTIONS),
+                    false,
+                    this);
+            update();
+        }
+
+        private void update() {
+            mBlacklistDisabled = "*".equals(Settings.Global.getString(mContext.getContentResolver(),
+                    Settings.Global.HIDDEN_API_BLACKLIST_EXEMPTIONS));
+        }
+
+        boolean isDisabled() {
+            return mBlacklistDisabled;
+        }
+
+        public void onChange(boolean selfChange) {
+            update();
+        }
+    }
+
     @VisibleForTesting
     public ActivityManagerService(Injector injector) {
         mInjector = injector;
@@ -2906,6 +2965,7 @@
         mLifecycleManager = null;
         mProcStartHandlerThread = null;
         mProcStartHandler = null;
+        mHiddenApiBlacklist = null;
     }
 
     // Note: This method is invoked on the main thread but may need to attach various
@@ -3049,8 +3109,20 @@
             }
         };
 
+        mHiddenApiBlacklist = new HiddenApiBlacklist(mHandler, mContext);
+
         Watchdog.getInstance().addMonitor(this);
         Watchdog.getInstance().addThread(mHandler);
+
+        // bind background thread to little cores
+        // this is expected to fail inside of framework tests because apps can't touch cpusets directly
+        try {
+            Process.setThreadGroupAndCpuset(BackgroundThread.get().getThreadId(),
+                    Process.THREAD_GROUP_BG_NONINTERACTIVE);
+        } catch (Exception e) {
+            Slog.w(TAG, "Setting background thread cpuset failed");
+        }
+
     }
 
     protected ActivityStackSupervisor createStackSupervisor() {
@@ -3333,6 +3405,7 @@
      * Update AMS states when an activity is resumed. This should only be called by
      * {@link ActivityStack#setResumedActivityLocked} when an activity is resumed.
      */
+    @GuardedBy("this")
     void setResumedActivityUncheckLocked(ActivityRecord r, String reason) {
         final TaskRecord task = r.getTask();
         if (task.isActivityTypeStandard()) {
@@ -3858,6 +3931,7 @@
             info.className = entryPoint;
             info.packageName = "android";
             info.seInfoUser = SELinuxUtil.COMPLETE_STR;
+            info.targetSdkVersion = Build.VERSION.SDK_INT;
             ProcessRecord proc = startProcessLocked(processName, info /* info */,
                     false /* knownToBeDead */, 0 /* intentFlags */, ""  /* hostingType */,
                     null /* hostingName */, true /* allowWhileBooting */, true /* isolated */,
@@ -3867,6 +3941,7 @@
         }
     }
 
+    @GuardedBy("this")
     final ProcessRecord startProcessLocked(String processName,
             ApplicationInfo info, boolean knownToBeDead, int intentFlags,
             String hostingType, ComponentName hostingName, boolean allowWhileBooting,
@@ -3877,6 +3952,7 @@
                 null /* crashHandler */);
     }
 
+    @GuardedBy("this")
     final ProcessRecord startProcessLocked(String processName, ApplicationInfo info,
             boolean knownToBeDead, int intentFlags, String hostingType, ComponentName hostingName,
             boolean allowWhileBooting, boolean isolated, int isolatedUid, boolean keepIfLarge,
@@ -3993,16 +4069,25 @@
         return (ai.flags&ApplicationInfo.FLAG_PERSISTENT) != 0;
     }
 
+    @GuardedBy("this")
     private final void startProcessLocked(ProcessRecord app,
             String hostingType, String hostingNameStr) {
         startProcessLocked(app, hostingType, hostingNameStr, null /* abiOverride */);
     }
 
+    @GuardedBy("this")
+    private final boolean startProcessLocked(ProcessRecord app,
+            String hostingType, String hostingNameStr, String abiOverride) {
+        return startProcessLocked(app, hostingType, hostingNameStr,
+                false /* disableHiddenApiChecks */, abiOverride);
+    }
+
     /**
      * @return {@code true} if process start is successful, false otherwise.
      */
+    @GuardedBy("this")
     private final boolean startProcessLocked(ProcessRecord app, String hostingType,
-            String hostingNameStr, String abiOverride) {
+            String hostingNameStr, boolean disableHiddenApiChecks, String abiOverride) {
         if (app.pendingStart) {
             return true;
         }
@@ -4125,10 +4210,12 @@
                 runtimeFlags |= Zygote.ONLY_USE_SYSTEM_OAT_FILES;
             }
 
-            if (app.info.isAllowedToUseHiddenApi()) {
-                // This app is allowed to use undocumented and private APIs. Set
-                // up its runtime with the appropriate flag.
-                runtimeFlags |= Zygote.DISABLE_HIDDEN_API_CHECKS;
+            if (!app.info.isAllowedToUseHiddenApi() &&
+                    !disableHiddenApiChecks &&
+                    !mHiddenApiBlacklist.isDisabled()) {
+                // This app is not allowed to use undocumented and private APIs, or blacklisting is
+                // enabled. Set up its runtime with the appropriate flag.
+                runtimeFlags |= Zygote.ENABLE_HIDDEN_API_CHECKS;
             }
 
             String invokeWith = null;
@@ -4426,7 +4513,7 @@
                 "updateUsageStats: comp=" + component + "res=" + resumed);
         final BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
         StatsLog.write(StatsLog.ACTIVITY_FOREGROUND_STATE_CHANGED,
-            component.userId, component.realActivity.getPackageName(),
+            component.app.uid, component.realActivity.getPackageName(),
             component.realActivity.getShortClassName(), resumed ?
                         StatsLog.ACTIVITY_FOREGROUND_STATE_CHANGED__ACTIVITY__MOVE_TO_FOREGROUND :
                         StatsLog.ACTIVITY_FOREGROUND_STATE_CHANGED__ACTIVITY__MOVE_TO_BACKGROUND);
@@ -4722,6 +4809,7 @@
                     "*** Delivering " + N + " uid changes");
         }
 
+        mUidChangeDispatchCount += N;
         int i = mUidObservers.beginBroadcast();
         while (i > 0) {
             i--;
@@ -4774,6 +4862,7 @@
                     // interested in all proc state changes.
                     continue;
                 }
+                final long start = SystemClock.uptimeMillis();
                 if ((change & UidRecord.CHANGE_IDLE) != 0) {
                     if ((reg.which & ActivityManager.UID_OBSERVER_IDLE) != 0) {
                         if (DEBUG_UID_OBSERVERS) Slog.i(TAG_UID_OBSERVERS,
@@ -4834,6 +4923,13 @@
                         }
                     }
                 }
+                final int duration = (int) (SystemClock.uptimeMillis() - start);
+                if (reg.mMaxDispatchTime < duration) {
+                    reg.mMaxDispatchTime = duration;
+                }
+                if (duration >= SLOW_UID_OBSERVER_THRESHOLD_MS) {
+                    reg.mSlowDispatchCount++;
+                }
             }
         } catch (RemoteException e) {
         }
@@ -5195,6 +5291,7 @@
                 .supportsLocalVoiceInteraction();
     }
 
+    @GuardedBy("this")
     void onLocalVoiceInteractionStartedLocked(IBinder activity,
             IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor) {
         ActivityRecord activityToCallback = ActivityRecord.forTokenLocked(activity);
@@ -5693,6 +5790,7 @@
      * as a result of that process going away.  Clears out all connections
      * to the process.
      */
+    @GuardedBy("this")
     private final void handleAppDiedLocked(ProcessRecord app,
             boolean restarting, boolean allowRestart) {
         int pid = app.pid;
@@ -5839,10 +5937,12 @@
         }
     }
 
+    @GuardedBy("this")
     final void appDiedLocked(ProcessRecord app) {
        appDiedLocked(app, app.pid, app.thread, false);
     }
 
+    @GuardedBy("this")
     final void appDiedLocked(ProcessRecord app, int pid, IApplicationThread thread,
             boolean fromBinderDied) {
         // First check if this ProcessRecord is actually active for the pid.
@@ -6303,6 +6403,7 @@
         }
     }
 
+    @GuardedBy("this")
     final void showLaunchWarningLocked(final ActivityRecord cur, final ActivityRecord next) {
         if (!mLaunchWarningShown) {
             mLaunchWarningShown = true;
@@ -6729,6 +6830,7 @@
         }
     }
 
+    @GuardedBy("this")
     void closeSystemDialogsLocked(String reason) {
         Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
@@ -6835,11 +6937,13 @@
         }
     }
 
+    @GuardedBy("this")
     private void forceStopPackageLocked(final String packageName, int uid, String reason) {
         forceStopPackageLocked(packageName, UserHandle.getAppId(uid), false,
                 false, true, false, false, UserHandle.getUserId(uid), reason);
     }
 
+    @GuardedBy("this")
     private void finishForceStopPackageLocked(final String packageName, int uid) {
         Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
                 Uri.fromParts("package", packageName, null));
@@ -6855,6 +6959,7 @@
     }
 
 
+    @GuardedBy("this")
     private final boolean killPackageProcessesLocked(String packageName, int appId,
             int userId, int minOomAdj, boolean callerWillRestart, boolean allowRestart,
             boolean doit, boolean evenPersistent, String reason) {
@@ -7026,6 +7131,7 @@
         return didSomething;
     }
 
+    @GuardedBy("this")
     final boolean forceStopPackageLocked(String packageName, int appId,
             boolean callerWillRestart, boolean purgeCache, boolean doit,
             boolean evenPersistent, boolean uninstalling, int userId, String reason) {
@@ -7237,6 +7343,7 @@
         }
     }
 
+    @GuardedBy("this")
     boolean removeProcessLocked(ProcessRecord app,
             boolean callerWillRestart, boolean allowRestart, String reason) {
         final String name = app.processName;
@@ -7291,6 +7398,7 @@
         return needRestart;
     }
 
+    @GuardedBy("this")
     private final void processContentProviderPublishTimedOutLocked(ProcessRecord app) {
         cleanupAppInLaunchingProvidersLocked(app, true);
         removeProcessLocked(app, false, true, "timeout publishing content providers");
@@ -7351,6 +7459,7 @@
         }
     }
 
+    @GuardedBy("this")
     private final boolean attachApplicationLocked(IApplicationThread thread,
             int pid, int callingUid, long startSeq) {
 
@@ -9241,6 +9350,7 @@
                 grantEphemeralAccess(userId, intent, targetAppId, ephemeralAppId);
     }
 
+    @GuardedBy("this")
     private UriPermission findUriPermissionLocked(int targetUid, GrantUri grantUri) {
         final ArrayMap<GrantUri, UriPermission> targetUris = mGrantedUriPermissions.get(targetUid);
         if (targetUris != null) {
@@ -9249,6 +9359,7 @@
         return null;
     }
 
+    @GuardedBy("this")
     private UriPermission findOrCreateUriPermissionLocked(String sourcePkg,
             String targetPkg, int targetUid, GrantUri grantUri) {
         ArrayMap<GrantUri, UriPermission> targetUris = mGrantedUriPermissions.get(targetUid);
@@ -9266,6 +9377,7 @@
         return perm;
     }
 
+    @GuardedBy("this")
     private final boolean checkUriPermissionLocked(GrantUri grantUri, int uid,
             final int modeFlags) {
         final boolean persistable = (modeFlags & Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION) != 0;
@@ -9336,6 +9448,7 @@
      * If you already know the uid of the target, you can supply it in
      * lastTargetUid else set that to -1.
      */
+    @GuardedBy("this")
     int checkGrantUriPermissionLocked(int callingUid, String targetPkg, GrantUri grantUri,
             final int modeFlags, int lastTargetUid) {
         if (!Intent.isAccessUriMode(modeFlags)) {
@@ -9498,6 +9611,7 @@
         }
     }
 
+    @GuardedBy("this")
     void grantUriPermissionUncheckedLocked(int targetUid, String targetPkg, GrantUri grantUri,
             final int modeFlags, UriPermissionOwner owner) {
         if (!Intent.isAccessUriMode(modeFlags)) {
@@ -9527,6 +9641,7 @@
         perm.grantModes(modeFlags, owner);
     }
 
+    @GuardedBy("this")
     void grantUriPermissionLocked(int callingUid, String targetPkg, GrantUri grantUri,
             final int modeFlags, UriPermissionOwner owner, int targetUserId) {
         if (targetPkg == null) {
@@ -9578,6 +9693,7 @@
     /**
      * Like checkGrantUriPermissionLocked, but takes an Intent.
      */
+    @GuardedBy("this")
     NeededUriGrants checkGrantUriPermissionFromIntentLocked(int callingUid,
             String targetPkg, Intent intent, int mode, NeededUriGrants needed, int targetUserId) {
         if (DEBUG_URI_PERMISSION) Slog.v(TAG_URI_PERMISSION,
@@ -9664,6 +9780,7 @@
     /**
      * Like grantUriPermissionUncheckedLocked, but takes an Intent.
      */
+    @GuardedBy("this")
     void grantUriPermissionUncheckedFromIntentLocked(NeededUriGrants needed,
             UriPermissionOwner owner) {
         if (needed != null) {
@@ -9675,6 +9792,7 @@
         }
     }
 
+    @GuardedBy("this")
     void grantUriPermissionFromIntentLocked(int callingUid,
             String targetPkg, Intent intent, UriPermissionOwner owner, int targetUserId) {
         NeededUriGrants needed = checkGrantUriPermissionFromIntentLocked(callingUid, targetPkg,
@@ -9719,6 +9837,7 @@
         }
     }
 
+    @GuardedBy("this")
     void removeUriPermissionIfNeededLocked(UriPermission perm) {
         if (perm.modeFlags == 0) {
             final ArrayMap<GrantUri, UriPermission> perms = mGrantedUriPermissions.get(
@@ -9735,6 +9854,7 @@
         }
     }
 
+    @GuardedBy("this")
     private void revokeUriPermissionLocked(String targetPackage, int callingUid, GrantUri grantUri,
             final int modeFlags) {
         if (DEBUG_URI_PERMISSION) Slog.v(TAG_URI_PERMISSION,
@@ -9869,6 +9989,7 @@
      * @param targetOnly When {@code true}, only remove permissions where the app is the target,
      * not source.
      */
+    @GuardedBy("this")
     private void removeUriPermissionsForPackageLocked(
             String packageName, int userHandle, boolean persistable, boolean targetOnly) {
         if (userHandle == UserHandle.USER_ALL && packageName == null) {
@@ -10055,6 +10176,7 @@
         }
     }
 
+    @GuardedBy("this")
     private void readGrantedUriPermissionsLocked() {
         if (DEBUG_URI_PERMISSION) Slog.v(TAG_URI_PERMISSION, "readGrantedUriPermissions()");
 
@@ -10128,6 +10250,75 @@
     }
 
     /**
+     * Updates (grants or revokes) a persitable URI permission.
+     *
+     * @param uri URI to be granted or revoked.
+     * @param prefix if {@code false}, permission apply to this specific URI; if {@code true}, it
+     * applies to all URIs that are prefixed by this URI.
+     * @param packageName target package.
+     * @param grant if {@code true} a new permission will be granted, otherwise an existing
+     * permission will be revoked.
+     * @param userId user handle
+     *
+     * @return whether or not the requested succeeded.
+     *
+     * @deprecated TODO(b/72055774): caller should use takePersistableUriPermission() or
+     * releasePersistableUriPermission() instead, but such change will be made in a separate CL
+     * so it can be easily reverted if it breaks existing functionality.
+     */
+    @Deprecated // STOPSHIP if not removed
+    @Override
+    public boolean updatePersistableUriPermission(Uri uri, boolean prefix, String packageName,
+            boolean grant, int userId) {
+        enforceCallingPermission(android.Manifest.permission.GET_APP_GRANTED_URI_PERMISSIONS,
+                "updatePersistableUriPermission");
+        final int uid = mPackageManagerInt.getPackageUid(packageName, 0, userId);
+
+        final GrantUri grantUri = new GrantUri(userId, uri, prefix);
+
+        boolean persistChanged = false;
+        synchronized (this) {
+            if (grant) { // Grant
+                final String authority = uri.getAuthority();
+                final ProviderInfo pi = getProviderInfoLocked(authority, userId, 0);
+                if (pi == null) {
+                    Slog.w(TAG, "No content provider found for authority " + authority);
+                    return false;
+                }
+                final UriPermission permission = findOrCreateUriPermissionLocked(pi.packageName,
+                        packageName, uid, grantUri);
+                if (permission.isNew()) {
+                    final int modeFlags = Intent.FLAG_GRANT_READ_URI_PERMISSION
+                            | Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
+                    permission.initPersistedModes(modeFlags, System.currentTimeMillis());
+                    persistChanged = true;
+                } else {
+                    // Caller should not try to grant permission that is already granted.
+                    Slog.w(TAG_URI_PERMISSION,
+                            "permission already granted for " + grantUri.toSafeString());
+                    return false;
+                }
+                persistChanged |= maybePrunePersistedUriGrantsLocked(uid);
+            } else { // Revoke
+                final UriPermission permission = findUriPermissionLocked(uid, grantUri);
+                if (permission == null) {
+                    // Caller should not try to revoke permission that is not granted.
+                    Slog.v(TAG_URI_PERMISSION, "no permission for " + grantUri.toSafeString());
+                    return false;
+                } else {
+                    permission.modeFlags = 0;
+                    removeUriPermissionIfNeededLocked(permission);
+                    persistChanged = true;
+                }
+            }
+            if (persistChanged) {
+                schedulePersistUriGrants();
+            }
+        }
+        return true;
+    }
+
+    /**
      * @param uri This uri must NOT contain an embedded userId.
      * @param userId The userId in which the uri is to be resolved.
      */
@@ -10217,6 +10408,7 @@
      *
      * @return if any mutations occured that require persisting.
      */
+    @GuardedBy("this")
     private boolean maybePrunePersistedUriGrantsLocked(int uid) {
         final ArrayMap<GrantUri, UriPermission> perms = mGrantedUriPermissions.get(uid);
         if (perms == null) return false;
@@ -11390,9 +11582,6 @@
             throw new IllegalArgumentException("Invalid task, not in foreground");
         }
 
-        // When a task is locked, dismiss the pinned stack if it exists
-        mStackSupervisor.removeStacksInWindowingModes(WINDOWING_MODE_PINNED);
-
         // {@code isSystemCaller} is used to distinguish whether this request is initiated by the
         // system or a specific app.
         // * System-initiated requests will only start the pinned mode (screen pinning)
@@ -11402,6 +11591,9 @@
         final int callingUid = Binder.getCallingUid();
         long ident = Binder.clearCallingIdentity();
         try {
+            // When a task is locked, dismiss the pinned stack if it exists
+            mStackSupervisor.removeStacksInWindowingModes(WINDOWING_MODE_PINNED);
+
             mLockTaskController.startLockTaskMode(task, isSystemCaller, callingUid);
         } finally {
             Binder.restoreCallingIdentity(ident);
@@ -11426,8 +11618,11 @@
         long ident = Binder.clearCallingIdentity();
         try {
             synchronized (this) {
-                startLockTaskModeLocked(mStackSupervisor.anyTaskForIdLocked(taskId),
-                        true /* isSystemCaller */);
+                final TaskRecord task = mStackSupervisor.anyTaskForIdLocked(taskId);
+
+                // When starting lock task mode the stack must be in front and focused
+                task.getStack().moveToFront("startSystemLockTaskMode");
+                startLockTaskModeLocked(task, true /* isSystemCaller */);
             }
         } finally {
             Binder.restoreCallingIdentity(ident);
@@ -12714,6 +12909,7 @@
     // GLOBAL MANAGEMENT
     // =========================================================
 
+    @GuardedBy("this")
     final ProcessRecord newProcessRecordLocked(ApplicationInfo info, String customProcess,
             boolean isolated, int isolatedUid) {
         String proc = customProcess != null ? customProcess : info.processName;
@@ -12758,6 +12954,9 @@
         if (!mBooted && !mBooting
                 && userId == UserHandle.USER_SYSTEM
                 && (info.flags & PERSISTENT_MASK) == PERSISTENT_MASK) {
+            // The system process is initialized to SCHED_GROUP_DEFAULT in init.rc.
+            r.curSchedGroup = ProcessList.SCHED_GROUP_DEFAULT;
+            r.setSchedGroup = ProcessList.SCHED_GROUP_DEFAULT;
             r.persistent = true;
             r.maxAdj = ProcessList.PERSISTENT_PROC_ADJ;
         }
@@ -12800,8 +12999,15 @@
         }
     }
 
+    @GuardedBy("this")
     final ProcessRecord addAppLocked(ApplicationInfo info, String customProcess, boolean isolated,
             String abiOverride) {
+        return addAppLocked(info, customProcess, isolated, false /* disableHiddenApiChecks */,
+                abiOverride);
+    }
+
+    final ProcessRecord addAppLocked(ApplicationInfo info, String customProcess, boolean isolated,
+            boolean disableHiddenApiChecks, String abiOverride) {
         ProcessRecord app;
         if (!isolated) {
             app = getProcessRecordLocked(customProcess != null ? customProcess : info.processName,
@@ -12833,7 +13039,8 @@
         if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
             mPersistentStartingProcesses.add(app);
             startProcessLocked(app, "added application",
-                    customProcess != null ? customProcess : app.processName, abiOverride);
+                    customProcess != null ? customProcess : app.processName, disableHiddenApiChecks,
+                    abiOverride);
         }
 
         return app;
@@ -12916,6 +13123,7 @@
         }
     }
 
+    @GuardedBy("this")
     void finishRunningVoiceLocked() {
         if (mRunningVoice != null) {
             mRunningVoice = null;
@@ -12931,6 +13139,7 @@
         }
     }
 
+    @GuardedBy("this")
     void updateSleepIfNeededLocked() {
         final boolean shouldSleep = !mStackSupervisor.hasAwakeDisplay();
         final boolean wasSleeping = mSleeping;
@@ -13035,6 +13244,7 @@
         Binder.restoreCallingIdentity(origId);
     }
 
+    @GuardedBy("this")
     void startRunningVoiceLocked(IVoiceInteractionSession session, int targetUid) {
         Slog.d(TAG, "<<<  startRunningVoiceLocked()");
         mVoiceWakeLock.setWorkSource(new WorkSource(targetUid));
@@ -14587,9 +14797,6 @@
                             mTestPssMode, isSleepingLocked(), now);
                 }
             }
-
-            mHandler.removeMessages(REQUEST_ALL_PSS_MSG);
-            mHandler.sendEmptyMessageDelayed(REQUEST_ALL_PSS_MSG, 2*60*1000);
         }
     }
 
@@ -14638,6 +14845,7 @@
                 NETWORK_ACCESS_TIMEOUT_MS, NETWORK_ACCESS_TIMEOUT_DEFAULT_MS);
         final boolean supportsLeanbackOnly =
                 mContext.getPackageManager().hasSystemFeature(FEATURE_LEANBACK_ONLY);
+        mHiddenApiBlacklist.registerObserver();
 
         // Transfer any global setting for forcing RTL layout, into a System Property
         SystemProperties.set(DEVELOPMENT_FORCE_RTL, forceRtl ? "1":"0");
@@ -14896,8 +15104,6 @@
             mUserController.sendUserSwitchBroadcasts(-1, currentUserId);
 
             BinderInternal.nSetBinderProxyCountEnabled(true);
-            //STOPSHIP: Temporary BinderProxy Threshold for b/71353150
-            BinderInternal.nSetBinderProxyCountWatermarks(1500, 1200);
             BinderInternal.setBinderProxyCountCallback(
                     new BinderInternal.BinderProxyLimitListener() {
                         @Override
@@ -16284,6 +16490,7 @@
         return false;
     }
 
+    @GuardedBy("this")
     void dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
             int opti, boolean dumpAll, String dumpPackage, int dumpAppId) {
         boolean needSep = false;
@@ -16732,11 +16939,31 @@
                         pw.print(" mLowRamSinceLastIdle=");
                         TimeUtils.formatDuration(getLowRamTimeSinceIdle(now), pw);
                         pw.println();
+                pw.println();
+                pw.print("  mUidChangeDispatchCount=");
+                pw.print(mUidChangeDispatchCount);
+                pw.println();
+
+                pw.println("  Slow UID dispatches:");
+                final int N = mUidObservers.beginBroadcast();
+                for (int i = 0; i < N; i++) {
+                    UidObserverRegistration r =
+                            (UidObserverRegistration) mUidObservers.getBroadcastCookie(i);
+                    pw.print("    ");
+                    pw.print(mUidObservers.getBroadcastItem(i).getClass().getTypeName());
+                    pw.print(": ");
+                    pw.print(r.mSlowDispatchCount);
+                    pw.print(" / Max ");
+                    pw.print(r.mMaxDispatchTime);
+                    pw.println("ms");
+                }
+                mUidObservers.finishBroadcast();
             }
         }
         pw.println("  mForceBackgroundCheck=" + mForceBackgroundCheck);
     }
 
+    @GuardedBy("this")
     void writeProcessesToProtoLocked(ProtoOutputStream proto, String dumpPackage) {
         int numPers = 0;
 
@@ -17564,6 +17791,7 @@
         }
     }
 
+    @GuardedBy("this")
     void dumpPermissionsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
             int opti, boolean dumpAll, String dumpPackage) {
         boolean needSep = false;
@@ -18618,6 +18846,7 @@
                         final long myTotalPss = mi.getTotalPss();
                         final long myTotalSwapPss = mi.getTotalSwappedOutPss();
                         totalPss += myTotalPss;
+                        totalSwapPss += myTotalSwapPss;
                         nativeProcTotalPss += myTotalPss;
 
                         MemItem pssItem = new MemItem(st.name + " (pid " + st.pid + ")",
@@ -19636,6 +19865,7 @@
      * @return Returns true if the given process has been restarted, so the
      * app that was passed in must remain on the process lists.
      */
+    @GuardedBy("this")
     private final boolean cleanUpApplicationRecordLocked(ProcessRecord app,
             boolean restarting, boolean allowRestart, int index, boolean replacingPid) {
         if (index >= 0) {
@@ -19645,6 +19875,7 @@
 
         mProcessesToGc.remove(app);
         mPendingPssProcesses.remove(app);
+        ProcessList.abortNextPssTime(app.procStateMemTracker);
 
         // Dismiss any open dialogs.
         if (app.crashDialog != null && !app.forceCrashReport) {
@@ -20724,6 +20955,7 @@
         }
     }
 
+    @GuardedBy("this")
     final int broadcastIntentLocked(ProcessRecord callerApp,
             String callerPackage, Intent intent, String resolvedType,
             IIntentReceiver resultTo, int resultCode, String resultData,
@@ -21647,7 +21879,10 @@
                 mUsageStatsService.reportEvent(ii.targetPackage, userId,
                         UsageEvents.Event.SYSTEM_INTERACTION);
             }
-            ProcessRecord app = addAppLocked(ai, defProcess, false, abiOverride);
+            boolean disableHiddenApiChecks =
+                    (flags & INSTRUMENTATION_FLAG_DISABLE_HIDDEN_API_CHECKS) != 0;
+            ProcessRecord app = addAppLocked(ai, defProcess, false, disableHiddenApiChecks,
+                    abiOverride);
             app.instr = activeInstr;
             activeInstr.mFinished = false;
             activeInstr.mRunningProcesses.add(app);
@@ -21714,6 +21949,7 @@
         }
     }
 
+    @GuardedBy("this")
     void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
         if (app.instr == null) {
             Slog.w(TAG, "finishInstrumentation called on non-instrumented: " + app);
@@ -21998,7 +22234,7 @@
         }
         try {
             if (values != null) {
-                changes = updateGlobalConfiguration(values, initLocale, persistent, userId,
+                changes = updateGlobalConfigurationLocked(values, initLocale, persistent, userId,
                         deferResume);
             }
 
@@ -22016,8 +22252,16 @@
         return kept;
     }
 
+    /**
+     * Returns true if this configuration change is interesting enough to send an
+     * {@link Intent#ACTION_SPLIT_CONFIGURATION_CHANGED} broadcast.
+     */
+    private static boolean isSplitConfigurationChange(int configDiff) {
+        return (configDiff & (ActivityInfo.CONFIG_LOCALE | ActivityInfo.CONFIG_DENSITY)) != 0;
+    }
+
     /** Update default (global) configuration and notify listeners about changes. */
-    private int updateGlobalConfiguration(@NonNull Configuration values, boolean initLocale,
+    private int updateGlobalConfigurationLocked(@NonNull Configuration values, boolean initLocale,
             boolean persistent, int userId, boolean deferResume) {
         mTempConfig.setTo(getGlobalConfiguration());
         final int changes = mTempConfig.updateFrom(values);
@@ -22120,6 +22364,19 @@
                     UserHandle.USER_ALL);
         }
 
+        // Send a broadcast to PackageInstallers if the configuration change is interesting
+        // for the purposes of installing additional splits.
+        if (!initLocale && isSplitConfigurationChange(changes)) {
+            intent = new Intent(Intent.ACTION_SPLIT_CONFIGURATION_CHANGED);
+            intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING
+                    | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
+
+            // Typically only app stores will have this permission.
+            String[] permissions = new String[] { android.Manifest.permission.INSTALL_PACKAGES };
+            broadcastIntentLocked(null, null, intent, null, null, 0, null, null, permissions,
+                    OP_NONE, null, false, false, MY_PID, SYSTEM_UID, UserHandle.USER_ALL);
+        }
+
         // Override configuration of the default display duplicates global config, so we need to
         // update it also. This will also notify WindowManager about changes.
         performDisplayOverrideConfigUpdate(mStackSupervisor.getConfiguration(), deferResume,
@@ -22192,7 +22449,7 @@
                     // Override configuration of the default display duplicates global config, so
                     // we're calling global config update instead for default display. It will also
                     // apply the correct override config.
-                    changes = updateGlobalConfiguration(values, false /* initLocale */,
+                    changes = updateGlobalConfigurationLocked(values, false /* initLocale */,
                             false /* persistent */, UserHandle.USER_NULL /* userId */, deferResume);
                 } else {
                     changes = performDisplayOverrideConfigUpdate(values, deferResume, displayId);
@@ -23409,9 +23666,9 @@
     /**
      * Schedule PSS collection of a process.
      */
-    void requestPssLocked(ProcessRecord proc, int procState) {
+    boolean requestPssLocked(ProcessRecord proc, int procState) {
         if (mPendingPssProcesses.contains(proc)) {
-            return;
+            return false;
         }
         if (mPendingPssProcesses.size() == 0) {
             mBgHandler.sendEmptyMessage(COLLECT_PSS_BG_MSG);
@@ -23420,6 +23677,7 @@
         proc.pssProcState = procState;
         proc.pssStatType = ProcessStats.ADD_PSS_INTERNAL_SINGLE;
         mPendingPssProcesses.add(proc);
+        return true;
     }
 
     /**
@@ -23436,6 +23694,9 @@
         if (DEBUG_PSS) Slog.d(TAG_PSS, "Requesting pss of all procs!  memLowered=" + memLowered);
         mLastFullPssTime = now;
         mFullPssPending = true;
+        for (int i = mPendingPssProcesses.size() - 1; i >= 0; i--) {
+            ProcessList.abortNextPssTime(mPendingPssProcesses.get(i).procStateMemTracker);;
+        }
         mPendingPssProcesses.ensureCapacity(mLruProcesses.size());
         mPendingPssProcesses.clear();
         for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
@@ -23444,7 +23705,9 @@
                     || app.curProcState == ActivityManager.PROCESS_STATE_NONEXISTENT) {
                 continue;
             }
-            if (memLowered || now > (app.lastStateTime+ProcessList.PSS_ALL_INTERVAL)) {
+            if (memLowered || (always && now >
+                            app.lastStateTime+ProcessList.PSS_SAFE_TIME_FROM_STATE_CHANGE)
+                    || now > (app.lastStateTime+ProcessList.PSS_ALL_INTERVAL)) {
                 app.pssProcState = app.setProcState;
                 app.pssStatType = always ? ProcessStats.ADD_PSS_INTERNAL_ALL_POLL
                         : ProcessStats.ADD_PSS_INTERNAL_ALL_MEM;
@@ -23453,7 +23716,9 @@
                 mPendingPssProcesses.add(app);
             }
         }
-        mBgHandler.sendEmptyMessage(COLLECT_PSS_BG_MSG);
+        if (!mBgHandler.hasMessages(COLLECT_PSS_BG_MSG)) {
+            mBgHandler.sendEmptyMessage(COLLECT_PSS_BG_MSG);
+        }
     }
 
     public void setTestPssMode(boolean enabled) {
@@ -23811,7 +24076,7 @@
                 // Experimental code to more aggressively collect pss while
                 // running test...  the problem is that this tends to collect
                 // the data right when a process is transitioning between process
-                // states, which well tend to give noisy data.
+                // states, which will tend to give noisy data.
                 long start = SystemClock.uptimeMillis();
                 long startTime = SystemClock.currentThreadTimeMillis();
                 long pss = Debug.getPss(app.pid, mTmpLong, null);
@@ -23834,9 +24099,10 @@
             if (now > app.nextPssTime || (now > (app.lastPssTime+ProcessList.PSS_MAX_INTERVAL)
                     && now > (app.lastStateTime+ProcessList.minTimeFromStateChange(
                     mTestPssMode)))) {
-                requestPssLocked(app, app.setProcState);
-                app.nextPssTime = ProcessList.computeNextPssTime(app.curProcState,
-                        app.procStateMemTracker, mTestPssMode, isSleepingLocked(), now);
+                if (requestPssLocked(app, app.setProcState)) {
+                    app.nextPssTime = ProcessList.computeNextPssTime(app.curProcState,
+                            app.procStateMemTracker, mTestPssMode, isSleepingLocked(), now);
+                }
             } else if (false && DEBUG_PSS) Slog.d(TAG_PSS,
                     "Not requesting pss of " + app + ": next=" + (app.nextPssTime-now));
         }
@@ -24103,6 +24369,7 @@
         return applyOomAdjLocked(app, doingAll, now, SystemClock.elapsedRealtime());
     }
 
+    @GuardedBy("this")
     final void updateProcessForegroundLocked(ProcessRecord proc, boolean isForeground,
             boolean oomAdj) {
         if (isForeground != proc.foregroundServices) {
@@ -24172,6 +24439,7 @@
      *                  if necessary, or skip.
      * @return whether updateOomAdjLocked(app) was successful.
      */
+    @GuardedBy("this")
     final boolean updateOomAdjLocked(ProcessRecord app, boolean oomAdjAll) {
         final ActivityRecord TOP_ACT = resumedAppLocked();
         final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
@@ -24196,6 +24464,7 @@
         return success;
     }
 
+    @GuardedBy("this")
     final void updateOomAdjLocked() {
         final ActivityRecord TOP_ACT = resumedAppLocked();
         final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
@@ -24955,6 +25224,7 @@
     /**
      * Whitelists {@code targetUid} to temporarily bypass Power Save mode.
      */
+    @GuardedBy("this")
     void tempWhitelistForPendingIntentLocked(int callerPid, int callerUid, int targetUid,
             long duration, String tag) {
         if (DEBUG_WHITELISTS) {
@@ -24987,6 +25257,7 @@
     /**
      * Whitelists {@code targetUid} to temporarily bypass Power Save mode.
      */
+    @GuardedBy("this")
     void tempWhitelistUidLocked(int targetUid, long duration, String tag) {
         mPendingTempWhitelist.put(targetUid, new PendingTempWhitelist(targetUid, duration, tag));
         setUidTempWhitelistStateLocked(targetUid, true);
@@ -25026,6 +25297,7 @@
         }
     }
 
+    @GuardedBy("this")
     final void setAppIdTempWhitelistStateLocked(int appId, boolean onWhitelist) {
         boolean changed = false;
         for (int i=mActiveUids.size()-1; i>=0; i--) {
@@ -25040,6 +25312,7 @@
         }
     }
 
+    @GuardedBy("this")
     final void setUidTempWhitelistStateLocked(int uid, boolean onWhitelist) {
         boolean changed = false;
         final UidRecord uidRec = mActiveUids.get(uid);
@@ -25749,9 +26022,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 */);
             }
         }
 
@@ -26018,6 +26293,41 @@
         public boolean isCallerRecents(int callingUid) {
             return getRecentTasks().isCallerRecents(callingUid);
         }
+
+        @Override
+        public boolean isUidActive(int uid) {
+            synchronized (ActivityManagerService.this) {
+                final UidRecord uidRec = mActiveUids.get(uid);
+                return (uidRec != null) && !uidRec.idle;
+            }
+        }
+
+        @Override
+        public List<ProcessMemoryState> getMemoryStateForProcesses() {
+            List<ProcessMemoryState> processMemoryStates = new ArrayList<>();
+            synchronized (mPidsSelfLocked) {
+                for (int i = 0, size = mPidsSelfLocked.size(); i < size; i++) {
+                    final ProcessRecord r = mPidsSelfLocked.valueAt(i);
+                    final int pid = r.pid;
+                    final int uid = r.uid;
+                    final MemoryStat memoryStat = readMemoryStatFromMemcg(uid, pid);
+                    if (memoryStat == null) {
+                        continue;
+                    }
+                    ProcessMemoryState processMemoryState =
+                            new ProcessMemoryState(uid,
+                                    r.processName,
+                                    r.maxAdj,
+                                    memoryStat.pgfault,
+                                    memoryStat.pgmajfault,
+                                    memoryStat.rssInBytes,
+                                    memoryStat.cacheInBytes,
+                                    memoryStat.swapInBytes);
+                    processMemoryStates.add(processMemoryState);
+                }
+            }
+            return processMemoryStates;
+        }
     }
 
     /**
@@ -26350,4 +26660,20 @@
             }
         }
     }
+
+    @Override
+    public void registerRemoteAnimationForNextActivityStart(String packageName,
+            RemoteAnimationAdapter adapter) throws RemoteException {
+        enforceCallingPermission(CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS,
+                "registerRemoteAnimationForNextActivityStart");
+        synchronized (this) {
+            final long origId = Binder.clearCallingIdentity();
+            try {
+                mActivityStartController.registerRemoteAnimationForNextActivityStart(packageName,
+                        adapter);
+            } finally {
+                Binder.restoreCallingIdentity(origId);
+            }
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index 24a77c7..fa0df56 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -2608,7 +2608,7 @@
             pw.println("          specified then send to all users.");
             pw.println("      --receiver-permission <PERMISSION>: Require receiver to hold permission.");
             pw.println("  instrument [-r] [-e <NAME> <VALUE>] [-p <FILE>] [-w]");
-            pw.println("          [--user <USER_ID> | current]");
+            pw.println("          [--user <USER_ID> | current] [--no-hidden-api-checks]");
             pw.println("          [--no-window-animation] [--abi <ABI>] <COMPONENT>");
             pw.println("      Start an Instrumentation.  Typically this target <COMPONENT> is in the");
             pw.println("      form <TEST_PACKAGE>/<RUNNER_CLASS> or only <TEST_PACKAGE> if there");
@@ -2626,6 +2626,7 @@
             pw.println("          test runners.");
             pw.println("      --user <USER_ID> | current: Specify user instrumentation runs in;");
             pw.println("          current user if not specified.");
+            pw.println("      --no-hidden-api-checks: disable restrictions on use of hidden API.");
             pw.println("      --no-window-animation: turn off window animations while running.");
             pw.println("      --abi <ABI>: Launch the instrumented process with the selected ABI.");
             pw.println("          This assumes that the process supports the selected ABI.");
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/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index c023257..faafe72 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -133,11 +133,16 @@
 import android.app.PendingIntent;
 import android.app.PictureInPictureParams;
 import android.app.ResultInfo;
+import android.app.servertransaction.ActivityLifecycleItem;
+import android.app.servertransaction.ActivityRelaunchItem;
+import android.app.servertransaction.ClientTransaction;
+import android.app.servertransaction.ClientTransactionItem;
 import android.app.servertransaction.MoveToDisplayItem;
 import android.app.servertransaction.MultiWindowModeChangeItem;
 import android.app.servertransaction.NewIntentItem;
 import android.app.servertransaction.PauseActivityItem;
 import android.app.servertransaction.PipModeChangeItem;
+import android.app.servertransaction.ResumeActivityItem;
 import android.app.servertransaction.WindowVisibilityItem;
 import android.app.servertransaction.ActivityConfigurationChangeItem;
 import android.content.ComponentName;
@@ -378,7 +383,9 @@
     }
 
     String getLifecycleDescription(String reason) {
-        return "packageName=" + packageName + ", state=" + state + ", reason=" + reason;
+        return "name= " + this + ", component=" + intent.getComponent().flattenToShortString()
+                + ", package=" + packageName + ", state=" + state + ", reason=" + reason + ", time="
+                + System.currentTimeMillis();
     }
 
     void dump(PrintWriter pw, String prefix) {
@@ -2381,6 +2388,15 @@
 
         setLastReportedConfiguration(service.getGlobalConfiguration(), newMergedOverrideConfig);
 
+        if (state == INITIALIZING) {
+            // No need to relaunch or schedule new config for activity that hasn't been launched
+            // yet. We do, however, return after applying the config to activity record, so that
+            // it will use it for launch transaction.
+            if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
+                    "Skipping config check for initializing activity: " + this);
+            return true;
+        }
+
         if (changes == 0 && !forceNewConfig) {
             if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
                     "Configuration no differences in " + this);
@@ -2570,12 +2586,24 @@
                             + " callers=" + Debug.getCallers(6));
             forceNewConfig = false;
             mStackSupervisor.activityRelaunchingLocked(this);
-            app.thread.scheduleRelaunchActivity(appToken, pendingResults, pendingNewIntents,
-                    configChangeFlags, !andResume,
-                    new Configuration(service.getGlobalConfiguration()),
-                    new Configuration(getMergedOverrideConfiguration()), preserveWindow);
+            final ClientTransactionItem callbackItem = ActivityRelaunchItem.obtain(pendingResults,
+                    pendingNewIntents, configChangeFlags,
+                    new MergedConfiguration(service.getGlobalConfiguration(),
+                            getMergedOverrideConfiguration()),
+                    preserveWindow);
+            final ActivityLifecycleItem lifecycleItem;
+            if (andResume) {
+                lifecycleItem = ResumeActivityItem.obtain(service.isNextTransitionForward());
+            } else {
+                lifecycleItem = PauseActivityItem.obtain()
+                        .setDescription(getLifecycleDescription("relaunchActivityLocked"));
+            }
+            final ClientTransaction transaction = ClientTransaction.obtain(app.thread, appToken);
+            transaction.addCallback(callbackItem);
+            transaction.setLifecycleStateRequest(lifecycleItem);
+            service.mLifecycleManager.scheduleTransaction(transaction);
             // Note: don't need to call pauseIfSleepingLocked() here, because the caller will only
-            // pass in 'andResume' if this activity is currently resumed, which implies we aren't
+            // request resume if this activity is currently resumed, which implies we aren't
             // sleeping.
         } catch (RemoteException e) {
             if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG_SWITCH, "Relaunch failed", e);
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 4aa7594..33ba9b4 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -140,6 +140,7 @@
 import com.android.internal.app.ActivityTrigger;
 
 
+import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.app.IVoiceInteractor;
 import com.android.internal.os.BatteryStatsImpl;
@@ -1453,7 +1454,8 @@
 
                 mService.mLifecycleManager.scheduleTransaction(prev.app.thread, prev.appToken,
                         PauseActivityItem.obtain(prev.finishing, userLeaving,
-                                prev.configChangeFlags, pauseImmediately));
+                                prev.configChangeFlags, pauseImmediately).setDescription(
+                                        prev.getLifecycleDescription("startPausingLocked")));
             } catch (Exception e) {
                 // Ignore exception, if process died other code will cleanup.
                 Slog.w(TAG, "Exception thrown during pause", e);
@@ -1533,7 +1535,8 @@
                     if (r.finishing) {
                         if (DEBUG_PAUSE) Slog.v(TAG,
                                 "Executing finish of failed to pause activity: " + r);
-                        finishCurrentActivityLocked(r, FINISH_AFTER_VISIBLE, false);
+                        finishCurrentActivityLocked(r, FINISH_AFTER_VISIBLE, false,
+                                "activityPausedLocked");
                     }
                 }
             }
@@ -1550,7 +1553,8 @@
             prev.state = ActivityState.PAUSED;
             if (prev.finishing) {
                 if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Executing finish of activity: " + prev);
-                prev = finishCurrentActivityLocked(prev, FINISH_AFTER_VISIBLE, false);
+                prev = finishCurrentActivityLocked(prev, FINISH_AFTER_VISIBLE, false,
+                        "completedPausedLocked");
             } else if (prev.app != null) {
                 if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Enqueue pending stop if needed: " + prev
                         + " wasStopping=" + wasStopping + " visible=" + prev.visible);
@@ -2221,6 +2225,7 @@
      *       Use {@link ActivityStackSupervisor#resumeFocusedStackTopActivityLocked} to resume the
      *       right activity for the current system state.
      */
+    @GuardedBy("mService")
     boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
         if (mStackSupervisor.inResumeTopActivity) {
             // Don't even start recursing.
@@ -2260,6 +2265,7 @@
         mStackSupervisor.mRecentTasks.add(r.getTask());
     }
 
+    @GuardedBy("mService")
     private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
         if (!mService.mBooting && !mService.mBooted) {
             // Not ready yet!
@@ -3709,8 +3715,8 @@
 
                 final int finishMode = (r.visible || r.nowVisible) ? FINISH_AFTER_VISIBLE
                         : FINISH_AFTER_PAUSE;
-                final boolean removedActivity = finishCurrentActivityLocked(r, finishMode, oomAdj)
-                        == null;
+                final boolean removedActivity = finishCurrentActivityLocked(r, finishMode, oomAdj,
+                        "finishActivityLocked") == null;
 
                 // The following code is an optimization. When the last non-task overlay activity
                 // is removed from the task, we remove the entire task from the stack. However,
@@ -3751,7 +3757,8 @@
     static final int FINISH_AFTER_PAUSE = 1;
     static final int FINISH_AFTER_VISIBLE = 2;
 
-    final ActivityRecord finishCurrentActivityLocked(ActivityRecord r, int mode, boolean oomAdj) {
+    final ActivityRecord finishCurrentActivityLocked(ActivityRecord r, int mode, boolean oomAdj,
+            String reason) {
         // First things first: if this activity is currently visible,
         // and the resumed activity is not yet visible, then hold off on
         // finishing until the resumed one becomes visible.
@@ -3794,7 +3801,7 @@
                 || prevState == STOPPED
                 || prevState == ActivityState.INITIALIZING) {
             r.makeFinishingLocked();
-            boolean activityRemoved = destroyActivityLocked(r, true, "finish-imm");
+            boolean activityRemoved = destroyActivityLocked(r, true, "finish-imm:" + reason);
 
             if (finishingActivityInNonFocusedStack) {
                 // Finishing activity that was in paused state and it was in not currently focused
@@ -3830,7 +3837,8 @@
                     continue;
                 }
                 Slog.d(TAG, "finishAllActivitiesLocked: finishing " + r + " immediately");
-                finishCurrentActivityLocked(r, FINISH_IMMEDIATELY, false);
+                finishCurrentActivityLocked(r, FINISH_IMMEDIATELY, false,
+                        "finishAllActivitiesLocked");
             }
         }
         if (noActivitiesInStack) {
@@ -4253,7 +4261,8 @@
                 if (DEBUG_SWITCH) Slog.i(TAG_SWITCH, "Destroying: " + r);
                 mService.mLifecycleManager.scheduleTransaction(r.app.thread, r.appToken,
                         DestroyActivityItem.obtain(r.finishing, r.configChangeFlags)
-                            .setDescription(r.getLifecycleDescription("destroyActivityLocked")));
+                            .setDescription(
+                                    r.getLifecycleDescription("destroyActivityLocked:" + reason)));
             } catch (Exception e) {
                 // We can just ignore exceptions here...  if the process
                 // has crashed, our death notification will clean things
@@ -4917,7 +4926,8 @@
                             + r.intent.getComponent().flattenToShortString());
                     // Force the destroy to skip right to removal.
                     r.app = null;
-                    finishCurrentActivityLocked(r, FINISH_IMMEDIATELY, false);
+                    finishCurrentActivityLocked(r, FINISH_IMMEDIATELY, false,
+                            "handleAppCrashedLocked");
                 }
             }
         }
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index dfa8cca..bbf81d2 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -167,6 +167,7 @@
 import android.view.Display;
 import android.view.RemoteAnimationAdapter;
 
+import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.content.ReferrerIntent;
 import com.android.internal.os.logging.MetricsLoggerWrapper;
@@ -1458,7 +1459,8 @@
                     lifecycleItem = ResumeActivityItem.obtain(mService.isNextTransitionForward())
                             .setDescription(r.getLifecycleDescription("realStartActivityLocked"));
                 } else {
-                    lifecycleItem = PauseActivityItem.obtain();
+                    lifecycleItem = PauseActivityItem.obtain()
+                            .setDescription(r.getLifecycleDescription("realStartActivityLocked"));
                 }
                 clientTransaction.setLifecycleStateRequest(lifecycleItem);
 
@@ -1514,6 +1516,8 @@
             Slog.w(TAG, "Activity " + r + " being launched, but already in LRU list");
         }
 
+        // TODO(lifecycler): Resume or pause requests are done as part of launch transaction,
+        // so updating the state should be done accordingly.
         if (andResume && readyToResume()) {
             // As part of the process of launching, ActivityThread also performs
             // a resume.
@@ -1864,6 +1868,7 @@
      * Called when the frontmost task is idle.
      * @return the state of mService.mBooting before this was called.
      */
+    @GuardedBy("mService")
     private boolean checkFinishBootingLocked() {
         final boolean booting = mService.mBooting;
         boolean enableScreen = false;
@@ -1879,6 +1884,7 @@
     }
 
     // Checked.
+    @GuardedBy("mService")
     final ActivityRecord activityIdleInternalLocked(final IBinder token, boolean fromTimeout,
             boolean processPausingActivities, Configuration config) {
         if (DEBUG_ALL) Slog.v(TAG, "Activity idle: " + token);
@@ -1956,7 +1962,8 @@
             final ActivityStack stack = r.getStack();
             if (stack != null) {
                 if (r.finishing) {
-                    stack.finishCurrentActivityLocked(r, ActivityStack.FINISH_IMMEDIATELY, false);
+                    stack.finishCurrentActivityLocked(r, ActivityStack.FINISH_IMMEDIATELY, false,
+                            "activityIdleInternalLocked");
                 } else {
                     stack.stopActivityLocked(r);
                 }
@@ -4130,25 +4137,12 @@
             if (activityDisplay == null) {
                 return;
             }
-            final boolean destroyContentOnRemoval
-                    = activityDisplay.shouldDestroyContentOnRemove();
-            while (activityDisplay.getChildCount() > 0) {
-                final ActivityStack stack = activityDisplay.getChildAt(0);
-                if (destroyContentOnRemoval) {
-                    moveStackToDisplayLocked(stack.mStackId, DEFAULT_DISPLAY, false /* onTop */);
-                    stack.finishAllActivitiesLocked(true /* immediately */);
-                } else {
-                    // Moving all tasks to fullscreen stack, because it's guaranteed to be
-                    // a valid launch stack for all activities. This way the task history from
-                    // external display will be preserved on primary after move.
-                    moveTasksToFullscreenStackLocked(stack, true /* onTop */);
-                }
-            }
+
+            activityDisplay.remove();
 
             releaseSleepTokens(activityDisplay);
 
             mActivityDisplays.remove(displayId);
-            mWindowManager.onDisplayRemoved(displayId);
         }
     }
 
@@ -4575,7 +4569,7 @@
 
     int startActivityFromRecents(int callingPid, int callingUid, int taskId,
             SafeActivityOptions options) {
-        final TaskRecord task;
+        TaskRecord task = null;
         final String callingPackage;
         final Intent intent;
         final int userId;
@@ -4638,13 +4632,6 @@
                             targetActivity);
                 }
 
-                // If we are launching the task in the docked stack, put it into resizing mode so
-                // the window renders full-screen with the background filling the void. Also only
-                // call this at the end to make sure that tasks exists on the window manager side.
-                if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
-                    setResizingDuringAnimation(task);
-                }
-
                 mService.getActivityStartController().postStartActivityProcessingForLastStarter(
                         task.getTopActivity(), ActivityManager.START_TASK_TO_FRONT,
                         task.getStack());
@@ -4654,15 +4641,28 @@
             intent = task.intent;
             intent.addFlags(Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY);
             userId = task.userId;
-            int result = mService.getActivityStartController().startActivityInPackage(
+            return mService.getActivityStartController().startActivityInPackage(
                     task.mCallingUid, callingPid, callingUid, callingPackage, intent, null, null,
-                    null, 0, 0, options, userId, task,
-                    "startActivityFromRecents");
-            if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
-                setResizingDuringAnimation(task);
-            }
-            return result;
+                    null, 0, 0, options, userId, task, "startActivityFromRecents");
         } finally {
+            if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY && task != null) {
+                // If we are launching the task in the docked stack, put it into resizing mode so
+                // the window renders full-screen with the background filling the void. Also only
+                // call this at the end to make sure that tasks exists on the window manager side.
+                setResizingDuringAnimation(task);
+
+                final ActivityDisplay display = task.getStack().getDisplay();
+                final ActivityStack topSecondaryStack =
+                        display.getTopStackInWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
+                if (topSecondaryStack.isActivityTypeHome()) {
+                    // If the home activity if the top split-screen secondary stack, then the
+                    // primary split-screen stack is in the minimized mode which means it can't
+                    // receive input keys, so we should move the focused app to the home app so that
+                    // window manager can correctly calculate the focus window that can receive
+                    // input keys.
+                    moveHomeStackToFront("startActivityFromRecents: homeVisibleInSplitScreen");
+                }
+            }
             mWindowManager.continueSurfaceLayout();
         }
     }
diff --git a/services/core/java/com/android/server/am/ActivityStartController.java b/services/core/java/com/android/server/am/ActivityStartController.java
index 5551914..868f90d 100644
--- a/services/core/java/com/android/server/am/ActivityStartController.java
+++ b/services/core/java/com/android/server/am/ActivityStartController.java
@@ -41,6 +41,7 @@
 import android.os.Message;
 import android.provider.Settings;
 import android.util.Slog;
+import android.view.RemoteAnimationAdapter;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.server.am.ActivityStackSupervisor.PendingActivityLaunch;
@@ -85,6 +86,8 @@
 
     private final Handler mHandler;
 
+    private final PendingRemoteAnimationRegistry mPendingRemoteAnimationRegistry;
+
     private final class StartHandler extends Handler {
         public StartHandler(Looper looper) {
             super(looper, null, true);
@@ -123,6 +126,8 @@
         mHandler = new StartHandler(mService.mHandlerThread.getLooper());
         mFactory = factory;
         mFactory.setController(this);
+        mPendingRemoteAnimationRegistry = new PendingRemoteAnimationRegistry(service,
+                service.mHandler);
     }
 
     /**
@@ -245,11 +250,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);
@@ -385,6 +404,15 @@
         return mPendingActivityLaunches.size() < pendingLaunches;
     }
 
+    void registerRemoteAnimationForNextActivityStart(String packageName,
+            RemoteAnimationAdapter adapter) {
+        mPendingRemoteAnimationRegistry.addPendingAnimation(packageName, adapter);
+    }
+
+    PendingRemoteAnimationRegistry getPendingRemoteAnimationRegistry() {
+        return mPendingRemoteAnimationRegistry;
+    }
+
     void dump(PrintWriter pw, String prefix, String dumpPackage) {
         pw.print(prefix);
         pw.print("mLastHomeActivityStartResult=");
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index b061ba4..8205265 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -708,6 +708,8 @@
         ActivityOptions checkedOptions = options != null
                 ? options.getOptions(intent, aInfo, callerApp, mSupervisor)
                 : null;
+        checkedOptions = mService.getActivityStartController().getPendingRemoteAnimationRegistry()
+                .overrideOptionsIfNeeded(callingPackage, checkedOptions);
         if (mService.mController != null) {
             try {
                 // The Intent we give to the watcher has the extra data
@@ -790,7 +792,7 @@
         // Instead, launch the ephemeral installer. Once the installer is finished, it
         // starts either the intent we resolved here [on install error] or the ephemeral
         // app [on install success].
-        if (rInfo != null && rInfo.isInstantAppAvailable) {
+        if (rInfo != null && rInfo.auxiliaryInfo != null) {
             intent = createLaunchIntent(rInfo.auxiliaryInfo, ephemeralIntent,
                     callingPackage, verificationBundle, resolvedType, userId);
             resolvedType = null;
@@ -930,6 +932,7 @@
         // Don't modify the client's object!
         intent = new Intent(intent);
         if (componentSpecified
+                && !(Intent.ACTION_VIEW.equals(intent.getAction()) && intent.getData() == null)
                 && !Intent.ACTION_INSTALL_INSTANT_APP_PACKAGE.equals(intent.getAction())
                 && !Intent.ACTION_RESOLVE_INSTANT_APP_PACKAGE.equals(intent.getAction())
                 && mService.getPackageManagerInternalLocked()
diff --git a/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java b/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java
index 927b72c..1f10181 100644
--- a/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java
+++ b/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java
@@ -43,7 +43,10 @@
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 import java.util.concurrent.Future;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledFuture;
 import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
 
 /**
@@ -65,12 +68,13 @@
     // There is some accuracy error in wifi reports so allow some slop in the results.
     private static final long MAX_WIFI_STATS_SAMPLE_ERROR_MILLIS = 750;
 
-    private final ExecutorService mExecutorService = Executors.newSingleThreadExecutor(
-            (ThreadFactory) r -> {
-                Thread t = new Thread(r, "batterystats-worker");
-                t.setPriority(Thread.NORM_PRIORITY);
-                return t;
-            });
+    private final ScheduledExecutorService mExecutorService =
+            Executors.newSingleThreadScheduledExecutor(
+                    (ThreadFactory) r -> {
+                        Thread t = new Thread(r, "batterystats-worker");
+                        t.setPriority(Thread.NORM_PRIORITY);
+                        return t;
+                    });
 
     private final Context mContext;
     private final BatteryStatsImpl mStats;
@@ -85,8 +89,20 @@
     private String mCurrentReason = null;
 
     @GuardedBy("this")
+    private boolean mOnBattery;
+
+    @GuardedBy("this")
+    private boolean mOnBatteryScreenOff;
+
+    @GuardedBy("this")
+    private boolean mUseLatestStates = true;
+
+    @GuardedBy("this")
     private final IntArray mUidsToRemove = new IntArray();
 
+    @GuardedBy("this")
+    private Future<?> mWakelockChangesUpdate;
+
     private final Object mWorkerLock = new Object();
 
     @GuardedBy("mWorkerLock")
@@ -123,7 +139,8 @@
     }
 
     @Override
-    public Future<?> scheduleReadProcStateCpuTimes(boolean onBattery, boolean onBatteryScreenOff) {
+    public Future<?> scheduleReadProcStateCpuTimes(
+            boolean onBattery, boolean onBatteryScreenOff, long delayMillis) {
         synchronized (mStats) {
             if (!mStats.trackPerProcStateCpuTimes()) {
                 return null;
@@ -131,9 +148,10 @@
         }
         synchronized (BatteryExternalStatsWorker.this) {
             if (!mExecutorService.isShutdown()) {
-                return mExecutorService.submit(PooledLambda.obtainRunnable(
+                return mExecutorService.schedule(PooledLambda.obtainRunnable(
                         BatteryStatsImpl::updateProcStateCpuTimes,
-                        mStats, onBattery, onBatteryScreenOff).recycleOnUse());
+                        mStats, onBattery, onBatteryScreenOff).recycleOnUse(),
+                        delayMillis, TimeUnit.MILLISECONDS);
             }
         }
         return null;
@@ -157,6 +175,50 @@
         return null;
     }
 
+    @Override
+    public Future<?> scheduleCpuSyncDueToScreenStateChange(
+            boolean onBattery, boolean onBatteryScreenOff) {
+        synchronized (BatteryExternalStatsWorker.this) {
+            if (mCurrentFuture == null || (mUpdateFlags & UPDATE_CPU) == 0) {
+                mOnBattery = onBattery;
+                mOnBatteryScreenOff = onBatteryScreenOff;
+                mUseLatestStates = false;
+            }
+            return scheduleSyncLocked("screen-state", UPDATE_CPU);
+        }
+    }
+
+    @Override
+    public Future<?> scheduleCpuSyncDueToWakelockChange(long delayMillis) {
+        if (mExecutorService.isShutdown()) {
+            return CompletableFuture.failedFuture(new IllegalStateException("worker shutdown"));
+        }
+
+        if (mWakelockChangesUpdate != null) {
+            // If there's already a scheduled task, leave it as is if we're trying to re-schedule
+            // it again with a delay, otherwise cancel and re-schedule it.
+            if (delayMillis == 0) {
+                mWakelockChangesUpdate.cancel(false);
+            } else {
+                return mWakelockChangesUpdate;
+            }
+        }
+
+        mWakelockChangesUpdate = mExecutorService.schedule(() -> {
+            scheduleSync("wakelock-change", UPDATE_CPU);
+            scheduleRunnable(() -> mStats.postBatteryNeedsCpuUpdateMsg());
+            mWakelockChangesUpdate = null;
+        }, delayMillis, TimeUnit.MILLISECONDS);
+        return mWakelockChangesUpdate;
+    }
+
+    @Override
+    public void cancelCpuSyncDueToWakelockChange() {
+        if (mWakelockChangesUpdate != null) {
+            mWakelockChangesUpdate.cancel(false);
+        }
+    }
+
     public synchronized Future<?> scheduleWrite() {
         if (mExecutorService.isShutdown()) {
             return CompletableFuture.failedFuture(new IllegalStateException("worker shutdown"));
@@ -182,6 +244,7 @@
         mExecutorService.shutdownNow();
     }
 
+    @GuardedBy("this")
     private Future<?> scheduleSyncLocked(String reason, int flags) {
         if (mExecutorService.isShutdown()) {
             return CompletableFuture.failedFuture(new IllegalStateException("worker shutdown"));
@@ -203,14 +266,21 @@
             final int updateFlags;
             final String reason;
             final int[] uidsToRemove;
+            final boolean onBattery;
+            final boolean onBatteryScreenOff;
+            final boolean useLatestStates;
             synchronized (BatteryExternalStatsWorker.this) {
                 updateFlags = mUpdateFlags;
                 reason = mCurrentReason;
                 uidsToRemove = mUidsToRemove.size() > 0 ? mUidsToRemove.toArray() : EmptyArray.INT;
+                onBattery = mOnBattery;
+                onBatteryScreenOff = mOnBatteryScreenOff;
+                useLatestStates = mUseLatestStates;
                 mUpdateFlags = 0;
                 mCurrentReason = null;
                 mUidsToRemove.clear();
                 mCurrentFuture = null;
+                mUseLatestStates = true;
             }
 
             synchronized (mWorkerLock) {
@@ -218,7 +288,8 @@
                     Slog.d(TAG, "begin updateExternalStatsSync reason=" + reason);
                 }
                 try {
-                    updateExternalStatsLocked(reason, updateFlags);
+                    updateExternalStatsLocked(reason, updateFlags, onBattery,
+                            onBatteryScreenOff, useLatestStates);
                 } finally {
                     if (DEBUG) {
                         Slog.d(TAG, "end updateExternalStatsSync");
@@ -248,7 +319,9 @@
         }
     };
 
-    private void updateExternalStatsLocked(final String reason, int updateFlags) {
+    @GuardedBy("mWorkerLock")
+    private void updateExternalStatsLocked(final String reason, int updateFlags,
+            boolean onBattery, boolean onBatteryScreenOff, boolean useLatestStates) {
         // We will request data from external processes asynchronously, and wait on a timeout.
         SynchronousResultReceiver wifiReceiver = null;
         SynchronousResultReceiver bluetoothReceiver = null;
@@ -304,7 +377,14 @@
                     reason, 0);
 
             if ((updateFlags & UPDATE_CPU) != 0) {
-                mStats.updateCpuTimeLocked();
+                if (useLatestStates) {
+                    onBattery = mStats.isOnBatteryLocked();
+                    onBatteryScreenOff = mStats.isOnBatteryScreenOffLocked();
+                }
+                mStats.updateCpuTimeLocked(onBattery, onBatteryScreenOff);
+            }
+
+            if ((updateFlags & UPDATE_ALL) != 0) {
                 mStats.updateKernelWakelocksLocked();
                 mStats.updateKernelMemoryBandwidthLocked();
             }
@@ -372,6 +452,7 @@
         return null;
     }
 
+    @GuardedBy("mWorkerLock")
     private WifiActivityEnergyInfo extractDeltaLocked(WifiActivityEnergyInfo latest) {
         final long timePeriodMs = latest.mTimestamp - mLastInfo.mTimestamp;
         final long lastScanMs = mLastInfo.mControllerScanTimeMs;
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index ea52782..9d1adb2 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -1057,7 +1057,7 @@
         // to block such a low level service like BatteryService on external stats like WiFi.
         mWorker.scheduleRunnable(() -> {
             synchronized (mStats) {
-                final boolean onBattery = plugType == BatteryStatsImpl.BATTERY_PLUGGED_NONE;
+                final boolean onBattery = BatteryStatsImpl.isOnBattery(plugType, status);
                 if (mStats.isOnBattery() == onBattery) {
                     // The battery state has not changed, so we don't need to sync external
                     // stats immediately.
diff --git a/services/core/java/com/android/server/am/GlobalSettingsToPropertiesMapper.java b/services/core/java/com/android/server/am/GlobalSettingsToPropertiesMapper.java
index 9033b55..71fd71b 100644
--- a/services/core/java/com/android/server/am/GlobalSettingsToPropertiesMapper.java
+++ b/services/core/java/com/android/server/am/GlobalSettingsToPropertiesMapper.java
@@ -93,7 +93,7 @@
         }
         try {
             systemPropertiesSet(key, value);
-        } catch (IllegalArgumentException e) {
+        } catch (Exception e) {
             Slog.e(TAG, "Unable to set property " + key + " value '" + value + "'", e);
         }
     }
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..a2a84ec
--- /dev/null
+++ b/services/core/java/com/android/server/am/MemoryStatUtil.java
@@ -0,0 +1,111 @@
+/*
+ * 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.Locale;
+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.
+     */
+    @Nullable
+    static MemoryStat readMemoryStatFromMemcg(int uid, int pid) {
+        final String memoryStatPath = String.format(Locale.US, 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)
+    @Nullable
+    static 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/PendingRemoteAnimationRegistry.java b/services/core/java/com/android/server/am/PendingRemoteAnimationRegistry.java
new file mode 100644
index 0000000..77713f5
--- /dev/null
+++ b/services/core/java/com/android/server/am/PendingRemoteAnimationRegistry.java
@@ -0,0 +1,86 @@
+/*
+ * 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 android.annotation.Nullable;
+import android.app.ActivityOptions;
+import android.os.Handler;
+import android.util.ArrayMap;
+import android.view.RemoteAnimationAdapter;
+
+/**
+ * Registry to keep track of remote animations to be run for activity starts from a certain package.
+ *
+ * @see ActivityManagerService#registerRemoteAnimationForNextActivityStart
+ */
+class PendingRemoteAnimationRegistry {
+
+    private static final long TIMEOUT_MS = 3000;
+
+    private final ArrayMap<String, Entry> mEntries = new ArrayMap<>();
+    private final Handler mHandler;
+    private final ActivityManagerService mService;
+
+    PendingRemoteAnimationRegistry(ActivityManagerService service, Handler handler) {
+        mService = service;
+        mHandler = handler;
+    }
+
+    /**
+     * Adds a remote animation to be run for all activity starts originating from a certain package.
+     */
+    void addPendingAnimation(String packageName, RemoteAnimationAdapter adapter) {
+        mEntries.put(packageName, new Entry(packageName, adapter));
+    }
+
+    /**
+     * Overrides the activity options with a registered remote animation for a certain calling
+     * package if such a remote animation is registered.
+     */
+    ActivityOptions overrideOptionsIfNeeded(String callingPackage,
+            @Nullable ActivityOptions options) {
+        final Entry entry = mEntries.get(callingPackage);
+        if (entry == null) {
+            return options;
+        }
+        if (options == null) {
+            options = ActivityOptions.makeRemoteAnimation(entry.adapter);
+        } else {
+            options.setRemoteAnimationAdapter(entry.adapter);
+        }
+        mEntries.remove(callingPackage);
+        return options;
+    }
+
+    private class Entry {
+        final String packageName;
+        final RemoteAnimationAdapter adapter;
+
+        Entry(String packageName, RemoteAnimationAdapter adapter) {
+            this.packageName = packageName;
+            this.adapter = adapter;
+            mHandler.postDelayed(() -> {
+                synchronized (mService) {
+                    final Entry entry = mEntries.get(packageName);
+                    if (entry == this) {
+                        mEntries.remove(packageName);
+                    }
+                }
+            }, TIMEOUT_MS);
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/am/PersistentConnection.java b/services/core/java/com/android/server/am/PersistentConnection.java
index 52eaca1..c5edb26 100644
--- a/services/core/java/com/android/server/am/PersistentConnection.java
+++ b/services/core/java/com/android/server/am/PersistentConnection.java
@@ -220,6 +220,7 @@
         }
     }
 
+    @GuardedBy("mLock")
     public final void bindInnerLocked(boolean resetBackoff) {
         unscheduleRebindLocked();
 
@@ -260,6 +261,7 @@
         }
     }
 
+    @GuardedBy("mLock")
     private void cleanUpConnectionLocked() {
         mIsConnected = false;
         mService = null;
@@ -276,6 +278,7 @@
         }
     }
 
+    @GuardedBy("mLock")
     private final void unbindLocked() {
         unscheduleRebindLocked();
 
@@ -289,11 +292,13 @@
         cleanUpConnectionLocked();
     }
 
+    @GuardedBy("mLock")
     void unscheduleRebindLocked() {
         injectRemoveCallbacks(mBindForBackoffRunnable);
         mRebindScheduled = false;
     }
 
+    @GuardedBy("mLock")
     void scheduleRebindLocked() {
         unbindLocked();
 
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 08ee237..bf7aef9 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -501,19 +501,19 @@
     private static final int PSS_FIRST_CACHED_INTERVAL = 20*1000;
 
     // The amount of time until PSS when an important process stays in the same state.
-    private static final int PSS_SAME_PERSISTENT_INTERVAL = 20*60*1000;
+    private static final int PSS_SAME_PERSISTENT_INTERVAL = 10*60*1000;
 
     // The amount of time until PSS when the top process stays in the same state.
-    private static final int PSS_SAME_TOP_INTERVAL = 5*60*1000;
+    private static final int PSS_SAME_TOP_INTERVAL = 1*60*1000;
 
     // The amount of time until PSS when an important process stays in the same state.
-    private static final int PSS_SAME_IMPORTANT_INTERVAL = 15*60*1000;
+    private static final int PSS_SAME_IMPORTANT_INTERVAL = 10*60*1000;
 
     // The amount of time until PSS when a service process stays in the same state.
-    private static final int PSS_SAME_SERVICE_INTERVAL = 20*60*1000;
+    private static final int PSS_SAME_SERVICE_INTERVAL = 5*60*1000;
 
     // The amount of time until PSS when a cached process stays in the same state.
-    private static final int PSS_SAME_CACHED_INTERVAL = 20*60*1000;
+    private static final int PSS_SAME_CACHED_INTERVAL = 10*60*1000;
 
     // The amount of time until PSS when a persistent process first appears.
     private static final int PSS_FIRST_ASLEEP_PERSISTENT_INTERVAL = 1*60*1000;
@@ -622,16 +622,17 @@
 
     public static final class ProcStateMemTracker {
         final int[] mHighestMem = new int[PROC_MEM_NUM];
+        final float[] mScalingFactor = new float[PROC_MEM_NUM];
         int mTotalHighestMem = PROC_MEM_CACHED;
-        float mCurFactor = 1.0f;
 
         int mPendingMemState;
         int mPendingHighestMemState;
-        boolean mPendingSame;
+        float mPendingScalingFactor;
 
         public ProcStateMemTracker() {
             for (int i = PROC_MEM_PERSISTENT; i < PROC_MEM_NUM; i++) {
                 mHighestMem[i] = PROC_MEM_NUM;
+                mScalingFactor[i] = 1.0f;
             }
             mPendingMemState = -1;
         }
@@ -639,16 +640,22 @@
         public void dumpLine(PrintWriter pw) {
             pw.print("best=");
             pw.print(mTotalHighestMem);
-            pw.print(" ");
-            pw.print(mCurFactor);
-            pw.print("x (");
+            pw.print(" (");
+            boolean needSep = false;
             for (int i = 0; i < PROC_MEM_NUM; i++) {
-                if (i != 0) {
-                    pw.print(", ");
+                if (mHighestMem[i] < PROC_MEM_NUM) {
+                    if (needSep) {
+                        pw.print(", ");
+                        needSep = false;
+                    }
+                    pw.print(i);
+                    pw.print("=");
+                    pw.print(mHighestMem[i]);
+                    pw.print(" ");
+                    pw.print(mScalingFactor[i]);
+                    pw.print("x");
+                    needSep = true;
                 }
-                pw.print(i);
-                pw.print("=");
-                pw.print(mHighestMem[i]);
             }
             pw.print(")");
             if (mPendingMemState >= 0) {
@@ -656,8 +663,9 @@
                 pw.print(mPendingMemState);
                 pw.print(" highest=");
                 pw.print(mPendingHighestMemState);
-                pw.print(" same=");
-                pw.print(mPendingSame);
+                pw.print(" ");
+                pw.print(mPendingScalingFactor);
+                pw.print("x");
             }
             pw.println();
         }
@@ -674,12 +682,8 @@
     public static void commitNextPssTime(ProcStateMemTracker tracker) {
         if (tracker.mPendingMemState >= 0) {
             tracker.mHighestMem[tracker.mPendingMemState] = tracker.mPendingHighestMemState;
+            tracker.mScalingFactor[tracker.mPendingMemState] = tracker.mPendingScalingFactor;
             tracker.mTotalHighestMem = tracker.mPendingHighestMemState;
-            if (tracker.mPendingSame) {
-                tracker.mCurFactor *= 1.5f;
-            } else {
-                tracker.mCurFactor = 1;
-            }
             tracker.mPendingMemState = -1;
         }
     }
@@ -691,6 +695,7 @@
     public static long computeNextPssTime(int procState, ProcStateMemTracker tracker, boolean test,
             boolean sleeping, long now) {
         boolean first;
+        float scalingFactor;
         final int memState = sProcStateToProcMem[procState];
         if (tracker != null) {
             final int highestMemState = memState < tracker.mTotalHighestMem
@@ -698,9 +703,15 @@
             first = highestMemState < tracker.mHighestMem[memState];
             tracker.mPendingMemState = memState;
             tracker.mPendingHighestMemState = highestMemState;
-            tracker.mPendingSame = !first;
+            if (first) {
+                tracker.mPendingScalingFactor = scalingFactor = 1.0f;
+            } else {
+                scalingFactor = tracker.mScalingFactor[memState];
+                tracker.mPendingScalingFactor = scalingFactor * 1.5f;
+            }
         } else {
             first = true;
+            scalingFactor = 1.0f;
         }
         final long[] table = test
                 ? (first
@@ -709,8 +720,7 @@
                 : (first
                 ? (sleeping ? sFirstAsleepPssTimes : sFirstAwakePssTimes)
                 : (sleeping ? sSameAsleepPssTimes : sSameAwakePssTimes));
-        long delay = (long)(table[memState] * (tracker != null && !first
-                ? tracker.mCurFactor : 1.0f));
+        long delay = (long)(table[memState] * scalingFactor);
         if (delay > PSS_MAX_INTERVAL) {
             delay = PSS_MAX_INTERVAL;
         }
diff --git a/services/core/java/com/android/server/am/ProcessStatsService.java b/services/core/java/com/android/server/am/ProcessStatsService.java
index 8bf320e..c10d81b 100644
--- a/services/core/java/com/android/server/am/ProcessStatsService.java
+++ b/services/core/java/com/android/server/am/ProcessStatsService.java
@@ -135,6 +135,7 @@
         return mMemFactorLowered;
     }
 
+    @GuardedBy("mAm")
     public boolean setMemFactorLocked(int memFactor, boolean screenOn, long now) {
         mMemFactorLowered = memFactor < mLastMemOnlyState;
         mLastMemOnlyState = memFactor;
@@ -237,6 +238,7 @@
             if (commit) {
                 mProcessStats.resetSafely();
                 updateFile();
+                mAm.requestPssAllProcsLocked(SystemClock.uptimeMillis(), true, false);
             }
             mLastWriteTime = SystemClock.uptimeMillis();
             totalTime = SystemClock.uptimeMillis() - now;
@@ -784,12 +786,14 @@
                 } else if ("--reset".equals(arg)) {
                     synchronized (mAm) {
                         mProcessStats.resetSafely();
+                        mAm.requestPssAllProcsLocked(SystemClock.uptimeMillis(), true, false);
                         pw.println("Process stats reset.");
                         quit = true;
                     }
                 } else if ("--clear".equals(arg)) {
                     synchronized (mAm) {
                         mProcessStats.resetSafely();
+                        mAm.requestPssAllProcsLocked(SystemClock.uptimeMillis(), true, false);
                         ArrayList<String> files = getCommittedFiles(0, true, true);
                         if (files != null) {
                             for (int fi=0; fi<files.size(); fi++) {
diff --git a/services/core/java/com/android/server/am/RecentsAnimation.java b/services/core/java/com/android/server/am/RecentsAnimation.java
index e7b067b..6dcf041 100644
--- a/services/core/java/com/android/server/am/RecentsAnimation.java
+++ b/services/core/java/com/android/server/am/RecentsAnimation.java
@@ -20,6 +20,7 @@
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
 import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
 import static android.content.Intent.FLAG_ACTIVITY_NO_ANIMATION;
+import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
 import static android.view.WindowManager.TRANSIT_NONE;
 import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS;
 
@@ -27,6 +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;
@@ -61,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
@@ -70,13 +75,34 @@
 
     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);
@@ -92,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,
@@ -119,11 +140,9 @@
             // 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);
         }
     }
 
@@ -134,6 +153,8 @@
             if (mWindowManager.getRecentsAnimationController() == null) return;
 
             mWindowManager.inSurfaceTransaction(() -> {
+                Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER,
+                        "RecentsAnimation#onAnimationFinished_inSurfaceTransaction");
                 mWindowManager.deferSurfaceLayout();
                 try {
                     mWindowManager.cleanupRecentsAnimation();
@@ -167,8 +188,20 @@
                     mWindowManager.executeAppTransition();
                 } finally {
                     mWindowManager.continueSurfaceLayout();
+                    Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
                 }
             });
         }
     }
+
+    /**
+     * 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/UriPermission.java b/services/core/java/com/android/server/am/UriPermission.java
index 1e071aa..3bf1cf4 100644
--- a/services/core/java/com/android/server/am/UriPermission.java
+++ b/services/core/java/com/android/server/am/UriPermission.java
@@ -124,6 +124,10 @@
         updateModeFlags();
     }
 
+    boolean isNew() {
+        return persistedCreateTime == INVALID_TIME;
+    }
+
     void grantModes(int modeFlags, UriPermissionOwner owner) {
         final boolean persistable = (modeFlags & Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION) != 0;
         modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index 7b0c714..bfc787e 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -743,7 +743,7 @@
             mInjector.stackSupervisorRemoveUser(userId);
             // Remove the user if it is ephemeral.
             if (getUserInfo(userId).isEphemeral()) {
-                mInjector.getUserManager().removeUser(userId);
+                mInjector.getUserManager().removeUserEvenWhenDisallowed(userId);
             }
             // Evict the user's credential encryption key.
             try {
@@ -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/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 460fee3..34187bd9 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -23,6 +23,7 @@
 import static android.os.Process.FIRST_APPLICATION_UID;
 
 import android.Manifest;
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.ActivityManager;
 import android.app.ActivityManagerInternal;
@@ -69,6 +70,7 @@
 import android.media.AudioSystem;
 import android.media.IAudioFocusDispatcher;
 import android.media.IAudioRoutesObserver;
+import android.media.IAudioServerStateDispatcher;
 import android.media.IAudioService;
 import android.media.IPlaybackConfigDispatcher;
 import android.media.IRecordingConfigDispatcher;
@@ -240,6 +242,8 @@
     private static final int MSG_DYN_POLICY_MIX_STATE_UPDATE = 25;
     private static final int MSG_INDICATE_SYSTEM_READY = 26;
     private static final int MSG_ACCESSORY_PLUG_MEDIA_UNMUTE = 27;
+    private static final int MSG_NOTIFY_VOL_EVENT = 28;
+    private static final int MSG_DISPATCH_AUDIO_SERVER_STATE = 29;
     // start of messages handled under wakelock
     //   these messages can only be queued, i.e. sent with queueMsgUnderWakeLock(),
     //   and not with sendMsg(..., ..., SENDMSG_QUEUE, ...)
@@ -283,7 +287,7 @@
     private final int[][] SOUND_EFFECT_FILES_MAP = new int[AudioManager.NUM_SOUND_EFFECTS][2];
 
    /** Maximum volume index values for audio streams */
-    private static int[] MAX_STREAM_VOLUME = new int[] {
+    protected static int[] MAX_STREAM_VOLUME = new int[] {
         5,  // STREAM_VOICE_CALL
         7,  // STREAM_SYSTEM
         7,  // STREAM_RING
@@ -298,7 +302,7 @@
     };
 
     /** Minimum volume index values for audio streams */
-    private static int[] MIN_STREAM_VOLUME = new int[] {
+    protected static int[] MIN_STREAM_VOLUME = new int[] {
         1,  // STREAM_VOICE_CALL
         0,  // STREAM_SYSTEM
         0,  // STREAM_RING
@@ -388,6 +392,8 @@
             case AudioSystem.AUDIO_STATUS_SERVER_DIED:
                 sendMsg(mAudioHandler, MSG_AUDIO_SERVER_DIED,
                         SENDMSG_NOOP, 0, 0, null, 0);
+                sendMsg(mAudioHandler, MSG_DISPATCH_AUDIO_SERVER_STATE,
+                        SENDMSG_QUEUE, 0, 0, null, 0);
                 break;
             default:
                 break;
@@ -545,8 +551,6 @@
     // Used to play ringtones outside system_server
     private volatile IRingtonePlayer mRingtonePlayer;
 
-    private int mDeviceOrientation = Configuration.ORIENTATION_UNDEFINED;
-
     // Request to override default use of A2DP for media.
     private boolean mBluetoothA2dpEnabled;
     private final Object mBluetoothA2dpEnabledLock = new Object();
@@ -565,8 +569,6 @@
             AudioSystem.DEVICE_OUT_AUX_LINE;
     int mFullVolumeDevices = 0;
 
-    // TODO merge orientation and rotation
-    private final boolean mMonitorOrientation;
     private final boolean mMonitorRotation;
 
     private boolean mDockAudioMediaEnabled = true;
@@ -782,13 +784,6 @@
         intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
 
         intentFilter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
-        // TODO merge orientation and rotation
-        mMonitorOrientation = SystemProperties.getBoolean("ro.audio.monitorOrientation", false);
-        if (mMonitorOrientation) {
-            Log.v(TAG, "monitoring device orientation");
-            // initialize orientation in AudioSystem
-            setOrientationForAudioSystem();
-        }
         mMonitorRotation = SystemProperties.getBoolean("ro.audio.monitorRotation", false);
         if (mMonitorRotation) {
             RotationHelper.init(mContext, mAudioHandler);
@@ -957,10 +952,7 @@
         // Restore ringer mode
         setRingerModeInt(getRingerModeInternal(), false);
 
-        // Reset device orientation (if monitored for this device)
-        if (mMonitorOrientation) {
-            setOrientationForAudioSystem();
-        }
+        // Reset device rotation (if monitored for this device)
         if (mMonitorRotation) {
             RotationHelper.updateOrientation();
         }
@@ -998,6 +990,21 @@
         onIndicateSystemReady();
         // indicate the end of reconfiguration phase to audio HAL
         AudioSystem.setParameters("restarting=false");
+
+        sendMsg(mAudioHandler, MSG_DISPATCH_AUDIO_SERVER_STATE,
+                SENDMSG_QUEUE, 1, 0, null, 0);
+    }
+
+    private void onDispatchAudioServerStateChange(boolean state) {
+        synchronized (mAudioServerStateListeners) {
+            for (AsdProxy asdp : mAudioServerStateListeners.values()) {
+                try {
+                    asdp.callback().dispatchAudioServerStateChange(state);
+                } catch (RemoteException e) {
+                    Log.w(TAG, "Could not call dispatchAudioServerStateChange()", e);
+                }
+            }
+        }
     }
 
     private void createAudioSystemThread() {
@@ -1021,14 +1028,16 @@
     }
 
     private void checkAllAliasStreamVolumes() {
-        synchronized (VolumeStreamState.class) {
-            int numStreamTypes = AudioSystem.getNumStreamTypes();
-            for (int streamType = 0; streamType < numStreamTypes; streamType++) {
-                mStreamStates[streamType]
-                        .setAllIndexes(mStreamStates[mStreamVolumeAlias[streamType]], TAG);
-                // apply stream volume
-                if (!mStreamStates[streamType].mIsMuted) {
-                    mStreamStates[streamType].applyAllVolumes();
+        synchronized (mSettingsLock) {
+            synchronized (VolumeStreamState.class) {
+                int numStreamTypes = AudioSystem.getNumStreamTypes();
+                for (int streamType = 0; streamType < numStreamTypes; streamType++) {
+                    mStreamStates[streamType]
+                            .setAllIndexes(mStreamStates[mStreamVolumeAlias[streamType]], TAG);
+                    // apply stream volume
+                    if (!mStreamStates[streamType].mIsMuted) {
+                        mStreamStates[streamType].applyAllVolumes();
+                    }
                 }
             }
         }
@@ -1134,13 +1143,16 @@
         if (updateVolumes && mStreamStates != null) {
             updateDefaultVolumes();
 
-            mStreamStates[AudioSystem.STREAM_DTMF].setAllIndexes(mStreamStates[dtmfStreamAlias],
-                    caller);
-
-            mStreamStates[AudioSystem.STREAM_ACCESSIBILITY].mVolumeIndexSettingName =
-                    System.VOLUME_SETTINGS_INT[a11yStreamAlias];
-            mStreamStates[AudioSystem.STREAM_ACCESSIBILITY].setAllIndexes(
-                    mStreamStates[a11yStreamAlias], caller);
+            synchronized (mSettingsLock) {
+                synchronized (VolumeStreamState.class) {
+                    mStreamStates[AudioSystem.STREAM_DTMF]
+                            .setAllIndexes(mStreamStates[dtmfStreamAlias], caller);
+                    mStreamStates[AudioSystem.STREAM_ACCESSIBILITY].mVolumeIndexSettingName =
+                            System.VOLUME_SETTINGS_INT[a11yStreamAlias];
+                    mStreamStates[AudioSystem.STREAM_ACCESSIBILITY].setAllIndexes(
+                            mStreamStates[a11yStreamAlias], caller);
+                }
+            }
             if (sIndependentA11yVolume) {
                 // restore the a11y values from the settings
                 mStreamStates[AudioSystem.STREAM_ACCESSIBILITY].readSettings();
@@ -1334,11 +1346,9 @@
             extVolCtlr = mExtVolumeController;
         }
         if (extVolCtlr != null) {
-            try {
-                mExtVolumeController.notifyVolumeAdjust(direction);
-            } catch(RemoteException e) {
-                // nothing we can do about this. Do not log error, too much potential for spam
-            }
+            sendMsg(mAudioHandler, MSG_NOTIFY_VOL_EVENT, SENDMSG_QUEUE,
+                    direction, 0 /*ignored*/,
+                    extVolCtlr, 0 /*delay*/);
         } else {
             adjustSuggestedStreamVolume(direction, suggestedStreamType, flags, callingPackage,
                     caller, Binder.getCallingUid());
@@ -1412,7 +1422,7 @@
                 Binder.getCallingUid());
     }
 
-    private void adjustStreamVolume(int streamType, int direction, int flags,
+    protected void adjustStreamVolume(int streamType, int direction, int flags,
             String callingPackage, String caller, int uid) {
         if (mUseFixedVolume) {
             return;
@@ -4587,39 +4597,36 @@
          * @param srcStream
          * @param caller
          */
+        // must be sync'd on mSettingsLock before VolumeStreamState.class
+        @GuardedBy("VolumeStreamState.class")
         public void setAllIndexes(VolumeStreamState srcStream, String caller) {
             if (mStreamType == srcStream.mStreamType) {
                 return;
             }
-            synchronized (mSettingsLock) {
-                synchronized (VolumeStreamState.class) {
-                    int srcStreamType = srcStream.getStreamType();
-                    // apply default device volume from source stream to all devices first in case
-                    // some devices are present in this stream state but not in source stream state
-                    int index = srcStream.getIndex(AudioSystem.DEVICE_OUT_DEFAULT);
-                    index = rescaleIndex(index, srcStreamType, mStreamType);
-                    for (int i = 0; i < mIndexMap.size(); i++) {
-                        mIndexMap.put(mIndexMap.keyAt(i), index);
-                    }
-                    // Now apply actual volume for devices in source stream state
-                    SparseIntArray srcMap = srcStream.mIndexMap;
-                    for (int i = 0; i < srcMap.size(); i++) {
-                        int device = srcMap.keyAt(i);
-                        index = srcMap.valueAt(i);
-                        index = rescaleIndex(index, srcStreamType, mStreamType);
+            int srcStreamType = srcStream.getStreamType();
+            // apply default device volume from source stream to all devices first in case
+            // some devices are present in this stream state but not in source stream state
+            int index = srcStream.getIndex(AudioSystem.DEVICE_OUT_DEFAULT);
+            index = rescaleIndex(index, srcStreamType, mStreamType);
+            for (int i = 0; i < mIndexMap.size(); i++) {
+                mIndexMap.put(mIndexMap.keyAt(i), index);
+            }
+            // Now apply actual volume for devices in source stream state
+            SparseIntArray srcMap = srcStream.mIndexMap;
+            for (int i = 0; i < srcMap.size(); i++) {
+                int device = srcMap.keyAt(i);
+                index = srcMap.valueAt(i);
+                index = rescaleIndex(index, srcStreamType, mStreamType);
 
-                        setIndex(index, device, caller);
-                    }
-                }
+                setIndex(index, device, caller);
             }
         }
 
-        @GuardedBy("mSettingsLock")
+        // must be sync'd on mSettingsLock before VolumeStreamState.class
+        @GuardedBy("VolumeStreamState.class")
         public void setAllIndexesToMax() {
-            synchronized (VolumeStreamState.class) {
-                for (int i = 0; i < mIndexMap.size(); i++) {
-                    mIndexMap.put(mIndexMap.keyAt(i), mIndexMax);
-                }
+            for (int i = 0; i < mIndexMap.size(); i++) {
+                mIndexMap.put(mIndexMap.keyAt(i), mIndexMax);
             }
         }
 
@@ -5056,6 +5063,15 @@
                     state);
         }
 
+        private void onNotifyVolumeEvent(@NonNull IAudioPolicyCallback apc,
+                @AudioManager.VolumeAdjustment int direction) {
+            try {
+                apc.notifyVolumeAdjust(direction);
+            } catch(Exception e) {
+                // nothing we can do about this. Do not log error, too much potential for spam
+            }
+        }
+
         @Override
         public void handleMessage(Message msg) {
             switch (msg.what) {
@@ -5082,6 +5098,10 @@
                     onAudioServerDied();
                     break;
 
+                case MSG_DISPATCH_AUDIO_SERVER_STATE:
+                    onDispatchAudioServerStateChange(msg.arg1 == 1);
+                    break;
+
                 case MSG_UNLOAD_SOUND_EFFECTS:
                     onUnloadSoundEffects();
                     break;
@@ -5218,6 +5238,10 @@
                 case MSG_DYN_POLICY_MIX_STATE_UPDATE:
                     onDynPolicyMixStateUpdate((String) msg.obj, msg.arg1);
                     break;
+
+                case MSG_NOTIFY_VOL_EVENT:
+                    onNotifyVolumeEvent((IAudioPolicyCallback) msg.obj, msg.arg1);
+                    break;
             }
         }
     }
@@ -6158,24 +6182,15 @@
     // Device orientation
     //==========================================================================================
     /**
-     * Handles device configuration changes that may map to a change in the orientation
-     * or orientation.
-     * Monitoring orientation and rotation is optional, and is defined by the definition and value
-     * of the "ro.audio.monitorOrientation" and "ro.audio.monitorRotation" system properties.
+     * Handles device configuration changes that may map to a change in rotation.
+     * Monitoring rotation is optional, and is defined by the definition and value
+     * of the "ro.audio.monitorRotation" system property.
      */
     private void handleConfigurationChanged(Context context) {
         try {
-            // reading new orientation "safely" (i.e. under try catch) in case anything
-            // goes wrong when obtaining resources and configuration
+            // reading new configuration "safely" (i.e. under try catch) in case anything
+            // goes wrong.
             Configuration config = context.getResources().getConfiguration();
-            // TODO merge rotation and orientation
-            if (mMonitorOrientation) {
-                int newOrientation = config.orientation;
-                if (newOrientation != mDeviceOrientation) {
-                    mDeviceOrientation = newOrientation;
-                    setOrientationForAudioSystem();
-                }
-            }
             sendMsg(mAudioHandler,
                     MSG_CONFIGURE_SAFE_MEDIA_VOLUME,
                     SENDMSG_REPLACE,
@@ -6190,15 +6205,17 @@
                 mCameraSoundForced = cameraSoundForced;
                 if (cameraSoundForcedChanged) {
                     if (!mIsSingleVolume) {
-                        VolumeStreamState s = mStreamStates[AudioSystem.STREAM_SYSTEM_ENFORCED];
-                        if (cameraSoundForced) {
-                            s.setAllIndexesToMax();
-                            mRingerModeAffectedStreams &=
-                                    ~(1 << AudioSystem.STREAM_SYSTEM_ENFORCED);
-                        } else {
-                            s.setAllIndexes(mStreamStates[AudioSystem.STREAM_SYSTEM], TAG);
-                            mRingerModeAffectedStreams |=
-                                    (1 << AudioSystem.STREAM_SYSTEM_ENFORCED);
+                        synchronized (VolumeStreamState.class) {
+                            VolumeStreamState s = mStreamStates[AudioSystem.STREAM_SYSTEM_ENFORCED];
+                            if (cameraSoundForced) {
+                                s.setAllIndexesToMax();
+                                mRingerModeAffectedStreams &=
+                                        ~(1 << AudioSystem.STREAM_SYSTEM_ENFORCED);
+                            } else {
+                                s.setAllIndexes(mStreamStates[AudioSystem.STREAM_SYSTEM], TAG);
+                                mRingerModeAffectedStreams |=
+                                        (1 << AudioSystem.STREAM_SYSTEM_ENFORCED);
+                            }
                         }
                         // take new state into account for streams muted by ringer mode
                         setRingerModeInt(getRingerModeInternal(), false);
@@ -6227,30 +6244,6 @@
         }
     }
 
-    //TODO move to an external "orientation helper" class
-    private void setOrientationForAudioSystem() {
-        switch (mDeviceOrientation) {
-            case Configuration.ORIENTATION_LANDSCAPE:
-                //Log.i(TAG, "orientation is landscape");
-                AudioSystem.setParameters("orientation=landscape");
-                break;
-            case Configuration.ORIENTATION_PORTRAIT:
-                //Log.i(TAG, "orientation is portrait");
-                AudioSystem.setParameters("orientation=portrait");
-                break;
-            case Configuration.ORIENTATION_SQUARE:
-                //Log.i(TAG, "orientation is square");
-                AudioSystem.setParameters("orientation=square");
-                break;
-            case Configuration.ORIENTATION_UNDEFINED:
-                //Log.i(TAG, "orientation is undefined");
-                AudioSystem.setParameters("orientation=undefined");
-                break;
-            default:
-                Log.e(TAG, "Unknown orientation");
-        }
-    }
-
     // Handles request to override default use of A2DP for media.
     // Must be called synchronized on mConnectedDevices
     public void setBluetoothA2dpOnInt(boolean on, String eventSource) {
@@ -7330,6 +7323,77 @@
 
 
     //======================
+    // Audioserver state displatch
+    //======================
+    private class AsdProxy implements IBinder.DeathRecipient {
+        private final IAudioServerStateDispatcher mAsd;
+
+        AsdProxy(IAudioServerStateDispatcher asd) {
+            mAsd = asd;
+        }
+
+        public void binderDied() {
+            synchronized (mAudioServerStateListeners) {
+                mAudioServerStateListeners.remove(mAsd.asBinder());
+            }
+        }
+
+        IAudioServerStateDispatcher callback() {
+            return mAsd;
+        }
+    }
+
+    private HashMap<IBinder, AsdProxy> mAudioServerStateListeners =
+            new HashMap<IBinder, AsdProxy>();
+
+    private void checkMonitorAudioServerStatePermission() {
+        if (!(mContext.checkCallingOrSelfPermission(
+                    android.Manifest.permission.MODIFY_PHONE_STATE) ==
+                PackageManager.PERMISSION_GRANTED ||
+              mContext.checkCallingOrSelfPermission(
+                    android.Manifest.permission.MODIFY_AUDIO_ROUTING) ==
+                PackageManager.PERMISSION_GRANTED)) {
+            throw new SecurityException("Not allowed to monitor audioserver state");
+        }
+    }
+
+    public void registerAudioServerStateDispatcher(IAudioServerStateDispatcher asd) {
+        checkMonitorAudioServerStatePermission();
+        synchronized (mAudioServerStateListeners) {
+            if (mAudioServerStateListeners.containsKey(asd.asBinder())) {
+                Slog.w(TAG, "Cannot re-register audio server state dispatcher");
+                return;
+            }
+            AsdProxy asdp = new AsdProxy(asd);
+            try {
+                asd.asBinder().linkToDeath(asdp, 0/*flags*/);
+            } catch (RemoteException e) {
+
+            }
+            mAudioServerStateListeners.put(asd.asBinder(), asdp);
+        }
+    }
+
+    public void unregisterAudioServerStateDispatcher(IAudioServerStateDispatcher asd) {
+        checkMonitorAudioServerStatePermission();
+        synchronized (mAudioServerStateListeners) {
+            AsdProxy asdp = mAudioServerStateListeners.remove(asd.asBinder());
+            if (asdp == null) {
+                Slog.w(TAG, "Trying to unregister unknown audioserver state dispatcher for pid "
+                        + Binder.getCallingPid() + " / uid " + Binder.getCallingUid());
+                return;
+            } else {
+                asd.asBinder().unlinkToDeath(asdp, 0/*flags*/);
+            }
+        }
+    }
+
+    public boolean isAudioServerRunning() {
+        checkMonitorAudioServerStatePermission();
+        return (AudioSystem.checkAudioFlinger() == AudioSystem.AUDIO_STATUS_OK);
+    }
+
+    //======================
     // misc
     //======================
     private HashMap<IBinder, AudioPolicyProxy> mAudioPolicies =
diff --git a/services/core/java/com/android/server/audio/OWNERS b/services/core/java/com/android/server/audio/OWNERS
new file mode 100644
index 0000000..b70de29
--- /dev/null
+++ b/services/core/java/com/android/server/audio/OWNERS
@@ -0,0 +1,2 @@
+jmtrivi@google.com
+elaurent@google.com
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..2a9d386 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/car/CarServiceHelperService.java b/services/core/java/com/android/server/car/CarServiceHelperService.java
deleted file mode 100644
index 9392a6a..0000000
--- a/services/core/java/com/android/server/car/CarServiceHelperService.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.car;
-
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.ServiceConnection;
-import android.os.Binder;
-import android.os.IBinder;
-import android.os.Parcel;
-import android.os.RemoteException;
-import android.os.UserHandle;
-import android.util.Slog;
-
-import com.android.internal.car.ICarServiceHelper;
-import com.android.server.SystemService;
-
-/**
- * System service side companion service for CarService.
- * Starts car service and provide necessary API for CarService. Only for car product.
- */
-public class CarServiceHelperService extends SystemService {
-    private static final String TAG = "CarServiceHelper";
-    private static final String CAR_SERVICE_INTERFACE = "android.car.ICar";
-    private final ICarServiceHelperImpl mHelper = new ICarServiceHelperImpl();
-    private IBinder mCarService;
-    private final ServiceConnection mCarServiceConnection = new ServiceConnection() {
-
-        @Override
-        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
-            Slog.i(TAG, "**CarService connected**");
-            mCarService = iBinder;
-            // Cannot depend on ICar which is defined in CarService, so handle binder call directly
-            // instead.
-            // void setCarServiceHelper(in IBinder helper)
-            Parcel data = Parcel.obtain();
-            data.writeInterfaceToken(CAR_SERVICE_INTERFACE);
-            data.writeStrongBinder(mHelper.asBinder());
-            try {
-                mCarService.transact(IBinder.FIRST_CALL_TRANSACTION, // setCarServiceHelper
-                        data, null, Binder.FLAG_ONEWAY);
-            } catch (RemoteException e) {
-                Slog.w(TAG, "RemoteException from car service", e);
-                handleCarServiceCrash();
-            }
-        }
-
-        @Override
-        public void onServiceDisconnected(ComponentName componentName) {
-            handleCarServiceCrash();
-        }
-    };
-
-    public CarServiceHelperService(Context context) {
-        super(context);
-    }
-
-    @Override
-    public void onStart() {
-        Intent intent = new Intent();
-        intent.setPackage("com.android.car");
-        intent.setAction(CAR_SERVICE_INTERFACE);
-        if (!getContext().bindServiceAsUser(intent, mCarServiceConnection, Context.BIND_AUTO_CREATE,
-                UserHandle.SYSTEM)) {
-            Slog.wtf(TAG, "cannot start car service");
-        }
-    }
-
-    private void handleCarServiceCrash() {
-        //TODO define recovery bahavior
-    }
-
-    private class ICarServiceHelperImpl extends ICarServiceHelper.Stub {
-        //TODO
-    }
-}
diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
index 85b70ca..14b234d 100644
--- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
+++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
@@ -285,7 +285,6 @@
         int delta = add ? +1 : -1;
         switch (request.type) {
             case REQUEST:
-            case TRACK_DEFAULT:
                 mNumRequestNetworkRequests += delta;
                 break;
 
@@ -294,6 +293,7 @@
                 mNumBackgroundNetworkRequests += delta;
                 break;
 
+            case TRACK_DEFAULT:
             case LISTEN:
                 break;
 
@@ -392,6 +392,15 @@
         return !isVPN() && numForegroundNetworkRequests() == 0 && mNumBackgroundNetworkRequests > 0;
     }
 
+    /**
+     * Returns whether this network is currently suspended. A network is suspended if it is still
+     * connected but data temporarily fails to transfer. See {@link NetworkInfo.State#SUSPENDED}
+     * and {@link NetworkCapabilities#NET_CAPABILITY_NOT_SUSPENDED}.
+     */
+    public boolean isSuspended() {
+        return networkInfo.getState() == NetworkInfo.State.SUSPENDED;
+    }
+
     // Does this network satisfy request?
     public boolean satisfies(NetworkRequest request) {
         return created &&
@@ -458,7 +467,7 @@
 
     public NetworkState getNetworkState() {
         synchronized (this) {
-            // Network objects are outwardly immutable so there is no point to duplicating.
+            // Network objects are outwardly immutable so there is no point in duplicating.
             // Duplicating also precludes sharing socket factories and connection pools.
             final String subscriberId = (networkMisc != null) ? networkMisc.subscriberId : null;
             return new NetworkState(new NetworkInfo(networkInfo),
diff --git a/services/core/java/com/android/server/content/ContentService.java b/services/core/java/com/android/server/content/ContentService.java
index 1ee0548..63308f8 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_ACTIVITY_MANAGER_READY:
+                getSyncManager();
+                break;
+        }
+        if (mSyncManager != null) {
+            mSyncManager.onBootPhase(phase);
+        }
     }
 
     /**
@@ -1116,6 +1121,7 @@
         return (pi != null) ? pi.packageName : null;
     }
 
+    @GuardedBy("mCache")
     private ArrayMap<Pair<String, Uri>, Bundle> findOrCreateCacheLocked(int userId,
             String providerPackageName) {
         ArrayMap<String, ArrayMap<Pair<String, Uri>, Bundle>> userCache = mCache.get(userId);
@@ -1131,6 +1137,7 @@
         return packageCache;
     }
 
+    @GuardedBy("mCache")
     private void invalidateCacheLocked(int userId, String providerPackageName, Uri uri) {
         ArrayMap<String, ArrayMap<Pair<String, Uri>, Bundle>> userCache = mCache.get(userId);
         if (userCache == null) return;
diff --git a/services/core/java/com/android/server/content/SyncJobService.java b/services/core/java/com/android/server/content/SyncJobService.java
index 51499f7..9980930 100644
--- a/services/core/java/com/android/server/content/SyncJobService.java
+++ b/services/core/java/com/android/server/content/SyncJobService.java
@@ -137,11 +137,13 @@
                             + " params=" + jobParametersToString(params));
                 }
             } else if (runtime < 10 * 1000) {
-                // Job stopped too soon. WTF.
-                wtf("Job " + jobId + " stopped in " + runtime + " ms: "
-                        + " startUptime=" + startUptime
-                        + " nowUptime=" + nowUptime
-                        + " params=" + jobParametersToString(params));
+                // This happens too in a normal case too, and it's rather too often.
+                // Disable it for now.
+//                // Job stopped too soon. WTF.
+//                wtf("Job " + jobId + " stopped in " + runtime + " ms: "
+//                        + " startUptime=" + startUptime
+//                        + " nowUptime=" + nowUptime
+//                        + " params=" + jobParametersToString(params));
             }
 
             mStartedSyncs.delete(jobId);
diff --git a/services/core/java/com/android/server/content/SyncLogger.java b/services/core/java/com/android/server/content/SyncLogger.java
index 75c0181..20aec7e 100644
--- a/services/core/java/com/android/server/content/SyncLogger.java
+++ b/services/core/java/com/android/server/content/SyncLogger.java
@@ -194,6 +194,7 @@
             }
         }
 
+        @GuardedBy("mLock")
         private void openLogLocked(long now) {
             // If we already have a log file opened and the date has't changed, just use it.
             final long day = now % DateUtils.DAY_IN_MILLIS;
@@ -219,6 +220,7 @@
             }
         }
 
+        @GuardedBy("mLock")
         private void closeCurrentLogLocked() {
             IoUtils.closeQuietly(mLogWriter);
             mLogWriter = null;
diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
index de17ec7..7089268 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_ACTIVITY_MANAGER_READY and after.
+        switch (phase) {
+            case SystemService.PHASE_ACTIVITY_MANAGER_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) {
@@ -2076,8 +2078,33 @@
     protected void dumpSyncState(PrintWriter pw) {
         final StringBuilder sb = new StringBuilder();
 
-        pw.print("data connected: "); pw.println(mDataConnectionIsConnected);
-        pw.print("auto sync: ");
+        pw.print("Data connected: "); pw.println(mDataConnectionIsConnected);
+        pw.print("Battery saver: ");
+        pw.println((mPowerManager != null) && mPowerManager.isPowerSaveMode());
+
+        pw.print("Background network restriction: ");
+        {
+            final ConnectivityManager cm = getConnectivityManager();
+            final int status = (cm == null) ? -1 : cm.getRestrictBackgroundStatus();
+            switch (status) {
+                case ConnectivityManager.RESTRICT_BACKGROUND_STATUS_DISABLED:
+                    pw.println(" disabled");
+                    break;
+                case ConnectivityManager.RESTRICT_BACKGROUND_STATUS_WHITELISTED:
+                    pw.println(" whitelisted");
+                    break;
+                case ConnectivityManager.RESTRICT_BACKGROUND_STATUS_ENABLED:
+                    pw.println(" enabled");
+                    break;
+                default:
+                    pw.print("Unknown(");
+                    pw.print(status);
+                    pw.println(")");
+                    break;
+            }
+        }
+
+        pw.print("Auto sync: ");
         List<UserInfo> users = getAllUsers();
         if (users != null) {
             for (UserInfo user : users) {
@@ -2086,26 +2113,26 @@
             }
             pw.println();
         }
-        pw.print("memory low: "); pw.println(mStorageIsLow);
-        pw.print("device idle: "); pw.println(mDeviceIsIdle);
-        pw.print("reported active: "); pw.println(mReportedSyncActive);
+        pw.print("Memory low: "); pw.println(mStorageIsLow);
+        pw.print("Device idle: "); pw.println(mDeviceIsIdle);
+        pw.print("Reported active: "); pw.println(mReportedSyncActive);
 
         final AccountAndUser[] accounts = AccountManagerService.getSingleton().getAllAccounts();
 
-        pw.print("accounts: ");
+        pw.print("Accounts: ");
         if (accounts != INITIAL_ACCOUNTS_ARRAY) {
             pw.println(accounts.length);
         } else {
             pw.println("not known yet");
         }
         final long now = SystemClock.elapsedRealtime();
-        pw.print("now: "); pw.print(now);
+        pw.print("Now: "); pw.print(now);
         pw.println(" (" + formatTime(System.currentTimeMillis()) + ")");
 
         sb.setLength(0);
-        pw.print("uptime: "); pw.print(formatDurationHMS(sb, now));
+        pw.print("Uptime: "); pw.print(formatDurationHMS(sb, now));
         pw.println();
-        pw.print("time spent syncing: ");
+        pw.print("Time spent syncing: ");
 
         sb.setLength(0);
         pw.print(formatDurationHMS(sb,
@@ -3573,7 +3600,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..061e4ca
--- /dev/null
+++ b/services/core/java/com/android/server/content/SyncManagerConstants.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.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 com.android.internal.os.BackgroundThread;
+
+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;
+    }
+
+    public void start() {
+        BackgroundThread.getHandler().post(() -> {
+            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/BrightnessTracker.java b/services/core/java/com/android/server/display/BrightnessTracker.java
index 6b4666a..524de91 100644
--- a/services/core/java/com/android/server/display/BrightnessTracker.java
+++ b/services/core/java/com/android/server/display/BrightnessTracker.java
@@ -115,12 +115,10 @@
             = new RingBuffer<>(BrightnessChangeEvent.class, MAX_EVENTS);
     @GuardedBy("mEventsLock")
     private boolean mEventsDirty;
-    private final Runnable mEventsWriter = () -> writeEvents();
-    private volatile boolean mWriteEventsScheduled;
+
+    private volatile boolean mWriteBrightnessTrackerStateScheduled;
 
     private AmbientBrightnessStatsTracker mAmbientBrightnessStatsTracker;
-    private final Runnable mAmbientBrightnessStatsWriter = () -> writeAmbientBrightnessStats();
-    private volatile boolean mWriteBrightnessStatsScheduled;
 
     private UserManager mUserManager;
     private final Context mContext;
@@ -167,13 +165,7 @@
         }
         mBgHandler = new TrackerHandler(mInjector.getBackgroundHandler().getLooper());
         mUserManager = mContext.getSystemService(UserManager.class);
-        try {
-            final ActivityManager.StackInfo focusedStack = mInjector.getFocusedStack();
-            mCurrentUserId = focusedStack.userId;
-        } catch (RemoteException e) {
-            // Really shouldn't be possible.
-            return;
-        }
+        mCurrentUserId = ActivityManager.getCurrentUser();
         mBgHandler.obtainMessage(MSG_BACKGROUND_START, (Float) initialBrightness).sendToTarget();
     }
 
@@ -355,18 +347,17 @@
     }
 
     private void scheduleWriteBrightnessTrackerState() {
-        if (!mWriteEventsScheduled) {
-            mBgHandler.post(mEventsWriter);
-            mWriteEventsScheduled = true;
-        }
-        if (!mWriteBrightnessStatsScheduled) {
-            mBgHandler.post(mAmbientBrightnessStatsWriter);
-            mWriteBrightnessStatsScheduled = true;
+        if (!mWriteBrightnessTrackerStateScheduled) {
+            mBgHandler.post(() -> {
+                mWriteBrightnessTrackerStateScheduled = false;
+                writeEvents();
+                writeAmbientBrightnessStats();
+            });
+            mWriteBrightnessTrackerStateScheduled = true;
         }
     }
 
     private void writeEvents() {
-        mWriteEventsScheduled = false;
         synchronized (mEventsLock) {
             if (!mEventsDirty) {
                 // Nothing to write
@@ -398,7 +389,6 @@
     }
 
     private void writeAmbientBrightnessStats() {
-        mWriteBrightnessStatsScheduled = false;
         final AtomicFile writeTo = mInjector.getFile(AMBIENT_BRIGHTNESS_STATS_FILE);
         if (writeTo == null) {
             return;
@@ -642,6 +632,7 @@
             }
         }
         if (mAmbientBrightnessStatsTracker != null) {
+            pw.println();
             mAmbientBrightnessStatsTracker.dump(pw);
         }
     }
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index b27f1ec..fa39ce4 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -51,7 +51,6 @@
 import android.provider.Settings;
 import android.util.MathUtils;
 import android.util.Slog;
-import android.util.Spline;
 import android.util.TimeUtils;
 import android.view.Display;
 
@@ -501,6 +500,7 @@
     }
 
     public void onSwitchUser(@UserIdInt int newUserId) {
+        handleSettingsChange();
         mBrightnessTracker.onSwitchUser(newUserId);
     }
 
diff --git a/services/core/java/com/android/server/fingerprint/FingerprintService.java b/services/core/java/com/android/server/fingerprint/FingerprintService.java
index b5f94b1..692535c 100644
--- a/services/core/java/com/android/server/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/fingerprint/FingerprintService.java
@@ -421,7 +421,7 @@
                 byteToken[i] = token.get(i);
             }
             // Send to Keystore
-            KeyStore.getInstance().addAuthToken(byteToken);
+            KeyStore.getInstance().addAuthToken(byteToken, mCurrentUserId);
         }
         if (client != null && client.onAuthenticated(fingerId, groupId)) {
             removeClient(client);
@@ -915,7 +915,7 @@
         notifyLockoutResetMonitors();
     }
 
-    private class FingerprintServiceLockoutResetMonitor {
+    private class FingerprintServiceLockoutResetMonitor implements IBinder.DeathRecipient {
 
         private static final long WAKELOCK_TIMEOUT_MS = 2000;
         private final IFingerprintServiceLockoutResetCallback mCallback;
@@ -926,6 +926,11 @@
             mCallback = callback;
             mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
                     "lockout reset callback");
+            try {
+                mCallback.asBinder().linkToDeath(FingerprintServiceLockoutResetMonitor.this, 0);
+            } catch (RemoteException e) {
+                Slog.w(TAG, "caught remote exception in linkToDeath", e);
+            }
         }
 
         public void sendLockoutReset() {
@@ -959,6 +964,12 @@
                 removeLockoutResetCallback(FingerprintServiceLockoutResetMonitor.this);
             }
         };
+
+        @Override
+        public void binderDied() {
+            Slog.e(TAG, "Lockout reset callback binder died");
+            mHandler.post(mRemoveCallbackRunnable);
+        }
     }
 
     private IBiometricsFingerprintClientCallback mDaemonCallback =
diff --git a/services/core/java/com/android/server/fingerprint/FingerprintsUserState.java b/services/core/java/com/android/server/fingerprint/FingerprintsUserState.java
index 0976a22..b0cde2d 100644
--- a/services/core/java/com/android/server/fingerprint/FingerprintsUserState.java
+++ b/services/core/java/com/android/server/fingerprint/FingerprintsUserState.java
@@ -202,6 +202,7 @@
         }
     }
 
+    @GuardedBy("this")
     private void readStateSyncLocked() {
         FileInputStream in;
         if (!mFile.exists()) {
@@ -226,6 +227,7 @@
         }
     }
 
+    @GuardedBy("this")
     private void parseStateLocked(XmlPullParser parser)
             throws IOException, XmlPullParserException {
         final int outerDepth = parser.getDepth();
@@ -243,6 +245,7 @@
         }
     }
 
+    @GuardedBy("this")
     private void parseFingerprintsLocked(XmlPullParser parser)
             throws IOException, XmlPullParserException {
 
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
old mode 100644
new mode 100755
index e5f4282..0cba76b
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
@@ -660,7 +660,8 @@
     @ServiceThreadOnly
     void startQueuedActions() {
         assertRunOnServiceThread();
-        for (HdmiCecFeatureAction action : mActions) {
+        // Use copied action list in that start() may remove itself.
+        for (HdmiCecFeatureAction action : new ArrayList<>(mActions)) {
             if (!action.started()) {
                 Slog.i(TAG, "Starting queued action:" + action);
                 action.start();
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
index 1e09383..de0f298 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
@@ -1299,6 +1299,7 @@
     /**
      * Return external input devices.
      */
+    @GuardedBy("mLock")
     List<HdmiDeviceInfo> getSafeExternalInputsLocked() {
         return mSafeExternalInputs;
     }
@@ -1421,6 +1422,7 @@
         }
     }
 
+    @GuardedBy("mLock")
     List<HdmiDeviceInfo> getSafeCecDevicesLocked() {
         ArrayList<HdmiDeviceInfo> infoList = new ArrayList<>();
         for (HdmiDeviceInfo info : mSafeAllDeviceInfos) {
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index 3d079cc..b06dba9 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -1097,6 +1097,7 @@
         }
     }
 
+    @GuardedBy("mLock")
     private List<HdmiDeviceInfo> getMhlDevicesLocked() {
         return mMhlDevices;
     }
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index 401c05e..c33d7f4 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -23,6 +23,7 @@
 import android.app.Activity;
 import android.app.ActivityManager;
 import android.app.ActivityManagerInternal;
+import android.app.AlarmManager;
 import android.app.AppGlobals;
 import android.app.IUidObserver;
 import android.app.job.IJobScheduler;
@@ -40,7 +41,6 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.content.Intent.UriFlags;
 import android.content.pm.IPackageManager;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManagerInternal;
@@ -79,7 +79,7 @@
 import com.android.internal.util.Preconditions;
 import com.android.server.DeviceIdleController;
 import com.android.server.FgThread;
-import com.android.server.ForceAppStandbyTracker;
+import com.android.server.AppStateTracker;
 import com.android.server.LocalServices;
 import com.android.server.job.JobSchedulerServiceDumpProto.ActiveJob;
 import com.android.server.job.JobSchedulerServiceDumpProto.PendingJob;
@@ -184,7 +184,8 @@
     ActivityManagerInternal mActivityManagerInternal;
     IBatteryStats mBatteryStats;
     DeviceIdleController.LocalService mLocalDeviceIdleController;
-    final ForceAppStandbyTracker mForceAppStandbyTracker;
+    AppStateTracker mAppStateTracker;
+    final UsageStatsManagerInternal mUsageStats;
 
     /**
      * Set to true once we are allowed to run third party apps.
@@ -226,7 +227,10 @@
      */
     final long[] mNextBucketHeartbeat = { 0, 0, 0, 0, Long.MAX_VALUE };
     long mHeartbeat = 0;
-    long mLastHeartbeatTime = 0;
+    long mLastHeartbeatTime = sElapsedRealtimeClock.millis();
+
+    static final String HEARTBEAT_TAG = "*job.heartbeat*";
+    final HeartbeatAlarmListener mHeartbeatAlarm = new HeartbeatAlarmListener();
 
     // -- Pre-allocated temporaries only for use in assignJobsToContextsLocked --
 
@@ -496,6 +500,9 @@
                 STANDBY_BEATS[3] = mParser.getInt(KEY_STANDBY_RARE_BEATS,
                         DEFAULT_STANDBY_RARE_BEATS);
             }
+
+            // Reset the heartbeat alarm based on the new heartbeat duration
+            setNextHeartbeatAlarm();
         }
 
         void dump(PrintWriter pw) {
@@ -787,20 +794,13 @@
     }
 
     /**
-     * Return whether an UID is in the foreground or not.
+     * Return whether an UID is active or idle.
      */
-    private boolean isUidInForeground(int uid) {
-        synchronized (mLock) {
-            if (mUidPriorityOverride.get(uid, 0) > 0) {
-                return true;
-            }
-        }
-        // Note UID observer may not be called in time, so we always check with the AM.
-        return mActivityManagerInternal.getUidProcessState(uid)
-                <= ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
+    private boolean isUidActive(int uid) {
+        return mAppStateTracker.isUidActiveSynced(uid);
     }
 
-    private final Predicate<Integer> mIsUidInForegroundPredicate = this::isUidInForeground;
+    private final Predicate<Integer> mIsUidActivePredicate = this::isUidActive;
 
     public int scheduleAsPackage(JobInfo job, JobWorkItem work, int uId, String packageName,
             int userId, String tag) {
@@ -826,7 +826,7 @@
 
                     // If any of work item is enqueued when the source is in the foreground,
                     // exempt the entire job.
-                    toCancel.maybeAddForegroundExemption(mIsUidInForegroundPredicate);
+                    toCancel.maybeAddForegroundExemption(mIsUidActivePredicate);
 
                     return JobScheduler.RESULT_SUCCESS;
                 }
@@ -838,7 +838,7 @@
             // Note if it's a sync job, this method is called on the handler so it's not exactly
             // the state when requestSync() was called, but that should be fine because of the
             // 1 minute foreground grace period.
-            jobStatus.maybeAddForegroundExemption(mIsUidInForegroundPredicate);
+            jobStatus.maybeAddForegroundExemption(mIsUidActivePredicate);
 
             if (DEBUG) Slog.d(TAG, "SCHEDULE: " + jobStatus.toShortString());
             // Jobs on behalf of others don't apply to the per-app job cap
@@ -1098,9 +1098,9 @@
         mJobSchedulerStub = new JobSchedulerStub();
 
         // Set up the app standby bucketing tracker
-        UsageStatsManagerInternal usageStats = LocalServices.getService(UsageStatsManagerInternal.class);
-        mStandbyTracker = new StandbyTracker(usageStats);
-        usageStats.addAppIdleStateChangeListener(mStandbyTracker);
+        mStandbyTracker = new StandbyTracker();
+        mUsageStats = LocalServices.getService(UsageStatsManagerInternal.class);
+        mUsageStats.addAppIdleStateChangeListener(mStandbyTracker);
 
         // The job store needs to call back
         publishLocalService(JobSchedulerInternal.class, new LocalService());
@@ -1123,8 +1123,6 @@
         mDeviceIdleJobsController = DeviceIdleJobsController.get(this);
         mControllers.add(mDeviceIdleJobsController);
 
-        mForceAppStandbyTracker = ForceAppStandbyTracker.getInstance(context);
-
         // If the job store determined that it can't yet reschedule persisted jobs,
         // we need to start watching the clock.
         if (!mJobs.jobTimesInflatedValid()) {
@@ -1185,7 +1183,9 @@
         if (PHASE_SYSTEM_SERVICES_READY == phase) {
             mConstants.start(getContext().getContentResolver());
 
-            mForceAppStandbyTracker.start();
+            mAppStateTracker = Preconditions.checkNotNull(
+                    LocalServices.getService(AppStateTracker.class));
+            setNextHeartbeatAlarm();
 
             // Register br for package removals and user removals.
             final IntentFilter filter = new IntentFilter();
@@ -1427,6 +1427,23 @@
                 periodicToReschedule.getLastFailedRunTime());
     }
 
+    long heartbeatWhenJobsLastRun(String packageName, final @UserIdInt int userId) {
+        final long heartbeat;
+        final long timeSinceLastJob = mUsageStats.getTimeSinceLastJobRun(packageName, userId);
+        synchronized (mLock) {
+            heartbeat = mHeartbeat - (timeSinceLastJob / mConstants.STANDBY_HEARTBEAT_TIME);
+        }
+        if (DEBUG_STANDBY) {
+            Slog.v(TAG, "Last job heartbeat " + heartbeat + " for " + packageName + "/" + userId
+                    + " delta=" + timeSinceLastJob);
+        }
+        return heartbeat;
+    }
+
+    long heartbeatWhenJobsLastRun(JobStatus job) {
+        return heartbeatWhenJobsLastRun(job.getSourcePackageName(), job.getSourceUserId());
+    }
+
     // JobCompletedListener implementations.
 
     /**
@@ -1569,9 +1586,7 @@
         noteJobsNonpending(mPendingJobs);
         mPendingJobs.clear();
         stopNonReadyActiveJobsLocked();
-        boolean updated = updateStandbyHeartbeatLocked();
         mJobs.forEachJob(mReadyQueueFunctor);
-        if (updated) updateNextStandbyHeartbeatsLocked();
         mReadyQueueFunctor.postProcess();
 
         if (DEBUG) {
@@ -1725,36 +1740,78 @@
         noteJobsNonpending(mPendingJobs);
         mPendingJobs.clear();
         stopNonReadyActiveJobsLocked();
-        boolean updated = updateStandbyHeartbeatLocked();
         mJobs.forEachJob(mMaybeQueueFunctor);
-        if (updated) updateNextStandbyHeartbeatsLocked();
         mMaybeQueueFunctor.postProcess();
     }
 
-    private boolean updateStandbyHeartbeatLocked() {
-        final long sinceLast = sElapsedRealtimeClock.millis() - mLastHeartbeatTime;
-        final long beatsElapsed = sinceLast / mConstants.STANDBY_HEARTBEAT_TIME;
-        if (beatsElapsed > 0) {
-            mHeartbeat += beatsElapsed;
-            mLastHeartbeatTime += beatsElapsed * mConstants.STANDBY_HEARTBEAT_TIME;
-            if (DEBUG_STANDBY) {
-                Slog.v(TAG, "Advancing standby heartbeat by " + beatsElapsed + " to " + mHeartbeat);
+    /**
+     * Heartbeat tracking.  The heartbeat alarm is intentionally non-wakeup.
+     */
+    class HeartbeatAlarmListener implements AlarmManager.OnAlarmListener {
+
+        @Override
+        public void onAlarm() {
+            synchronized (mLock) {
+                final long sinceLast = sElapsedRealtimeClock.millis() - mLastHeartbeatTime;
+                final long beatsElapsed = sinceLast / mConstants.STANDBY_HEARTBEAT_TIME;
+                if (beatsElapsed > 0) {
+                    mLastHeartbeatTime += beatsElapsed * mConstants.STANDBY_HEARTBEAT_TIME;
+                    advanceHeartbeatLocked(beatsElapsed);
+                }
             }
-            return true;
+            setNextHeartbeatAlarm();
         }
-        return false;
     }
 
-    private void updateNextStandbyHeartbeatsLocked() {
-        // don't update ACTIVE or NEVER bucket milestones
+    // Intentionally does not touch the alarm timing
+    void advanceHeartbeatLocked(long beatsElapsed) {
+        mHeartbeat += beatsElapsed;
+        if (DEBUG_STANDBY) {
+            Slog.v(TAG, "Advancing standby heartbeat by " + beatsElapsed
+                    + " to " + mHeartbeat);
+        }
+        // Don't update ACTIVE or NEVER bucket milestones.  Note that mHeartbeat
+        // will be equal to mNextBucketHeartbeat[bucket] for one beat, during which
+        // new jobs scheduled by apps in that bucket will be permitted to run
+        // immediately.
+        boolean didAdvanceBucket = false;
         for (int i = 1; i < mNextBucketHeartbeat.length - 1; i++) {
-            while (mHeartbeat >= mNextBucketHeartbeat[i]) {
+            // Did we reach or cross a bucket boundary?
+            if (mHeartbeat >= mNextBucketHeartbeat[i]) {
+                didAdvanceBucket = true;
+            }
+            while (mHeartbeat > mNextBucketHeartbeat[i]) {
                 mNextBucketHeartbeat[i] += mConstants.STANDBY_BEATS[i];
             }
             if (DEBUG_STANDBY) {
-                Slog.v(TAG, "   Bucket " + i + " next heartbeat " + mNextBucketHeartbeat[i]);
+                Slog.v(TAG, "   Bucket " + i + " next heartbeat "
+                        + mNextBucketHeartbeat[i]);
             }
         }
+
+        if (didAdvanceBucket) {
+            if (DEBUG_STANDBY) {
+                Slog.v(TAG, "Hit bucket boundary; reevaluating job runnability");
+            }
+            mHandler.obtainMessage(MSG_CHECK_JOB).sendToTarget();
+        }
+    }
+
+    void setNextHeartbeatAlarm() {
+        final long heartbeatLength;
+        synchronized (mLock) {
+            heartbeatLength = mConstants.STANDBY_HEARTBEAT_TIME;
+        }
+        final long now = sElapsedRealtimeClock.millis();
+        final long nextBeatOrdinal = (now + heartbeatLength) / heartbeatLength;
+        final long nextHeartbeat = nextBeatOrdinal * heartbeatLength;
+        if (DEBUG_STANDBY) {
+            Slog.i(TAG, "Setting heartbeat alarm for " + nextHeartbeat
+                    + " = " + TimeUtils.formatDuration(nextHeartbeat - now));
+        }
+        AlarmManager am = (AlarmManager) getContext().getSystemService(Context.ALARM_SERVICE);
+        am.setExact(AlarmManager.ELAPSED_REALTIME, nextHeartbeat,
+                HEARTBEAT_TAG, mHeartbeatAlarm, mHandler);
     }
 
     /**
@@ -1820,17 +1877,20 @@
         if (!mInParole && !job.getJob().isExemptedFromAppStandby()) {
             final int bucket = job.getStandbyBucket();
             if (mHeartbeat < mNextBucketHeartbeat[bucket]) {
-                // Only skip this job if it's still waiting for the end of its (initial) nominal
+                // Only skip this job if the app is still waiting for the end of its nominal
                 // bucket interval.  Once it's waited that long, we let it go ahead and clear.
                 // The final (NEVER) bucket is special; we never age those apps' jobs into
                 // runnability.
+                final long appLastRan = heartbeatWhenJobsLastRun(job);
                 if (bucket >= mConstants.STANDBY_BEATS.length
-                        || (mHeartbeat < job.getBaseHeartbeat() + mConstants.STANDBY_BEATS[bucket])) {
+                        || (mHeartbeat > appLastRan
+                                && mHeartbeat < appLastRan + mConstants.STANDBY_BEATS[bucket])) {
                     // TODO: log/trace that we're deferring the job due to bucketing if we hit this
                     if (job.getWhenStandbyDeferred() == 0) {
                         if (DEBUG_STANDBY) {
                             Slog.v(TAG, "Bucket deferral: " + mHeartbeat + " < "
-                                    + mNextBucketHeartbeat[job.getStandbyBucket()] + " for " + job);
+                                    + (appLastRan + mConstants.STANDBY_BEATS[bucket])
+                                    + " for " + job);
                         }
                         job.setWhenStandbyDeferred(sElapsedRealtimeClock.millis());
                     }
@@ -2087,18 +2147,19 @@
                 // ACTIVE => everything can be run right away
                 // NEVER => we won't run them anyway, so let them go in the future
                 // as soon as the app enters normal use
+                if (DEBUG_STANDBY) {
+                    Slog.v(TAG, "Base heartbeat forced ZERO for new job in "
+                            + packageName + "/" + userId);
+                }
                 return 0;
             }
 
-            final long timeSinceLastJob = mStandbyTracker.getTimeSinceLastJobRun(
-                    packageName, userId);
-            final long bucketLength = mConstants.STANDBY_BEATS[appStandbyBucket];
-            final long bucketsAgo = timeSinceLastJob / bucketLength;
-
-            // If we haven't run any jobs for more than the app's current bucket period, just
-            // consider anything new to be immediately runnable.  Otherwise, base it on the
-            // bucket at which we last ran jobs.
-            return (bucketsAgo > bucketLength) ? 0 : (getCurrentHeartbeat() - bucketsAgo);
+            final long baseHeartbeat = heartbeatWhenJobsLastRun(packageName, userId);
+            if (DEBUG_STANDBY) {
+                Slog.v(TAG, "Base heartbeat " + baseHeartbeat + " for new job in "
+                        + packageName + "/" + userId);
+            }
+            return baseHeartbeat;
         }
 
         /**
@@ -2175,15 +2236,6 @@
      * Tracking of app assignments to standby buckets
      */
     final class StandbyTracker extends AppIdleStateChangeListener {
-        final UsageStatsManagerInternal mUsageStats;
-
-        StandbyTracker(UsageStatsManagerInternal usageStats) {
-            mUsageStats = usageStats;
-        }
-
-        public long getTimeSinceLastJobRun(String packageName, final @UserIdInt int userId) {
-            return mUsageStats.getTimeSinceLastJobRun(packageName, userId);
-        }
 
         // AppIdleStateChangeListener interface for live updates
 
@@ -2265,6 +2317,7 @@
         else return 0;
     }
 
+    // Static to support external callers
     public static int standbyBucketForPackage(String packageName, int userId, long elapsedNow) {
         UsageStatsManagerInternal usageStats = LocalServices.getService(
                 UsageStatsManagerInternal.class);
@@ -2346,9 +2399,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);
                 }
             }
         }
@@ -2691,6 +2744,7 @@
         }
     }
 
+    // Shell command infrastructure
     int getJobState(PrintWriter pw, String pkgName, int userId, int jobId) {
         try {
             final int uid = AppGlobals.getPackageManager().getPackageUid(pkgName, 0,
@@ -2768,6 +2822,21 @@
         return 0;
     }
 
+    // Shell command infrastructure
+    int executeHeartbeatCommand(PrintWriter pw, int numBeats) {
+        if (numBeats < 1) {
+            pw.println(getCurrentHeartbeat());
+            return 0;
+        }
+
+        pw.print("Advancing standby heartbeat by ");
+        pw.println(numBeats);
+        synchronized (mLock) {
+            advanceHeartbeatLocked(numBeats);
+        }
+        return 0;
+    }
+
     private String printContextIdToJobMap(JobStatus[] map, String initial) {
         StringBuilder s = new StringBuilder(initial + ": ");
         for (int i=0; i<map.length; i++) {
diff --git a/services/core/java/com/android/server/job/JobSchedulerShellCommand.java b/services/core/java/com/android/server/job/JobSchedulerShellCommand.java
index d630aab..63225f3 100644
--- a/services/core/java/com/android/server/job/JobSchedulerShellCommand.java
+++ b/services/core/java/com/android/server/job/JobSchedulerShellCommand.java
@@ -64,6 +64,8 @@
                     return getStorageNotLow(pw);
                 case "get-job-state":
                     return getJobState(pw);
+                case "heartbeat":
+                    return doHeartbeat(pw);
                 default:
                     return handleDefaultCommands(cmd);
             }
@@ -333,6 +335,20 @@
         }
     }
 
+    private int doHeartbeat(PrintWriter pw) throws Exception {
+        checkPermission("manipulate scheduler heartbeat");
+
+        final String arg = getNextArg();
+        final int numBeats = (arg != null) ? Integer.parseInt(arg) : 0;
+
+        final long ident = Binder.clearCallingIdentity();
+        try {
+            return mInternal.executeHeartbeatCommand(pw, numBeats);
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+    }
+
     @Override
     public void onHelp() {
         final PrintWriter pw = getOutPrintWriter();
@@ -359,6 +375,9 @@
         pw.println("    Options:");
         pw.println("      -u or --user: specify which user's job is to be run; the default is");
         pw.println("         the primary or system user");
+        pw.println("  heartbeat [num]");
+        pw.println("    With no argument, prints the current standby heartbeat.  With a positive");
+        pw.println("    argument, advances the standby heartbeat by that number.");
         pw.println("  monitor-battery [on|off]");
         pw.println("    Control monitoring of all battery changes.  Off by default.  Turning");
         pw.println("    on makes get-battery-seq useful.");
diff --git a/services/core/java/com/android/server/job/JobServiceContext.java b/services/core/java/com/android/server/job/JobServiceContext.java
index 37b3990..1f8cf76 100644
--- a/services/core/java/com/android/server/job/JobServiceContext.java
+++ b/services/core/java/com/android/server/job/JobServiceContext.java
@@ -240,11 +240,6 @@
                 }
             }
 
-            UsageStatsManagerInternal usageStats =
-                    LocalServices.getService(UsageStatsManagerInternal.class);
-            usageStats.setLastJobRunTime(job.getSourcePackageName(), job.getSourceUserId(),
-                    mExecutionStartTimeElapsed);
-
             // Once we'e begun executing a job, we by definition no longer care whether
             // it was inflated from disk with not-yet-coherent delay/deadline bounds.
             job.clearPersistedUtcTimes();
@@ -267,12 +262,16 @@
                 removeOpTimeOutLocked();
                 return false;
             }
+            mJobPackageTracker.noteActive(job);
             try {
                 mBatteryStats.noteJobStart(job.getBatteryName(), job.getSourceUid());
             } catch (RemoteException e) {
                 // Whatever.
             }
-            mJobPackageTracker.noteActive(job);
+            UsageStatsManagerInternal usageStats =
+                    LocalServices.getService(UsageStatsManagerInternal.class);
+            usageStats.setLastJobRunTime(job.getSourcePackageName(), job.getSourceUserId(),
+                    mExecutionStartTimeElapsed);
             mAvailable = false;
             mStoppedReason = null;
             mStoppedTime = 0;
@@ -295,10 +294,12 @@
     }
 
     /** Called externally when a job that was scheduled for execution should be cancelled. */
+    @GuardedBy("mLock")
     void cancelExecutingJobLocked(int reason, String debugReason) {
         doCancelLocked(reason, debugReason);
     }
 
+    @GuardedBy("mLock")
     void preemptExecutingJobLocked() {
         doCancelLocked(JobParameters.REASON_PREEMPT, "cancelled due to preemption");
     }
@@ -319,6 +320,7 @@
         return mTimeoutElapsed;
     }
 
+    @GuardedBy("mLock")
     boolean timeoutIfExecutingLocked(String pkgName, int userId, boolean matchJobId, int jobId,
             String reason) {
         final JobStatus executing = getRunningJobLocked();
@@ -512,6 +514,7 @@
         }
     }
 
+    @GuardedBy("mLock")
     void doServiceBoundLocked() {
         removeOpTimeOutLocked();
         handleServiceBoundLocked();
@@ -531,6 +534,7 @@
         }
     }
 
+    @GuardedBy("mLock")
     void doCallbackLocked(boolean reschedule, String reason) {
         if (DEBUG) {
             Slog.d(TAG, "doCallback of : " + mRunningJob
@@ -550,6 +554,7 @@
         }
     }
 
+    @GuardedBy("mLock")
     void doCancelLocked(int arg1, String debugReason) {
         if (mVerb == VERB_FINISHED) {
             if (DEBUG) {
@@ -567,6 +572,7 @@
     }
 
     /** Start the job on the service. */
+    @GuardedBy("mLock")
     private void handleServiceBoundLocked() {
         if (DEBUG) {
             Slog.d(TAG, "handleServiceBound for " + getRunningJobNameLocked());
@@ -605,6 +611,7 @@
      *     _EXECUTING  -> Error
      *     _STOPPING   -> Error
      */
+    @GuardedBy("mLock")
     private void handleStartedLocked(boolean workOngoing) {
         switch (mVerb) {
             case VERB_STARTING:
@@ -637,6 +644,7 @@
      *     _STARTING   -> Error
      *     _PENDING    -> Error
      */
+    @GuardedBy("mLock")
     private void handleFinishedLocked(boolean reschedule, String reason) {
         switch (mVerb) {
             case VERB_EXECUTING:
@@ -659,6 +667,7 @@
      *                      in the message queue.
      *     _ENDING     -> No point in doing anything here, so we ignore.
      */
+    @GuardedBy("mLock")
     private void handleCancelLocked(String reason) {
         if (JobSchedulerService.DEBUG) {
             Slog.d(TAG, "Handling cancel for: " + mRunningJob.getJobId() + " "
@@ -683,6 +692,7 @@
     }
 
     /** Process MSG_TIMEOUT here. */
+    @GuardedBy("mLock")
     private void handleOpTimeoutLocked() {
         switch (mVerb) {
             case VERB_BINDING:
@@ -722,6 +732,7 @@
      * Already running, need to stop. Will switch {@link #mVerb} from VERB_EXECUTING ->
      * VERB_STOPPING.
      */
+    @GuardedBy("mLock")
     private void sendStopMessageLocked(String reason) {
         removeOpTimeOutLocked();
         if (mVerb != VERB_EXECUTING) {
@@ -747,6 +758,7 @@
      * or from acknowledging the stop message we sent. Either way, we're done tracking it and
      * we want to clean up internally.
      */
+    @GuardedBy("mLock")
     private void closeAndCleanupJobLocked(boolean reschedule, String reason) {
         final JobStatus completedJob;
         if (mVerb == VERB_FINISHED) {
diff --git a/services/core/java/com/android/server/job/controllers/BackgroundJobsController.java b/services/core/java/com/android/server/job/controllers/BackgroundJobsController.java
index 5eb7700..e8057fb 100644
--- a/services/core/java/com/android/server/job/controllers/BackgroundJobsController.java
+++ b/services/core/java/com/android/server/job/controllers/BackgroundJobsController.java
@@ -22,8 +22,10 @@
 import android.util.Slog;
 import android.util.proto.ProtoOutputStream;
 
-import com.android.server.ForceAppStandbyTracker;
-import com.android.server.ForceAppStandbyTracker.Listener;
+import com.android.internal.util.Preconditions;
+import com.android.server.AppStateTracker;
+import com.android.server.AppStateTracker.Listener;
+import com.android.server.LocalServices;
 import com.android.server.job.JobSchedulerService;
 import com.android.server.job.JobStore;
 import com.android.server.job.StateControllerProto;
@@ -42,8 +44,7 @@
 
     private final JobSchedulerService mJobSchedulerService;
 
-    private final ForceAppStandbyTracker mForceAppStandbyTracker;
-
+    private final AppStateTracker mAppStateTracker;
 
     public static BackgroundJobsController get(JobSchedulerService service) {
         synchronized (sCreationLock) {
@@ -59,10 +60,9 @@
         super(service, context, lock);
         mJobSchedulerService = service;
 
-        mForceAppStandbyTracker = ForceAppStandbyTracker.getInstance(context);
-
-        mForceAppStandbyTracker.addListener(mForceAppStandbyListener);
-        mForceAppStandbyTracker.start();
+        mAppStateTracker = Preconditions.checkNotNull(
+                LocalServices.getService(AppStateTracker.class));
+        mAppStateTracker.addListener(mForceAppStandbyListener);
     }
 
     @Override
@@ -79,7 +79,7 @@
     public void dumpControllerStateLocked(final PrintWriter pw, final int filterUid) {
         pw.println("BackgroundJobsController");
 
-        mForceAppStandbyTracker.dump(pw, "");
+        mAppStateTracker.dump(pw, "");
 
         pw.println("Job state:");
         mJobSchedulerService.getJobStore().forEachJob((jobStatus) -> {
@@ -92,16 +92,16 @@
             jobStatus.printUniqueId(pw);
             pw.print(" from ");
             UserHandle.formatUid(pw, uid);
-            pw.print(mForceAppStandbyTracker.isUidActive(uid) ? " active" : " idle");
-            if (mForceAppStandbyTracker.isUidPowerSaveWhitelisted(uid) ||
-                    mForceAppStandbyTracker.isUidTempPowerSaveWhitelisted(uid)) {
+            pw.print(mAppStateTracker.isUidActive(uid) ? " active" : " idle");
+            if (mAppStateTracker.isUidPowerSaveWhitelisted(uid) ||
+                    mAppStateTracker.isUidTempPowerSaveWhitelisted(uid)) {
                 pw.print(", whitelisted");
             }
             pw.print(": ");
             pw.print(sourcePkg);
 
             pw.print(" [RUN_ANY_IN_BACKGROUND ");
-            pw.print(mForceAppStandbyTracker.isRunAnyInBackgroundAppOpsAllowed(uid, sourcePkg)
+            pw.print(mAppStateTracker.isRunAnyInBackgroundAppOpsAllowed(uid, sourcePkg)
                     ? "allowed]" : "disallowed]");
 
             if ((jobStatus.satisfiedConstraints
@@ -118,7 +118,7 @@
         final long token = proto.start(fieldId);
         final long mToken = proto.start(StateControllerProto.BACKGROUND);
 
-        mForceAppStandbyTracker.dumpProto(proto,
+        mAppStateTracker.dumpProto(proto,
                 StateControllerProto.BackgroundJobsController.FORCE_APP_STANDBY_TRACKER);
 
         mJobSchedulerService.getJobStore().forEachJob((jobStatus) -> {
@@ -136,14 +136,14 @@
             proto.write(TrackedJob.SOURCE_PACKAGE_NAME, sourcePkg);
 
             proto.write(TrackedJob.IS_IN_FOREGROUND,
-                    mForceAppStandbyTracker.isUidActive(sourceUid));
+                    mAppStateTracker.isUidActive(sourceUid));
             proto.write(TrackedJob.IS_WHITELISTED,
-                    mForceAppStandbyTracker.isUidPowerSaveWhitelisted(sourceUid) ||
-                    mForceAppStandbyTracker.isUidTempPowerSaveWhitelisted(sourceUid));
+                    mAppStateTracker.isUidPowerSaveWhitelisted(sourceUid) ||
+                    mAppStateTracker.isUidTempPowerSaveWhitelisted(sourceUid));
 
             proto.write(
                     TrackedJob.CAN_RUN_ANY_IN_BACKGROUND,
-                    mForceAppStandbyTracker.isRunAnyInBackgroundAppOpsAllowed(
+                    mAppStateTracker.isRunAnyInBackgroundAppOpsAllowed(
                             sourceUid, sourcePkg));
 
             proto.write(
@@ -197,7 +197,7 @@
         final int uid = jobStatus.getSourceUid();
         final String packageName = jobStatus.getSourcePackageName();
 
-        final boolean canRun = !mForceAppStandbyTracker.areJobsRestricted(uid, packageName,
+        final boolean canRun = !mAppStateTracker.areJobsRestricted(uid, packageName,
                 (jobStatus.getInternalFlags() & JobStatus.INTERNAL_FLAG_HAS_FOREGROUND_EXEMPTION)
                         != 0);
 
diff --git a/services/core/java/com/android/server/job/controllers/ConnectivityController.java b/services/core/java/com/android/server/job/controllers/ConnectivityController.java
index 13873e4..77e813e 100644
--- a/services/core/java/com/android/server/job/controllers/ConnectivityController.java
+++ b/services/core/java/com/android/server/job/controllers/ConnectivityController.java
@@ -92,6 +92,7 @@
         mNetPolicyManager.registerListener(mNetPolicyListener);
     }
 
+    @GuardedBy("mLock")
     @Override
     public void maybeStartTrackingJobLocked(JobStatus jobStatus, JobStatus lastJob) {
         if (jobStatus.hasConnectivityConstraint()) {
@@ -101,6 +102,7 @@
         }
     }
 
+    @GuardedBy("mLock")
     @Override
     public void maybeStopTrackingJobLocked(JobStatus jobStatus, JobStatus incomingJob,
             boolean forUpdate) {
@@ -325,6 +327,7 @@
         }
     };
 
+    @GuardedBy("mLock")
     @Override
     public void dumpControllerStateLocked(PrintWriter pw, int filterUid) {
         pw.print("Connectivity: connected=");
@@ -348,6 +351,7 @@
         }
     }
 
+    @GuardedBy("mLock")
     @Override
     public void dumpControllerStateLocked(ProtoOutputStream proto, long fieldId, int filterUid) {
         final long token = proto.start(fieldId);
diff --git a/services/core/java/com/android/server/job/controllers/JobStatus.java b/services/core/java/com/android/server/job/controllers/JobStatus.java
index 08ff7bd..3867306 100644
--- a/services/core/java/com/android/server/job/controllers/JobStatus.java
+++ b/services/core/java/com/android/server/job/controllers/JobStatus.java
@@ -1346,6 +1346,15 @@
         }
         pw.print(prefix); pw.print("Standby bucket: ");
         pw.println(bucketName(standbyBucket));
+        if (standbyBucket > 0) {
+            pw.print(prefix); pw.print("Base heartbeat: ");
+            pw.println(baseHeartbeat);
+        }
+        if (whenStandbyDeferred != 0) {
+            pw.print(prefix); pw.print("  Deferred since: ");
+            TimeUtils.formatDuration(whenStandbyDeferred, elapsedRealtimeMillis, pw);
+            pw.println();
+        }
         pw.print(prefix); pw.print("Enqueue time: ");
         TimeUtils.formatDuration(enqueueTime, elapsedRealtimeMillis, pw);
         pw.println();
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index 55c0f5a..9d2a8e2 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -16,6 +16,7 @@
 
 package com.android.server.location;
 
+import android.annotation.Nullable;
 import android.app.AlarmManager;
 import android.app.AppOpsManager;
 import android.app.PendingIntent;
@@ -28,11 +29,11 @@
 import android.hardware.location.GeofenceHardwareImpl;
 import android.location.Criteria;
 import android.location.FusedBatchOptions;
+import android.location.GnssMeasurementsEvent;
+import android.location.GnssNavigationMessage;
 import android.location.GnssStatus;
 import android.location.IGnssStatusListener;
 import android.location.IGnssStatusProvider;
-import android.location.GnssMeasurementsEvent;
-import android.location.GnssNavigationMessage;
 import android.location.IGpsGeofenceHardware;
 import android.location.ILocationManager;
 import android.location.INetInitiatedListener;
@@ -48,16 +49,16 @@
 import android.net.NetworkRequest;
 import android.net.Uri;
 import android.os.AsyncTask;
-import android.os.PowerManager.ServiceType;
-import android.os.PowerSaveState;
 import android.os.BatteryStats;
 import android.os.Binder;
 import android.os.Bundle;
-import android.os.PersistableBundle;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
+import android.os.PersistableBundle;
 import android.os.PowerManager;
+import android.os.PowerManager.ServiceType;
+import android.os.PowerSaveState;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.SystemClock;
@@ -68,25 +69,21 @@
 import android.provider.Settings;
 import android.provider.Telephony.Carriers;
 import android.provider.Telephony.Sms.Intents;
+import android.telephony.CarrierConfigManager;
 import android.telephony.SubscriptionManager;
 import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
 import android.telephony.TelephonyManager;
-import android.telephony.CarrierConfigManager;
 import android.telephony.gsm.GsmCellLocation;
 import android.text.TextUtils;
 import android.util.Log;
 import android.util.NtpTrustedTime;
-
 import com.android.internal.app.IAppOpsService;
 import com.android.internal.app.IBatteryStats;
-import com.android.internal.location.gnssmetrics.GnssMetrics;
 import com.android.internal.location.GpsNetInitiatedHandler;
 import com.android.internal.location.GpsNetInitiatedHandler.GpsNiNotification;
 import com.android.internal.location.ProviderProperties;
 import com.android.internal.location.ProviderRequest;
-
-import libcore.io.IoUtils;
-
+import com.android.internal.location.gnssmetrics.GnssMetrics;
 import java.io.File;
 import java.io.FileDescriptor;
 import java.io.FileInputStream;
@@ -97,11 +94,13 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Date;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Properties;
-import java.util.Map;
-import java.util.HashMap;
+
+import libcore.io.IoUtils;
 
 /**
  * A GNSS implementation of LocationProvider used by LocationManager.
@@ -206,7 +205,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;
@@ -215,6 +214,7 @@
     private static final int INITIALIZE_HANDLER = 13;
     private static final int REQUEST_SUPL_CONNECTION = 14;
     private static final int RELEASE_SUPL_CONNECTION = 15;
+    private static final int REQUEST_LOCATION = 16;
 
     // Request setid
     private static final int AGPS_RIL_REQUEST_SETID_IMSI = 1;
@@ -248,6 +248,13 @@
     private static final int TCP_MIN_PORT = 0;
     private static final int TCP_MAX_PORT = 0xffff;
 
+    // 10 seconds.
+    private static final long LOCATION_TIME_FRESHNESS_THESHOLD_MILLIS = 10 * 1000;
+    // 1 second, or 1 Hz frequency.
+    private static final long LOCATION_UPDATE_MIN_TIME_INTERVAL_MILLIS = 1000;
+    // 30 seconds.
+    private static final long LOCATION_UPDATE_DURATION_MILLIS = 30 * 1000;
+
     /** simpler wrapper for ProviderRequest + Worksource */
     private static class GpsRequest {
         public ProviderRequest request;
@@ -259,6 +266,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,10 +412,12 @@
     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;
+    private final FusedLocationListener mFusedLocationListener = new FusedLocationListener();
+    private static int sNumFusedLocationUpdatesRequests = 0;
 
     // Handler for processing events
     private Handler mHandler;
@@ -713,7 +758,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);
@@ -1038,6 +1083,89 @@
         });
     }
 
+    private void handleRequestLocation(boolean independentFromGnss) {
+        if (isRequestLocationRateLimited()) {
+            if (DEBUG) {
+                Log.d(TAG, "RequestLocation is denied due to too frequent requests.");
+            }
+            return;
+        }
+
+        LocationManager locationManager = (LocationManager) mContext.getSystemService(
+                Context.LOCATION_SERVICE);
+
+        if (independentFromGnss) {
+            // For fast GNSS TTFF
+            Location networkLocation = getLastFreshLocation(locationManager,
+                    LocationManager.NETWORK_PROVIDER);
+            if (networkLocation != null) {
+                handleUpdateLocation(networkLocation);
+                return;
+            }
+            locationManager.requestSingleUpdate(LocationManager.NETWORK_PROVIDER,
+                    new NetworkLocationListener(),
+                    mHandler.getLooper());
+        } else {
+            // For Device-Based Hybrid (E911)
+            locationManager.requestLocationUpdates(LocationManager.FUSED_PROVIDER,
+                    LOCATION_UPDATE_MIN_TIME_INTERVAL_MILLIS, /*minDistance=*/ 0,
+                    mFusedLocationListener, mHandler.getLooper());
+            sNumFusedLocationUpdatesRequests++;
+            mHandler.postDelayed(() -> {
+                if (--sNumFusedLocationUpdatesRequests == 0) {
+                    locationManager.removeUpdates(mFusedLocationListener);
+                }
+            }, LOCATION_UPDATE_DURATION_MILLIS);
+        }
+    }
+
+    private void injectBestLocation(Location location) {
+        int gnssLocationFlags = LOCATION_HAS_LAT_LONG |
+                (location.hasAltitude() ? LOCATION_HAS_ALTITUDE : 0) |
+                (location.hasSpeed() ? LOCATION_HAS_SPEED : 0) |
+                (location.hasBearing() ? LOCATION_HAS_BEARING : 0) |
+                (location.hasAccuracy() ? LOCATION_HAS_HORIZONTAL_ACCURACY : 0) |
+                (location.hasVerticalAccuracy() ? LOCATION_HAS_VERTICAL_ACCURACY : 0) |
+                (location.hasSpeedAccuracy() ? LOCATION_HAS_SPEED_ACCURACY : 0) |
+                (location.hasBearingAccuracy() ? LOCATION_HAS_BEARING_ACCURACY : 0);
+
+        double latitudeDegrees = location.getLatitude();
+        double longitudeDegrees = location.getLongitude();
+        double altitudeMeters = location.getAltitude();
+        float speedMetersPerSec = location.getSpeed();
+        float bearingDegrees = location.getBearing();
+        float horizontalAccuracyMeters = location.getAccuracy();
+        float verticalAccuracyMeters = location.getVerticalAccuracyMeters();
+        float speedAccuracyMetersPerSecond = location.getSpeedAccuracyMetersPerSecond();
+        float bearingAccuracyDegrees = location.getBearingAccuracyDegrees();
+        long timestamp = location.getTime();
+        native_inject_best_location(gnssLocationFlags, latitudeDegrees, longitudeDegrees,
+                altitudeMeters, speedMetersPerSec, bearingDegrees, horizontalAccuracyMeters,
+                verticalAccuracyMeters, speedAccuracyMetersPerSecond, bearingAccuracyDegrees,
+                timestamp);
+    }
+
+    /**
+     * Get the last fresh location.
+     *
+     * Return null if the last location is not available or not fresh.
+     */
+    private @Nullable
+    Location getLastFreshLocation(LocationManager locationManager, String provider) {
+        Location location = locationManager.getLastKnownLocation(provider);
+        if (location != null && System.currentTimeMillis() - location.getTime()
+                < LOCATION_TIME_FRESHNESS_THESHOLD_MILLIS) {
+            return location;
+        }
+        return null;
+    }
+
+    /** Returns true if the location request is too frequent. */
+    private boolean isRequestLocationRateLimited() {
+        // TODO(b/73198123): implement exponential backoff.
+        return false;
+    }
+
     private void handleDownloadXtraData() {
         if (!mSupportsXtra) {
             // native code reports xtra not supported, don't try
@@ -1245,29 +1373,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 +1679,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 +1703,8 @@
             mLastFixTime = 0;
 
             // reset SV count to zero
-            updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE, 0, 0, 0);
+            updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE);
+            mLocationExtras.reset();
         }
     }
 
@@ -1626,7 +1744,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 +1780,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 +1791,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 +1890,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 +1898,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);
         }
     }
 
@@ -2244,6 +2363,16 @@
     }
 
     /**
+     * Called from native code to request location info.
+     */
+    private void requestLocation(boolean independentFromGnss) {
+        if (DEBUG) {
+            Log.d(TAG, "requestLocation. independentFromGnss: " + independentFromGnss);
+        }
+        sendMessage(REQUEST_LOCATION, 0, independentFromGnss);
+    }
+
+    /**
      * Called from native code to request utc time info
      */
     private void requestUtcTime() {
@@ -2254,7 +2383,6 @@
     /**
      * Called from native code to request reference location info
      */
-
     private void requestRefLocation() {
         TelephonyManager phone = (TelephonyManager)
                 mContext.getSystemService(Context.TELEPHONY_SERVICE);
@@ -2330,6 +2458,9 @@
                 case INJECT_NTP_TIME:
                     handleInjectNtpTime();
                     break;
+                case REQUEST_LOCATION:
+                    handleRequestLocation((boolean) msg.obj);
+                    break;
                 case DOWNLOAD_XTRA_DATA:
                     handleDownloadXtraData();
                     break;
@@ -2455,15 +2586,7 @@
         }
     }
 
-    private final class NetworkLocationListener implements LocationListener {
-        @Override
-        public void onLocationChanged(Location location) {
-            // this callback happens on mHandler looper
-            if (LocationManager.NETWORK_PROVIDER.equals(location.getProvider())) {
-                handleUpdateLocation(location);
-            }
-        }
-
+    private abstract class LocationChangeListener implements LocationListener {
         @Override
         public void onStatusChanged(String provider, int status, Bundle extras) {
         }
@@ -2477,6 +2600,26 @@
         }
     }
 
+    private final class NetworkLocationListener extends LocationChangeListener {
+        @Override
+        public void onLocationChanged(Location location) {
+            // this callback happens on mHandler looper
+            if (LocationManager.NETWORK_PROVIDER.equals(location.getProvider())) {
+                handleUpdateLocation(location);
+            }
+        }
+    }
+
+    private final class FusedLocationListener extends LocationChangeListener {
+        @Override
+        public void onLocationChanged(Location location) {
+            if (LocationManager.FUSED_PROVIDER.equals(location.getProvider())) {
+                Log.d(TAG, "fused location listener: " + location);
+                injectBestLocation(location);
+            }
+        }
+    }
+
     private String getSelectedApn() {
         Uri uri = Uri.parse("content://telephony/carriers/preferapn");
         Cursor cursor = null;
@@ -2641,6 +2784,8 @@
                 return "RELEASE_SUPL_CONNECTION";
             case INJECT_NTP_TIME:
                 return "INJECT_NTP_TIME";
+            case REQUEST_LOCATION:
+                return "REQUEST_LOCATION";
             case DOWNLOAD_XTRA_DATA:
                 return "DOWNLOAD_XTRA_DATA";
             case INJECT_NTP_TIME_FINISHED:
@@ -2726,9 +2871,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];
 
@@ -2764,6 +2906,19 @@
 
     private native int native_read_nmea(byte[] buffer, int bufferSize);
 
+    private native void native_inject_best_location(
+            int gnssLocationFlags,
+            double latitudeDegrees,
+            double longitudeDegrees,
+            double altitudeMeters,
+            float speedMetersPerSec,
+            float bearingDegrees,
+            float horizontalAccuracyMeters,
+            float verticalAccuracyMeters,
+            float speedAccuracyMetersPerSecond,
+            float bearingAccuracyDegrees,
+            long timestamp);
+
     private native void native_inject_location(double latitude, double longitude, float accuracy);
 
     // XTRA Support
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index e715724..6deff36 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -2236,9 +2236,10 @@
      *     This happens during a normal migration case when the user currently has password.
      *
      * 2. credentialhash == null and credential == null
-     *     A new SP blob and a new SID will be created, while the user has no credentials.
+     *     A new SP blob and will be created, while the user has no credentials.
      *     This can happens when we are activating an escrow token on a unsecured device, during
      *     which we want to create the SP structure with an empty user credential.
+     *     This could also happen during an untrusted reset to clear password.
      *
      * 3. credentialhash == null and credential != null
      *     This is the untrusted credential reset, OR the user sets a new lockscreen password
@@ -2250,16 +2251,8 @@
             String credential, int credentialType, int requestedQuality,
             int userId) throws RemoteException {
         Slog.i(TAG, "Initialize SyntheticPassword for user: " + userId);
-        // Load from the cache or a make a new one
-        AuthenticationToken auth = mSpCache.get(userId);
-        if (auth != null) {
-            // If the synthetic password has been cached, we can only be in case 3., described
-            // above, for an untrusted credential reset so a new SID is still needed.
-            mSpManager.newSidForUser(getGateKeeperService(), auth, userId);
-        } else {
-            auth = mSpManager.newSyntheticPasswordAndSid(getGateKeeperService(),
-                      credentialHash, credential, userId);
-        }
+        final AuthenticationToken auth = mSpManager.newSyntheticPasswordAndSid(
+                getGateKeeperService(), credentialHash, credential, userId);
         onAuthTokenKnownForUser(userId, auth);
         if (auth == null) {
             Slog.wtf(TAG, "initializeSyntheticPasswordLocked returns null auth token");
@@ -2473,36 +2466,41 @@
                             : "pattern"));
         }
 
+        boolean untrustedReset = false;
         if (auth != null) {
-            // We are performing a trusted credential change i.e. a correct existing credential
-            // is provided
-            setLockCredentialWithAuthTokenLocked(credential, credentialType, auth, requestedQuality,
-                    userId);
-            mSpManager.destroyPasswordBasedSyntheticPassword(handle, userId);
             onAuthTokenKnownForUser(userId, auth);
         } else if (response != null
                 && response.getResponseCode() == VerifyCredentialResponse.RESPONSE_ERROR) {
-            // We are performing an untrusted credential change i.e. by DevicePolicyManager.
-            // So provision a new SP and SID. This would invalidate existing escrow tokens.
-            // Still support this for now but this flow will be removed in the next release.
+            // We are performing an untrusted credential change, by DevicePolicyManager or other
+            // internal callers that don't provide the existing credential
             Slog.w(TAG, "Untrusted credential change invoked");
-
-            if (mSpCache.get(userId) == null) {
-                throw new IllegalStateException(
-                        "Untrusted credential reset not possible without cached SP");
-            }
-
-            initializeSyntheticPasswordLocked(null, credential, credentialType, requestedQuality,
-                    userId);
-            synchronizeUnifiedWorkChallengeForProfiles(userId, null);
-            mSpManager.destroyPasswordBasedSyntheticPassword(handle, userId);
-
-            notifyActivePasswordMetricsAvailable(credential, userId);
+            // Try to get a cached auth token, so we can keep SP unchanged.
+            auth = mSpCache.get(userId);
+            untrustedReset = true;
         } else /* response == null || responseCode == VerifyCredentialResponse.RESPONSE_RETRY */ {
             Slog.w(TAG, "spBasedSetLockCredentialInternalLocked: " +
                     (response != null ? "rate limit exceeded" : "failed"));
             return;
         }
+
+        if (auth != null) {
+            if (untrustedReset) {
+                // Force change the current SID to mantain existing behaviour that an untrusted
+                // reset leads to a change of SID. If the untrusted reset is for clearing the
+                // current password, the nuking of the SID will be done in
+                // setLockCredentialWithAuthTokenLocked next
+                mSpManager.newSidForUser(getGateKeeperService(), auth, userId);
+            }
+            setLockCredentialWithAuthTokenLocked(credential, credentialType, auth, requestedQuality,
+                    userId);
+            mSpManager.destroyPasswordBasedSyntheticPassword(handle, userId);
+        } else {
+            throw new IllegalStateException(
+                    "Untrusted credential reset not possible without cached SP");
+            // Could call initializeSyntheticPasswordLocked(null, credential, credentialType,
+            // requestedQuality, userId) instead if we still allow untrusted reset that changes
+            // synthetic password. That would invalidate existing escrow tokens though.
+        }
         mRecoverableKeyStoreManager.lockScreenSecretChanged(credentialType, credential, userId);
     }
 
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsStrongAuth.java b/services/core/java/com/android/server/locksettings/LockSettingsStrongAuth.java
index c9c9329..c4f1f3d 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsStrongAuth.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsStrongAuth.java
@@ -19,9 +19,6 @@
 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_NOT_REQUIRED;
 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_TIMEOUT;
 
-import com.android.internal.widget.LockPatternUtils;
-import com.android.internal.widget.LockPatternUtils.StrongAuthTracker;
-
 import android.app.AlarmManager;
 import android.app.AlarmManager.OnAlarmListener;
 import android.app.admin.DevicePolicyManager;
@@ -29,10 +26,9 @@
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.hardware.fingerprint.FingerprintManager;
-import android.os.Binder;
-import android.os.DeadObjectException;
 import android.os.Handler;
 import android.os.Message;
+import android.os.RemoteCallbackList;
 import android.os.RemoteException;
 import android.os.SystemClock;
 import android.os.UserHandle;
@@ -40,7 +36,7 @@
 import android.util.Slog;
 import android.util.SparseIntArray;
 
-import java.util.ArrayList;
+import com.android.internal.widget.LockPatternUtils.StrongAuthTracker;
 
 /**
  * Keeps track of requests for strong authentication.
@@ -58,7 +54,7 @@
     private static final String STRONG_AUTH_TIMEOUT_ALARM_TAG =
             "LockSettingsStrongAuth.timeoutForUser";
 
-    private final ArrayList<IStrongAuthTracker> mStrongAuthTrackers = new ArrayList<>();
+    private final RemoteCallbackList<IStrongAuthTracker> mTrackers = new RemoteCallbackList<>();
     private final SparseIntArray mStrongAuthForUser = new SparseIntArray();
     private final ArrayMap<Integer, StrongAuthTimeoutAlarmListener>
             mStrongAuthTimeoutAlarmListenerForUser = new ArrayMap<>();
@@ -82,12 +78,7 @@
     }
 
     private void handleAddStrongAuthTracker(IStrongAuthTracker tracker) {
-        for (int i = 0; i < mStrongAuthTrackers.size(); i++) {
-            if (mStrongAuthTrackers.get(i).asBinder() == tracker.asBinder()) {
-                return;
-            }
-        }
-        mStrongAuthTrackers.add(tracker);
+        mTrackers.register(tracker);
 
         for (int i = 0; i < mStrongAuthForUser.size(); i++) {
             int key = mStrongAuthForUser.keyAt(i);
@@ -101,12 +92,7 @@
     }
 
     private void handleRemoveStrongAuthTracker(IStrongAuthTracker tracker) {
-        for (int i = 0; i < mStrongAuthTrackers.size(); i++) {
-            if (mStrongAuthTrackers.get(i).asBinder() == tracker.asBinder()) {
-                mStrongAuthTrackers.remove(i);
-                return;
-            }
-        }
+        mTrackers.unregister(tracker);
     }
 
     private void handleRequireStrongAuth(int strongAuthReason, int userId) {
@@ -157,16 +143,19 @@
     }
 
     private void notifyStrongAuthTrackers(int strongAuthReason, int userId) {
-        for (int i = 0; i < mStrongAuthTrackers.size(); i++) {
-            try {
-                mStrongAuthTrackers.get(i).onStrongAuthRequiredChanged(strongAuthReason, userId);
-            } catch (DeadObjectException e) {
-                Slog.d(TAG, "Removing dead StrongAuthTracker.");
-                mStrongAuthTrackers.remove(i);
+        int i = mTrackers.beginBroadcast();
+        try {
+            while (i > 0) {
                 i--;
-            } catch (RemoteException e) {
-                Slog.e(TAG, "Exception while notifying StrongAuthTracker.", e);
+                try {
+                    mTrackers.getBroadcastItem(i).onStrongAuthRequiredChanged(
+                            strongAuthReason, userId);
+                } catch (RemoteException e) {
+                    Slog.e(TAG, "Exception while notifying StrongAuthTracker.", e);
+                }
             }
+        } finally {
+            mTrackers.finishBroadcast();
         }
     }
 
@@ -243,4 +232,5 @@
             }
         }
     };
+
 }
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java
index 662ffc8..dee24c7 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java
@@ -44,6 +44,7 @@
 import java.security.PublicKey;
 import java.security.SecureRandom;
 import java.security.UnrecoverableKeyException;
+import java.security.cert.CertPath;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
@@ -176,8 +177,17 @@
             return;
         }
 
-        PublicKey publicKey = mRecoverableKeyStoreDb.getRecoveryServicePublicKey(mUserId,
+        PublicKey publicKey;
+        CertPath certPath = mRecoverableKeyStoreDb.getRecoveryServiceCertPath(mUserId,
                 recoveryAgentUid);
+        if (certPath != null) {
+            Log.d(TAG, "Using the public key in stored CertPath for syncing");
+            publicKey = certPath.getCertificates().get(0).getPublicKey();
+        } else {
+            Log.d(TAG, "Using the stored raw public key for syncing");
+            publicKey = mRecoverableKeyStoreDb.getRecoveryServicePublicKey(mUserId,
+                    recoveryAgentUid);
+        }
         if (publicKey == null) {
             Log.w(TAG, "Not initialized for KeySync: no public key set. Cancelling task.");
             return;
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/OWNERS b/services/core/java/com/android/server/locksettings/recoverablekeystore/OWNERS
new file mode 100644
index 0000000..bb487fb
--- /dev/null
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/OWNERS
@@ -0,0 +1,4 @@
+aseemk@google.com
+bozhu@google.com
+dementyev@google.com
+robertberry@google.com
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/PlatformKeyManager.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/PlatformKeyManager.java
index 3a78f95..e5ff5b8 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/PlatformKeyManager.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/PlatformKeyManager.java
@@ -194,6 +194,9 @@
            UnrecoverableKeyException, NoSuchAlgorithmException, InsecureUserException {
         init(userId);
         try {
+            // Try to see if the decryption key is still accessible before using the encryption key.
+            // The auth-bound decryption will be unrecoverable if the screen lock is disabled.
+            getDecryptKeyInternal(userId);
             return getEncryptKeyInternal(userId);
         } catch (UnrecoverableKeyException e) {
             Log.i(TAG, String.format(Locale.US,
@@ -219,7 +222,7 @@
            UnrecoverableKeyException, NoSuchAlgorithmException, InsecureUserException {
         int generationId = getGenerationId(userId);
         String alias = getEncryptAlias(userId, generationId);
-        if (!mKeyStore.containsAlias(alias)) {
+        if (!isKeyLoaded(userId, generationId)) {
             throw new UnrecoverableKeyException("KeyStore doesn't contain key " + alias);
         }
         AndroidKeyStoreSecretKey key = (AndroidKeyStoreSecretKey) mKeyStore.getKey(
@@ -268,7 +271,7 @@
            UnrecoverableKeyException, NoSuchAlgorithmException, InsecureUserException {
         int generationId = getGenerationId(userId);
         String alias = getDecryptAlias(userId, generationId);
-        if (!mKeyStore.containsAlias(alias)) {
+        if (!isKeyLoaded(userId, generationId)) {
             throw new UnrecoverableKeyException("KeyStore doesn't contain key " + alias);
         }
         AndroidKeyStoreSecretKey key = (AndroidKeyStoreSecretKey) mKeyStore.getKey(
@@ -300,12 +303,12 @@
             return;
         }
         if (generationId == -1) {
-            Log.i(TAG, "Generating initial platform ID.");
+            Log.i(TAG, "Generating initial platform key generation ID.");
             generationId = 1;
         } else {
             Log.w(TAG, String.format(Locale.US, "Platform generation ID was %d but no "
                     + "entry was present in AndroidKeyStore. Generating fresh key.", generationId));
-            // Had to generate a fresh key, bump the generation id
+            // Have to generate a fresh key, so bump the generation id
             generationId++;
         }
 
@@ -374,7 +377,7 @@
         String decryptAlias = getDecryptAlias(userId, generationId);
         SecretKey secretKey = generateAesKey();
 
-        // Store Since decryption key first since it is more likely to fail.
+        // Store decryption key first since it is more likely to fail.
         mKeyStore.setEntry(
                 decryptAlias,
                 new KeyStore.SecretKeyEntry(secretKey),
@@ -386,7 +389,6 @@
                     .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
                     .setBoundToSpecificSecureUserId(userId)
                     .build());
-
         mKeyStore.setEntry(
                 encryptAlias,
                 new KeyStore.SecretKeyEntry(secretKey),
@@ -397,11 +399,7 @@
 
         setGenerationId(userId, generationId);
 
-        try {
-            secretKey.destroy();
-        } catch (DestroyFailedException e) {
-            Log.w(TAG, "Failed to destroy in-memory platform key.", e);
-        }
+        // TODO: Use a reliable way to destroy the temporary secretKey in memory.
     }
 
     /**
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 fda6cdf..23a66ba 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java
@@ -23,16 +23,15 @@
 import static android.security.keystore.RecoveryController.ERROR_SERVICE_INTERNAL_ERROR;
 import static android.security.keystore.RecoveryController.ERROR_SESSION_EXPIRED;
 
+import android.Manifest;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.PendingIntent;
 import android.content.Context;
-import android.Manifest;
 import android.os.Binder;
 import android.os.RemoteException;
 import android.os.ServiceSpecificException;
 import android.os.UserHandle;
-
 import android.security.keystore.recovery.KeyChainProtectionParams;
 import android.security.keystore.recovery.KeyChainSnapshot;
 import android.security.keystore.recovery.RecoveryController;
@@ -43,6 +42,10 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.HexDump;
 import com.android.server.locksettings.recoverablekeystore.storage.ApplicationKeyStorage;
+import com.android.server.locksettings.recoverablekeystore.certificate.CertParsingException;
+import com.android.server.locksettings.recoverablekeystore.certificate.CertValidationException;
+import com.android.server.locksettings.recoverablekeystore.certificate.CertXml;
+import com.android.server.locksettings.recoverablekeystore.certificate.TrustedRootCert;
 import com.android.server.locksettings.recoverablekeystore.storage.RecoverableKeyStoreDb;
 import com.android.server.locksettings.recoverablekeystore.storage.RecoverySessionStorage;
 import com.android.server.locksettings.recoverablekeystore.storage.RecoverySnapshotStorage;
@@ -52,8 +55,10 @@
 import java.security.KeyStoreException;
 import java.security.NoSuchAlgorithmException;
 import java.security.PublicKey;
-import java.security.spec.InvalidKeySpecException;
 import java.security.UnrecoverableKeyException;
+import java.security.cert.CertPath;
+import java.security.cert.CertificateEncodingException;
+import java.security.spec.InvalidKeySpecException;
 import java.security.spec.X509EncodedKeySpec;
 import java.util.Arrays;
 import java.util.HashMap;
@@ -152,18 +157,69 @@
     }
 
     public void initRecoveryService(
-            @NonNull String rootCertificateAlias, @NonNull byte[] signedPublicKeyList)
+            @NonNull String rootCertificateAlias, @NonNull byte[] recoveryServiceCertFile)
             throws RemoteException {
         checkRecoverKeyStorePermission();
         int userId = UserHandle.getCallingUserId();
         int uid = Binder.getCallingUid();
-        // TODO: open /system/etc/security/... cert file, and check the signature on the public keys
-        PublicKey publicKey;
+
+        // TODO: Check the public-key signature on the whole file before parsing it
+
+        CertXml certXml;
+        try {
+            certXml = CertXml.parse(recoveryServiceCertFile);
+        } catch (CertParsingException e) {
+            // TODO: Do not use raw key bytes anymore once the other components are updated
+            Log.d(TAG, "Failed to parse the input as a cert file: " + HexDump.toHexString(
+                    recoveryServiceCertFile));
+            PublicKey publicKey = parseEcPublicKey(recoveryServiceCertFile);
+            if (mDatabase.setRecoveryServicePublicKey(userId, uid, publicKey) > 0) {
+                mDatabase.setShouldCreateSnapshot(userId, uid, true);
+            }
+            Log.d(TAG, "Successfully set the input as the raw public key");
+            return;
+        }
+
+        // Check serial number
+        long newSerial = certXml.getSerial();
+        Long oldSerial = mDatabase.getRecoveryServiceCertSerial(userId, uid);
+        if (oldSerial != null && oldSerial >= newSerial) {
+            if (oldSerial == newSerial) {
+                Log.i(TAG, "The cert file serial number is the same, so skip updating.");
+            } else {
+                Log.e(TAG, "The cert file serial number is older than the one in database.");
+            }
+            return;
+        }
+        Log.i(TAG, "Updating the certificate with the new serial number " + newSerial);
+
+        CertPath certPath;
+        try {
+            Log.d(TAG, "Getting and validating a random endpoint certificate");
+            certPath = certXml.getRandomEndpointCert(TrustedRootCert.TRUSTED_ROOT_CERT);
+        } catch (CertValidationException e) {
+            Log.e(TAG, "Invalid endpoint cert", e);
+            throw new ServiceSpecificException(
+                    ERROR_BAD_CERTIFICATE_FORMAT, "Failed to validate certificate.");
+        }
+        try {
+            Log.d(TAG, "Saving the randomly chosen endpoint certificate to database");
+            if (mDatabase.setRecoveryServiceCertPath(userId, uid, certPath) > 0) {
+                mDatabase.setRecoveryServiceCertSerial(userId, uid, newSerial);
+                mDatabase.setShouldCreateSnapshot(userId, uid, true);
+            }
+        } catch (CertificateEncodingException e) {
+            Log.e(TAG, "Failed to encode CertPath", e);
+            throw new ServiceSpecificException(
+                    ERROR_BAD_CERTIFICATE_FORMAT, "Failed to encode CertPath.");
+        }
+    }
+
+    private PublicKey parseEcPublicKey(@NonNull byte[] bytes) throws ServiceSpecificException {
         try {
             KeyFactory kf = KeyFactory.getInstance("EC");
-            // TODO: Randomly choose a key from the list -- right now we just use the whole input
-            X509EncodedKeySpec pkSpec = new X509EncodedKeySpec(signedPublicKeyList);
-            publicKey = kf.generatePublic(pkSpec);
+            X509EncodedKeySpec pkSpec = new X509EncodedKeySpec(bytes);
+            return kf.generatePublic(pkSpec);
         } catch (NoSuchAlgorithmException e) {
             Log.wtf(TAG, "EC algorithm not available. AOSP must support this.", e);
             throw new ServiceSpecificException(ERROR_SERVICE_INTERNAL_ERROR, e.getMessage());
@@ -171,10 +227,6 @@
             throw new ServiceSpecificException(
                     ERROR_BAD_CERTIFICATE_FORMAT, "Not a valid X509 certificate.");
         }
-        long updatedRows = mDatabase.setRecoveryServicePublicKey(userId, uid, publicKey);
-        if (updatedRows > 0) {
-            mDatabase.setShouldCreateSnapshot(userId, uid, true);
-        }
     }
 
     /**
@@ -519,11 +571,11 @@
         byte[] locallyEncryptedKey;
         try {
             // TODO: Remove the extraneous logging here
-            Log.e(TAG, constructLoggingMessage("sessionEntry.getKeyClaimant()",
+            Log.d(TAG, constructLoggingMessage("sessionEntry.getKeyClaimant()",
                     sessionEntry.getKeyClaimant()));
-            Log.e(TAG, constructLoggingMessage("sessionEntry.getVaultParams()",
+            Log.d(TAG, constructLoggingMessage("sessionEntry.getVaultParams()",
                     sessionEntry.getVaultParams()));
-            Log.e(TAG, constructLoggingMessage("encryptedClaimResponse", encryptedClaimResponse));
+            Log.d(TAG, constructLoggingMessage("encryptedClaimResponse", encryptedClaimResponse));
             locallyEncryptedKey = KeySyncUtils.decryptRecoveryClaimResponse(
                     sessionEntry.getKeyClaimant(),
                     sessionEntry.getVaultParams(),
@@ -543,9 +595,9 @@
 
         try {
             // TODO: Remove the extraneous logging here
-            Log.e(TAG, constructLoggingMessage("sessionEntry.getLskfHash()",
+            Log.d(TAG, constructLoggingMessage("sessionEntry.getLskfHash()",
                     sessionEntry.getLskfHash()));
-            Log.e(TAG, constructLoggingMessage("locallyEncryptedKey", locallyEncryptedKey));
+            Log.d(TAG, constructLoggingMessage("locallyEncryptedKey", locallyEncryptedKey));
             return KeySyncUtils.decryptRecoveryKey(sessionEntry.getLskfHash(), locallyEncryptedKey);
         } catch (InvalidKeyException e) {
             Log.e(TAG, "Got InvalidKeyException during decrypting recovery key", e);
@@ -585,8 +637,8 @@
 
             try {
                 // TODO: Remove the extraneous logging here
-                Log.e(TAG, constructLoggingMessage("recoveryKey", recoveryKey));
-                Log.e(TAG, constructLoggingMessage("encryptedKeyMaterial", encryptedKeyMaterial));
+                Log.d(TAG, constructLoggingMessage("recoveryKey", recoveryKey));
+                Log.d(TAG, constructLoggingMessage("encryptedKeyMaterial", encryptedKeyMaterial));
                 byte[] keyMaterial =
                         KeySyncUtils.decryptApplicationKey(recoveryKey, encryptedKeyMaterial);
                 keyMaterialByAlias.put(alias, keyMaterial);
@@ -600,13 +652,16 @@
                 throw new ServiceSpecificException(ERROR_DECRYPTION_FAILED,
                         "Failed to recover key with alias '" + alias + "': " + e.getMessage());
             } catch (AEADBadTagException e) {
-                // TODO: Remove the extraneous logging here
                 Log.e(TAG, "Got AEADBadTagException during decrypting application key with alias: "
                         + alias, e);
-                throw new ServiceSpecificException(ERROR_DECRYPTION_FAILED,
-                        "Failed to recover key with alias '" + alias + "': " + e.getMessage());
+                // Ignore the exception to continue to recover the other application keys.
             }
         }
+        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.");
+        }
         return keyMaterialByAlias;
     }
 
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/certificate/CertUtils.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/certificate/CertUtils.java
index 985f5b6..09ec5ad 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/certificate/CertUtils.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/certificate/CertUtils.java
@@ -18,6 +18,7 @@
 
 import static javax.xml.xpath.XPathConstants.NODESET;
 
+import android.annotation.IntDef;
 import android.annotation.Nullable;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -25,6 +26,8 @@
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.security.InvalidAlgorithmParameterException;
 import java.security.InvalidKeyException;
 import java.security.NoSuchAlgorithmException;
@@ -65,20 +68,21 @@
 import org.xml.sax.SAXException;
 
 /** Utility functions related to parsing and validating public-key certificates. */
-final class CertUtils {
+public final class CertUtils {
 
     private static final String CERT_FORMAT = "X.509";
     private static final String CERT_PATH_ALG = "PKIX";
     private static final String CERT_STORE_ALG = "Collection";
     private static final String SIGNATURE_ALG = "SHA256withRSA";
 
-    private CertUtils() {}
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({MUST_EXIST_UNENFORCED, MUST_EXIST_EXACTLY_ONE, MUST_EXIST_AT_LEAST_ONE})
+    @interface MustExist {}
+    static final int MUST_EXIST_UNENFORCED = 0;
+    static final int MUST_EXIST_EXACTLY_ONE = 1;
+    static final int MUST_EXIST_AT_LEAST_ONE = 2;
 
-    enum MustExist {
-        FALSE,
-        EXACTLY_ONE,
-        AT_LEAST_ONE,
-    }
+    private CertUtils() {}
 
     /**
      * Decodes a byte array containing an encoded X509 certificate.
@@ -159,7 +163,7 @@
      * @return a list of strings that are the text contents of the child nodes
      * @throws CertParsingException if any parsing error occurs
      */
-    static List<String> getXmlNodeContents(MustExist mustExist, Element rootNode,
+    static List<String> getXmlNodeContents(@MustExist int mustExist, Element rootNode,
             String... nodeTags)
             throws CertParsingException {
         String expression = String.join("/", nodeTags);
@@ -173,10 +177,10 @@
         }
 
         switch (mustExist) {
-            case FALSE:
+            case MUST_EXIST_UNENFORCED:
                 break;
 
-            case EXACTLY_ONE:
+            case MUST_EXIST_EXACTLY_ONE:
                 if (nodeList.getLength() != 1) {
                     throw new CertParsingException(
                             "The XML file must contain exactly one node with the path "
@@ -184,7 +188,7 @@
                 }
                 break;
 
-            case AT_LEAST_ONE:
+            case MUST_EXIST_AT_LEAST_ONE:
                 if (nodeList.getLength() == 0) {
                     throw new CertParsingException(
                             "The XML file must contain at least one node with the path "
@@ -194,7 +198,7 @@
 
             default:
                 throw new UnsupportedOperationException(
-                        "This enum value of MustExist is not supported: " + mustExist);
+                        "This value of MustExist is not supported: " + mustExist);
         }
 
         List<String> result = new ArrayList<>();
@@ -213,7 +217,7 @@
      * @return the decoding decoding result
      * @throws CertParsingException if the input string is not a properly base64-encoded string
      */
-    static byte[] decodeBase64(String str) throws CertParsingException {
+    public static byte[] decodeBase64(String str) throws CertParsingException {
         try {
             return Base64.getDecoder().decode(str);
         } catch (IllegalArgumentException e) {
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/certificate/CertXml.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/certificate/CertXml.java
index 2c04a86..c62a31e 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/certificate/CertXml.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/certificate/CertXml.java
@@ -129,7 +129,7 @@
     private static long parseSerial(Element rootNode) throws CertParsingException {
         List<String> contents =
                 CertUtils.getXmlNodeContents(
-                        CertUtils.MustExist.EXACTLY_ONE,
+                        CertUtils.MUST_EXIST_EXACTLY_ONE,
                         rootNode,
                         METADATA_NODE_TAG,
                         METADATA_SERIAL_NODE_TAG);
@@ -139,7 +139,7 @@
     private static long parseRefreshInterval(Element rootNode) throws CertParsingException {
         List<String> contents =
                 CertUtils.getXmlNodeContents(
-                        CertUtils.MustExist.EXACTLY_ONE,
+                        CertUtils.MUST_EXIST_EXACTLY_ONE,
                         rootNode,
                         METADATA_NODE_TAG,
                         METADATA_REFRESH_INTERVAL_NODE_TAG);
@@ -150,7 +150,7 @@
             throws CertParsingException {
         List<String> contents =
                 CertUtils.getXmlNodeContents(
-                        CertUtils.MustExist.FALSE,
+                        CertUtils.MUST_EXIST_UNENFORCED,
                         rootNode,
                         INTERMEDIATE_CERT_LIST_TAG,
                         INTERMEDIATE_CERT_ITEM_TAG);
@@ -165,7 +165,7 @@
             throws CertParsingException {
         List<String> contents =
                 CertUtils.getXmlNodeContents(
-                        CertUtils.MustExist.AT_LEAST_ONE,
+                        CertUtils.MUST_EXIST_AT_LEAST_ONE,
                         rootNode,
                         ENDPOINT_CERT_LIST_TAG,
                         ENDPOINT_CERT_ITEM_TAG);
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/certificate/SigXml.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/certificate/SigXml.java
index 878fc6e..e75be85 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/certificate/SigXml.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/certificate/SigXml.java
@@ -94,7 +94,7 @@
             throws CertParsingException {
         List<String> contents =
                 CertUtils.getXmlNodeContents(
-                        CertUtils.MustExist.FALSE,
+                        CertUtils.MUST_EXIST_UNENFORCED,
                         rootNode,
                         INTERMEDIATE_CERT_LIST_TAG,
                         INTERMEDIATE_CERT_ITEM_TAG);
@@ -108,14 +108,14 @@
     private static X509Certificate parseSignerCert(Element rootNode) throws CertParsingException {
         List<String> contents =
                 CertUtils.getXmlNodeContents(
-                        CertUtils.MustExist.EXACTLY_ONE, rootNode, SIGNER_CERT_NODE_TAG);
+                        CertUtils.MUST_EXIST_EXACTLY_ONE, rootNode, SIGNER_CERT_NODE_TAG);
         return CertUtils.decodeCert(CertUtils.decodeBase64(contents.get(0)));
     }
 
     private static byte[] parseFileSignature(Element rootNode) throws CertParsingException {
         List<String> contents =
                 CertUtils.getXmlNodeContents(
-                        CertUtils.MustExist.EXACTLY_ONE, rootNode, SIGNATURE_NODE_TAG);
+                        CertUtils.MUST_EXIST_EXACTLY_ONE, rootNode, SIGNATURE_NODE_TAG);
         return CertUtils.decodeBase64(contents.get(0));
     }
 }
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/certificate/TrustedRootCert.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/certificate/TrustedRootCert.java
new file mode 100644
index 0000000..7195d62
--- /dev/null
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/certificate/TrustedRootCert.java
@@ -0,0 +1,74 @@
+/*
+ * 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.locksettings.recoverablekeystore.certificate;
+
+import java.security.cert.X509Certificate;
+
+/**
+ * Holds the X509 certificate of the trusted root CA cert for the recoverable key store service.
+ *
+ * TODO: Read the certificate from a PEM file directly and remove this class.
+ */
+public final class TrustedRootCert {
+
+    private  static final String TRUSTED_ROOT_CERT_BASE64 = ""
+            + "MIIFJjCCAw6gAwIBAgIJAIobXsJlzhNdMA0GCSqGSIb3DQEBDQUAMCAxHjAcBgNV"
+            + "BAMMFUdvb2dsZSBDcnlwdEF1dGhWYXVsdDAeFw0xODAyMDIxOTM5MTRaFw0zODAx"
+            + "MjgxOTM5MTRaMCAxHjAcBgNVBAMMFUdvb2dsZSBDcnlwdEF1dGhWYXVsdDCCAiIw"
+            + "DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK2OT5i40/H7LINg/lq/0G0hR65P"
+            + "Q4Mud3OnuVt6UIYV2T18+v6qW1yJd5FcnND/ZKPau4aUAYklqJuSVjOXQD0BjgS2"
+            + "98Xa4dSn8Ci1rUR+5tdmrxqbYUdT2ZvJIUMMR6fRoqi+LlAbKECrV+zYQTyLU68w"
+            + "V66hQpAButjJKiZzkXjmKLfJ5IWrNEn17XM988rk6qAQn/BYCCQGf3rQuJeksGmA"
+            + "N1lJOwNYxmWUyouVwqwZthNEWqTuEyBFMkAT+99PXW7oVDc7oU5cevuihxQWNTYq"
+            + "viGB8cck6RW3cmqrDSaJF/E+N0cXFKyYC7FDcggt6k3UrxNKTuySdDEa8+2RTQqU"
+            + "Y9npxBlQE+x9Ig56OI1BG3bSBsGdPgjpyHadZeh2tgk+oqlGsSsum24YxaxuSysT"
+            + "Qfcu/XhyfUXavfmGrBOXerTzIl5oBh/F5aHTV85M2tYEG0qsPPvSpZAWtdJ/2rca"
+            + "OxvhwOL+leZKr8McjXVR00lBsRuKXX4nTUMwya09CO3QHFPFZtZvqjy2HaMOnVLQ"
+            + "I6b6dHEfmsHybzVOe3yPEoFQSU9UhUdmi71kwwoanPD3j9fJHmXTx4PzYYBRf1ZE"
+            + "o+uPgMPk7CDKQFZLjnR40z1uzu3O8aZ3AKZzP+j7T4XQKJLQLmllKtPgLgNdJyib"
+            + "2Glg7QhXH/jBTL6hAgMBAAGjYzBhMB0GA1UdDgQWBBSbZfrqOYH54EJpkdKMZjMc"
+            + "z/Hp+DAfBgNVHSMEGDAWgBSbZfrqOYH54EJpkdKMZjMcz/Hp+DAPBgNVHRMBAf8E"
+            + "BTADAQH/MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQ0FAAOCAgEAKh9nm/vW"
+            + "glMWp3vcCwWwJW286ecREDlI+CjGh5h+f2N4QRrXd/tKE3qQJWCqGx8sFfIUjmI7"
+            + "KYdsC2gyQ2cA2zl0w7pB2QkuqE6zVbnh1D17Hwl19IMyAakFaM9ad4/EoH7oQmqX"
+            + "nF/f5QXGZw4kf1HcgKgoCHWXjqR8MqHOcXR8n6WFqxjzJf1jxzi6Yo2dZ7PJbnE6"
+            + "+kHIJuiCpiHL75v5g1HM41gT3ddFFSrn88ThNPWItT5Z8WpFjryVzank2Yt02LLl"
+            + "WqZg9IC375QULc5B58NMnaiVJIDJQ8zoNgj1yaxqtUMnJX570lotO2OXe4ec9aCQ"
+            + "DIJ84YLM/qStFdeZ9416E80dchskbDG04GuVJKlzWjxAQNMRFhyaPUSBTLLg+kwP"
+            + "t9+AMmc+A7xjtFQLZ9fBYHOBsndJOmeSQeYeckl+z/1WQf7DdwXn/yijon7mxz4z"
+            + "cCczfKwTJTwBh3wR5SQr2vQm7qaXM87qxF8PCAZrdZaw5I80QwkgTj0WTZ2/GdSw"
+            + "d3o5SyzzBAjpwtG+4bO/BD9h9wlTsHpT6yWOZs4OYAKU5ykQrncI8OyavMggArh3"
+            + "/oM58v0orUWINtIc2hBlka36PhATYQiLf+AiWKnwhCaaHExoYKfQlMtXBodNvOK8"
+            + "xqx69x05q/qbHKEcTHrsss630vxrp1niXvA=";
+
+    /**
+     * The X509 certificate of the trusted root CA cert for the recoverable key store service.
+     *
+     * TODO: Change it to the production certificate root CA before the final launch.
+     */
+    public static final X509Certificate TRUSTED_ROOT_CERT;
+
+    static {
+        try {
+            TRUSTED_ROOT_CERT = CertUtils.decodeCert(
+                    CertUtils.decodeBase64(TRUSTED_ROOT_CERT_BASE64));
+        } catch (CertParsingException e) {
+            // Should not happen
+            throw new RuntimeException(e);
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDb.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDb.java
index b96208d..89ddb6c 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDb.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDb.java
@@ -31,9 +31,14 @@
 import com.android.server.locksettings.recoverablekeystore.storage.RecoverableKeyStoreDbContract.RecoveryServiceMetadataEntry;
 import com.android.server.locksettings.recoverablekeystore.storage.RecoverableKeyStoreDbContract.UserMetadataEntry;
 
+import java.io.ByteArrayInputStream;
 import java.security.KeyFactory;
 import java.security.NoSuchAlgorithmException;
 import java.security.PublicKey;
+import java.security.cert.CertPath;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
 import java.security.spec.InvalidKeySpecException;
 import java.security.spec.X509EncodedKeySpec;
 import java.util.ArrayList;
@@ -53,6 +58,7 @@
     private static final String TAG = "RecoverableKeyStoreDb";
     private static final int IDLE_TIMEOUT_SECONDS = 30;
     private static final int LAST_SYNCED_AT_UNSYNCED = -1;
+    private static final String CERT_PATH_ENCODING = "PkiPath";
 
     private final RecoverableKeyStoreDbHelper mKeyStoreDbHelper;
 
@@ -361,6 +367,79 @@
     }
 
     /**
+     * Returns the serial number of the XML file containing certificates of the recovery service.
+     *
+     * @param userId The userId of the profile the application is running under.
+     * @param uid The uid of the application who initializes the local recovery components.
+     * @return The value that were previously set, or null if there's none.
+     *
+     * @hide
+     */
+    @Nullable
+    public Long getRecoveryServiceCertSerial(int userId, int uid) {
+        return getLong(userId, uid, RecoveryServiceMetadataEntry.COLUMN_NAME_CERT_SERIAL);
+    }
+
+    /**
+     * Records the serial number of the XML file containing certificates of the recovery service.
+     *
+     * @param userId The userId of the profile the application is running under.
+     * @param uid The uid of the application who initializes the local recovery components.
+     * @param serial The serial number contained in the XML file for recovery service certificates.
+     * @return The primary key of the inserted row, or -1 if failed.
+     *
+     * @hide
+     */
+    public long setRecoveryServiceCertSerial(int userId, int uid, long serial) {
+        return setLong(userId, uid, RecoveryServiceMetadataEntry.COLUMN_NAME_CERT_SERIAL, serial);
+    }
+
+    /**
+     * Returns the {@code CertPath} of the recovery service.
+     *
+     * @param userId The userId of the profile the application is running under.
+     * @param uid The uid of the application who initializes the local recovery components.
+     * @return The value that were previously set, or null if there's none.
+     *
+     * @hide
+     */
+    @Nullable
+    public CertPath getRecoveryServiceCertPath(int userId, int uid) {
+        byte[] bytes = getBytes(userId, uid, RecoveryServiceMetadataEntry.COLUMN_NAME_CERT_PATH);
+        if (bytes == null) {
+            return null;
+        }
+        try {
+            return decodeCertPath(bytes);
+        } catch (CertificateException e) {
+            Log.wtf(TAG,
+                    String.format(Locale.US,
+                            "Recovery service CertPath entry cannot be decoded for "
+                                    + "userId=%d uid=%d.",
+                            userId, uid), e);
+            return null;
+        }
+    }
+
+    /**
+     * Sets the {@code CertPath} of the recovery service.
+     *
+     * @param userId The userId of the profile the application is running under.
+     * @param uid The uid of the application who initializes the local recovery components.
+     * @param certPath The certificate path of the recovery service.
+     * @return The primary key of the inserted row, or -1 if failed.
+     * @hide
+     */
+    public long setRecoveryServiceCertPath(int userId, int uid, CertPath certPath) throws
+            CertificateEncodingException {
+        if (certPath.getCertificates().size() == 0) {
+            throw new CertificateEncodingException("No certificate contained in the cert path.");
+        }
+        return setBytes(userId, uid, RecoveryServiceMetadataEntry.COLUMN_NAME_CERT_PATH,
+                certPath.getEncoded(CERT_PATH_ENCODING));
+    }
+
+    /**
      * Returns the list of recovery agents initialized for given {@code userId}
      * @param userId The userId of the profile the application is running under.
      * @return The list of recovery agents
@@ -515,48 +594,6 @@
     }
 
     /**
-     * Returns the first (and only?) public key for {@code userId}.
-     *
-     * @param userId The userId of the profile whose keys are to be synced.
-     * @return The public key, or null if none exists.
-     */
-    @Nullable
-    public PublicKey getRecoveryServicePublicKey(int userId) {
-        SQLiteDatabase db = mKeyStoreDbHelper.getReadableDatabase();
-
-        String[] projection = { RecoveryServiceMetadataEntry.COLUMN_NAME_PUBLIC_KEY };
-        String selection =
-                RecoveryServiceMetadataEntry.COLUMN_NAME_USER_ID + " = ?";
-        String[] selectionArguments = { Integer.toString(userId) };
-
-        try (
-            Cursor cursor = db.query(
-                    RecoveryServiceMetadataEntry.TABLE_NAME,
-                    projection,
-                    selection,
-                    selectionArguments,
-                    /*groupBy=*/ null,
-                    /*having=*/ null,
-                    /*orderBy=*/ null)
-        ) {
-            if (cursor.getCount() < 1) {
-                return null;
-            }
-
-            cursor.moveToFirst();
-            byte[] keyBytes = cursor.getBlob(cursor.getColumnIndexOrThrow(
-                    RecoveryServiceMetadataEntry.COLUMN_NAME_PUBLIC_KEY));
-
-            try {
-                return decodeX509Key(keyBytes);
-            } catch (InvalidKeySpecException e) {
-                Log.wtf(TAG, "Could not decode public key for " + userId);
-                return null;
-            }
-        }
-    }
-
-    /**
      * Updates the counterId
      *
      * @param userId The userId of the profile the application is running under.
@@ -585,7 +622,6 @@
         return getLong(userId, uid, RecoveryServiceMetadataEntry.COLUMN_NAME_COUNTER_ID);
     }
 
-
     /**
      * Updates the server parameters given by the application initializing the local recovery
      * components.
@@ -869,4 +905,16 @@
             throw new RuntimeException(e);
         }
     }
+
+    @Nullable
+    private static CertPath decodeCertPath(byte[] bytes) throws CertificateException {
+        CertificateFactory certFactory;
+        try {
+            certFactory = CertificateFactory.getInstance("X.509");
+        } catch (CertificateException e) {
+            // Should not happen, as X.509 is mandatory for all providers.
+            throw new RuntimeException(e);
+        }
+        return certFactory.generateCertPath(new ByteArrayInputStream(bytes), CERT_PATH_ENCODING);
+    }
 }
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbContract.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbContract.java
index 4ee282b..1cb5d91 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbContract.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbContract.java
@@ -104,9 +104,10 @@
         static final String COLUMN_NAME_UID = "uid";
 
         /**
-         * Version of the latest recovery snapshot
+         * Version of the latest recovery snapshot.
          */
         static final String COLUMN_NAME_SNAPSHOT_VERSION = "snapshot_version";
+
         /**
          * Flag to generate new snapshot.
          */
@@ -118,6 +119,16 @@
         static final String COLUMN_NAME_PUBLIC_KEY = "public_key";
 
         /**
+         * The certificate path of the recovery service.
+         */
+        static final String COLUMN_NAME_CERT_PATH = "cert_path";
+
+        /**
+         * The serial number contained in the certificate XML file of the recovery service.
+         */
+        static final String COLUMN_NAME_CERT_SERIAL = "cert_serial";
+
+        /**
          * Secret types used for end-to-end encryption.
          */
         static final String COLUMN_NAME_SECRET_TYPES = "secret_types";
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbHelper.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbHelper.java
index 79fd496..8a89f2d 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbHelper.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbHelper.java
@@ -19,6 +19,7 @@
 import android.content.Context;
 import android.database.sqlite.SQLiteDatabase;
 import android.database.sqlite.SQLiteOpenHelper;
+import android.util.Log;
 
 import com.android.server.locksettings.recoverablekeystore.storage.RecoverableKeyStoreDbContract.KeysEntry;
 import com.android.server.locksettings.recoverablekeystore.storage.RecoverableKeyStoreDbContract.RecoveryServiceMetadataEntry;
@@ -28,7 +29,9 @@
  * Helper for creating the recoverable key database.
  */
 class RecoverableKeyStoreDbHelper extends SQLiteOpenHelper {
-    private static final int DATABASE_VERSION = 2;
+    private static final String TAG = "RecoverableKeyStoreDbHp";
+
+    static final int DATABASE_VERSION = 3;
     private static final String DATABASE_NAME = "recoverablekeystore.db";
 
     private static final String SQL_CREATE_KEYS_ENTRY =
@@ -59,6 +62,8 @@
                     + RecoveryServiceMetadataEntry.COLUMN_NAME_SNAPSHOT_VERSION + " INTEGER,"
                     + RecoveryServiceMetadataEntry.COLUMN_NAME_SHOULD_CREATE_SNAPSHOT + " INTEGER,"
                     + RecoveryServiceMetadataEntry.COLUMN_NAME_PUBLIC_KEY + " BLOB,"
+                    + RecoveryServiceMetadataEntry.COLUMN_NAME_CERT_PATH + " BLOB,"
+                    + RecoveryServiceMetadataEntry.COLUMN_NAME_CERT_SERIAL + " INTEGER,"
                     + RecoveryServiceMetadataEntry.COLUMN_NAME_SECRET_TYPES + " TEXT,"
                     + RecoveryServiceMetadataEntry.COLUMN_NAME_COUNTER_ID + " INTEGER,"
                     + RecoveryServiceMetadataEntry.COLUMN_NAME_SERVER_PARAMS + " BLOB,"
@@ -88,9 +93,39 @@
 
     @Override
     public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
-        db.execSQL(SQL_DELETE_KEYS_ENTRY);
-        db.execSQL(SQL_DELETE_USER_METADATA_ENTRY);
-        db.execSQL(SQL_DELETE_RECOVERY_SERVICE_METADATA_ENTRY);
-        onCreate(db);
+        if (oldVersion < 2) {
+            db.execSQL(SQL_DELETE_KEYS_ENTRY);
+            db.execSQL(SQL_DELETE_USER_METADATA_ENTRY);
+            db.execSQL(SQL_DELETE_RECOVERY_SERVICE_METADATA_ENTRY);
+            onCreate(db);
+            return;
+        }
+
+        if (oldVersion < 3) {
+            upgradeDbForVersion3(db);
+        }
+    }
+
+    private void upgradeDbForVersion3(SQLiteDatabase db) {
+        // Add the two columns for cert path and cert serial number
+        addColumnToTable(db, RecoveryServiceMetadataEntry.TABLE_NAME,
+                RecoveryServiceMetadataEntry.COLUMN_NAME_CERT_PATH, "BLOB", /*defaultStr=*/ null);
+        addColumnToTable(db, RecoveryServiceMetadataEntry.TABLE_NAME,
+                RecoveryServiceMetadataEntry.COLUMN_NAME_CERT_SERIAL, "INTEGER", /*defaultStr=*/
+                null);
+    }
+
+    private static void addColumnToTable(
+            SQLiteDatabase db, String tableName, String column, String columnType,
+            String defaultStr) {
+        Log.d(TAG, "Adding column " + column + " to " + tableName + ".");
+
+        String alterStr = "ALTER TABLE " + tableName + " ADD COLUMN " + column + " " + columnType;
+        if (defaultStr != null && !defaultStr.isEmpty()) {
+            alterStr += " DEFAULT " + defaultStr;
+        }
+
+        db.execSQL(alterStr + ";");
     }
 }
+
diff --git a/services/core/java/com/android/server/media/AudioPlayerStateMonitor.java b/services/core/java/com/android/server/media/AudioPlayerStateMonitor.java
index 7881a95..648c782 100644
--- a/services/core/java/com/android/server/media/AudioPlayerStateMonitor.java
+++ b/services/core/java/com/android/server/media/AudioPlayerStateMonitor.java
@@ -289,6 +289,7 @@
         }
     }
 
+    @GuardedBy("mLock")
     private void sendAudioPlayerActiveStateChangedMessageLocked(
             final AudioPlaybackConfiguration config, final boolean isRemoved) {
         for (MessageHandler messageHandler : mListenerMap.values()) {
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index b877184..21d86c4 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -29,6 +29,7 @@
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
+import android.content.IntentFilter;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.ResolveInfo;
@@ -76,6 +77,7 @@
 import android.view.KeyEvent;
 import android.view.ViewConfiguration;
 
+import com.android.internal.os.BackgroundThread;
 import com.android.internal.util.DumpUtils;
 import com.android.server.SystemService;
 import com.android.server.Watchdog;
@@ -180,9 +182,8 @@
 
         updateUser();
 
+        registerPackageBroadcastReceivers();
         // TODO(jaewan): Query per users
-        // TODO(jaewan): Add listener to know changes in list of services.
-        //               Refer TvInputManagerService.registerBroadcastReceivers()
         buildMediaSessionService2List();
     }
 
@@ -437,12 +438,74 @@
         mHandler.postSessionsChanged(session.getUserId());
     }
 
+    private void registerPackageBroadcastReceivers() {
+        // TODO(jaewan): Only consider changed packages when building session service list
+        //               when we make this multi-user aware. At that time,
+        //               use PackageMonitor.getChangingUserId() to know which user has changed.
+        IntentFilter filter = new IntentFilter();
+        filter.addDataScheme("package");
+        filter.addAction(Intent.ACTION_PACKAGE_ADDED);
+        filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
+        filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
+        filter.addAction(Intent.ACTION_PACKAGES_SUSPENDED);
+        filter.addAction(Intent.ACTION_PACKAGES_UNSUSPENDED);
+        filter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
+        filter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
+        filter.addAction(Intent.ACTION_PACKAGE_REPLACED);
+
+        getContext().registerReceiverAsUser(new BroadcastReceiver() {
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                final int changeUserId = intent.getIntExtra(
+                        Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
+                if (changeUserId == UserHandle.USER_NULL) {
+                    Log.w(TAG, "Intent broadcast does not contain user handle: "+ intent);
+                    return;
+                }
+                // Check if the package is replacing (i.e. reinstalling)
+                final boolean isReplacing = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
+                // TODO(jaewan): Add multi-user support with this.
+                // final int uid = intent.getIntExtra(Intent.EXTRA_UID, 0);
+
+                if (DEBUG) {
+                    Log.d(TAG, "Received change in packages, intent=" + intent);
+                }
+                switch (intent.getAction()) {
+                    case Intent.ACTION_PACKAGE_ADDED:
+                    case Intent.ACTION_PACKAGE_REMOVED:
+                    case Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE:
+                    case Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE:
+                        if (isReplacing) {
+                            // Ignore if the package(s) are replacing. In that case, followings will
+                            // happen in order.
+                            //    1. ACTION_PACKAGE_REMOVED with isReplacing=true
+                            //    2. ACTION_PACKAGE_ADDED with isReplacing=true
+                            //    3. ACTION_PACKAGE_REPLACED
+                            //    (Note that ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE and
+                            //     ACTION_EXTERNAL_APPLICATIONS_AVAILABLE will be also called with
+                            //     isReplacing=true for both ASEC hosted packages and packages in
+                            //     external storage)
+                            // Since we only want to update session service list once, ignore
+                            // actions above when replacing.
+                            // Replacing will be handled only once with the ACTION_PACKAGE_REPLACED.
+                            break;
+                        }
+                        // pass-through
+                    case Intent.ACTION_PACKAGE_CHANGED:
+                    case Intent.ACTION_PACKAGES_SUSPENDED:
+                    case Intent.ACTION_PACKAGES_UNSUSPENDED:
+                    case Intent.ACTION_PACKAGE_REPLACED:
+                        buildMediaSessionService2List();
+                }
+            }
+        }, UserHandle.ALL, filter, null, BackgroundThread.getHandler());
+    }
+
     private void buildMediaSessionService2List() {
         if (DEBUG) {
             Log.d(TAG, "buildMediaSessionService2List");
         }
-
-        // TODO(jaewan): Query per users.
+        // TODO(jaewan): Also query for managed profile users.
         // TODO(jaewan): Similar codes are also at the updatable. Can't we share codes?
         PackageManager manager = getContext().getPackageManager();
         List<ResolveInfo> services = new ArrayList<>();
@@ -458,9 +521,13 @@
             services.addAll(sessionServices);
         }
         synchronized (mLock) {
-            mSessions.clear();
-            if (services == null) {
-                return;
+            // List to keep the session services that need be removed because they don't exist
+            // in the 'services' above.
+            List<MediaSession2Record> removeCandidates = new ArrayList<>();
+            for (int i = 0; i < mSessions.size(); i++) {
+                if (mSessions.get(i).getToken().getType() != TYPE_SESSION) {
+                    removeCandidates.add(mSessions.get(i));
+                }
             }
             for (int i = 0; i < services.size(); i++) {
                 if (services.get(i) == null || services.get(i).serviceInfo == null) {
@@ -475,17 +542,35 @@
                 } catch (NameNotFoundException e) {
                     continue;
                 }
-
+                SessionToken2 token;
                 try {
-                    SessionToken2 token = new SessionToken2(getContext(),
+                    token = new SessionToken2(getContext(),
                             serviceInfo.packageName, serviceInfo.name, uid);
+                } catch (IllegalArgumentException e) {
+                    Log.w(TAG, "Invalid session service", e);
+                    continue;
+                }
+                boolean found = false;
+                for (int j = 0; j < mSessions.size(); j++) {
+                    if (token.equals(mSessions.get(j).getToken())) {
+                        // If the token already exists, keep it in the mSessions.
+                        removeCandidates.remove(mSessions.get(j));
+                        found = true;
+                        break;
+                    }
+                }
+                if (!found) {
+                    // New session service is found.
                     MediaSession2Record record = new MediaSession2Record(getContext(),
                             token, mSessionDestroyedListener);
                     mSessions.add(record);
-                } catch (IllegalArgumentException e) {
-                    Log.d(TAG, "Invalid session service", e);
                 }
             }
+            for (int i = 0; i < removeCandidates.size(); i++) {
+                removeCandidates.get(i).onSessionDestroyed();
+                mSessions.remove(removeCandidates.get(i));
+            }
+            removeCandidates.clear();
         }
         if (DEBUG) {
             Log.d(TAG, "Found " + mSessions.size() + " session services");
@@ -1503,12 +1588,14 @@
             return tokens;
         }
 
+        // TODO(jaewan): Protect this API with permission
         @Override
         public void addSessionTokensListener(ISessionTokensListener listener, int userId,
                 String packageName) {
             // TODO(jaewan): Implement.
         }
 
+        // TODO(jaewan): Protect this API with permission
         @Override
         public void removeSessionTokensListener(ISessionTokensListener listener) {
             // TODO(jaewan): Implement
diff --git a/services/core/java/com/android/server/media/OWNERS b/services/core/java/com/android/server/media/OWNERS
new file mode 100644
index 0000000..6f8d823
--- /dev/null
+++ b/services/core/java/com/android/server/media/OWNERS
@@ -0,0 +1,2 @@
+lajos@google.com
+elaurent@google.com
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index a6f049e..bd9ec55 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -145,7 +145,9 @@
 import android.net.wifi.WifiConfiguration;
 import android.net.wifi.WifiManager;
 import android.os.Binder;
+import android.os.Build;
 import android.os.Environment;
+import android.os.BestClock;
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.IDeviceIdleController;
@@ -163,6 +165,7 @@
 import android.os.ResultReceiver;
 import android.os.ServiceManager;
 import android.os.ShellCallback;
+import android.os.SystemClock;
 import android.os.SystemProperties;
 import android.os.Trace;
 import android.os.UserHandle;
@@ -182,7 +185,6 @@
 import android.util.AtomicFile;
 import android.util.DataUnit;
 import android.util.Log;
-import android.util.NtpTrustedTime;
 import android.util.Pair;
 import android.util.RecurrenceRule;
 import android.util.Slog;
@@ -190,7 +192,6 @@
 import android.util.SparseBooleanArray;
 import android.util.SparseIntArray;
 import android.util.SparseLongArray;
-import android.util.TrustedTime;
 import android.util.Xml;
 
 import com.android.internal.R;
@@ -225,7 +226,9 @@
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.nio.charset.StandardCharsets;
+import java.time.Clock;
 import java.time.ZoneId;
+import java.time.ZoneOffset;
 import java.time.ZonedDateTime;
 import java.util.ArrayList;
 import java.util.Calendar;
@@ -334,8 +337,6 @@
     private static final String ACTION_SNOOZE_RAPID =
             "com.android.server.net.action.SNOOZE_RAPID";
 
-    private static final long TIME_CACHE_MAX_AGE = DAY_IN_MILLIS;
-
     /**
      * Indicates the maximum wait time for admin data to be available;
      */
@@ -361,7 +362,7 @@
     private final INetworkStatsService mNetworkStats;
     private final INetworkManagementService mNetworkManager;
     private UsageStatsManagerInternal mUsageStats;
-    private final TrustedTime mTime;
+    private final Clock mClock;
     private final UserManager mUserManager;
     private final CarrierConfigManager mCarrierConfigManager;
 
@@ -517,24 +518,29 @@
     public NetworkPolicyManagerService(Context context, IActivityManager activityManager,
             INetworkStatsService networkStats, INetworkManagementService networkManagement) {
         this(context, activityManager, networkStats, networkManagement,
-                AppGlobals.getPackageManager(), NtpTrustedTime.getInstance(context), getSystemDir(),
+                AppGlobals.getPackageManager(), getDefaultClock(), getDefaultSystemDir(),
                 false);
     }
 
-    private static File getSystemDir() {
+    private static @NonNull File getDefaultSystemDir() {
         return new File(Environment.getDataDirectory(), "system");
     }
 
+    private static @NonNull Clock getDefaultClock() {
+        return new BestClock(ZoneOffset.UTC, SystemClock.currentNetworkTimeClock(),
+                Clock.systemUTC());
+    }
+
     public NetworkPolicyManagerService(Context context, IActivityManager activityManager,
             INetworkStatsService networkStats, INetworkManagementService networkManagement,
-            IPackageManager pm, TrustedTime time, File systemDir, boolean suppressDefaultPolicy) {
+            IPackageManager pm, Clock clock, File systemDir, boolean suppressDefaultPolicy) {
         mContext = checkNotNull(context, "missing context");
         mActivityManager = checkNotNull(activityManager, "missing activityManager");
         mNetworkStats = checkNotNull(networkStats, "missing networkStats");
         mNetworkManager = checkNotNull(networkManagement, "missing networkManagement");
         mDeviceIdleController = IDeviceIdleController.Stub.asInterface(ServiceManager.getService(
                 Context.DEVICE_IDLE_CONTROLLER));
-        mTime = checkNotNull(time, "missing TrustedTime");
+        mClock = checkNotNull(clock, "missing Clock");
         mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
         mCarrierConfigManager = mContext.getSystemService(CarrierConfigManager.class);
         mIPm = pm;
@@ -931,7 +937,6 @@
             // on background handler thread, and verified
             // READ_NETWORK_USAGE_HISTORY permission above.
 
-            maybeRefreshTrustedTime();
             synchronized (mNetworkPoliciesSecondLock) {
                 updateNetworkEnabledNL();
                 updateNotificationsNL();
@@ -1041,7 +1046,7 @@
         // cycle boundary to recompute notifications.
 
         // examine stats for each active policy
-        final long now = currentTimeMillis();
+        final long now = mClock.millis();
         for (int i = mNetworkPolicy.size()-1; i >= 0; i--) {
             final NetworkPolicy policy = mNetworkPolicy.valueAt(i);
             // ignore policies that aren't relevant to user
@@ -1298,7 +1303,6 @@
             // on background handler thread, and verified CONNECTIVITY_INTERNAL
             // permission above.
 
-            maybeRefreshTrustedTime();
             synchronized (mUidRulesFirstLock) {
                 synchronized (mNetworkPoliciesSecondLock) {
                     ensureActiveMobilePolicyAL();
@@ -1461,7 +1465,6 @@
             final TelephonyManager tele = mContext.getSystemService(TelephonyManager.class);
             final String subscriberId = tele.getSubscriberId(subId);
 
-            maybeRefreshTrustedTime();
             synchronized (mUidRulesFirstLock) {
                 synchronized (mNetworkPoliciesSecondLock) {
                     final boolean added = ensureActiveMobilePolicyAL(subId, subscriberId);
@@ -1722,7 +1725,7 @@
                 final long totalBytes = getTotalBytes(
                         NetworkTemplate.buildTemplateMobileAll(state.subscriberId), start, end);
                 final long remainingBytes = limitBytes - totalBytes;
-                final long remainingDays = Math.min(1, (end - currentTimeMillis())
+                final long remainingDays = Math.max(1, (end - mClock.millis())
                         / TimeUnit.DAYS.toMillis(1));
                 if (remainingBytes > 0) {
                     quotaBytes = (remainingBytes / remainingDays) / 10;
@@ -2443,7 +2446,6 @@
 
         final long token = Binder.clearCallingIdentity();
         try {
-            maybeRefreshTrustedTime();
             synchronized (mUidRulesFirstLock) {
                 synchronized (mNetworkPoliciesSecondLock) {
                     normalizePoliciesNL(policies);
@@ -2523,8 +2525,7 @@
     }
 
     void performSnooze(NetworkTemplate template, int type) {
-        maybeRefreshTrustedTime();
-        final long currentTime = currentTimeMillis();
+        final long currentTime = mClock.millis();
         synchronized (mUidRulesFirstLock) {
             synchronized (mNetworkPoliciesSecondLock) {
                 // find and snooze local policy that matches
@@ -2570,7 +2571,6 @@
             mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
             final long token = Binder.clearCallingIdentity();
             try {
-                maybeRefreshTrustedTime();
                 synchronized (mUidRulesFirstLock) {
                     setRestrictBackgroundUL(restrictBackground);
                 }
@@ -2759,6 +2759,13 @@
             return;
         }
 
+        // Fourth check: is caller a testing app on a debug build?
+        final boolean enableDebug = Build.IS_USERDEBUG || Build.IS_ENG;
+        if (enableDebug && callingPackage
+                .equals(SystemProperties.get("fw.sub_plan_owner." + subId, null))) {
+            return;
+        }
+
         // Final check: does the caller hold a permission?
         mContext.enforceCallingOrSelfPermission(MANAGE_SUBSCRIPTION_PLANS, TAG);
     }
@@ -2908,7 +2915,6 @@
 
         final long token = Binder.clearCallingIdentity();
         try {
-            maybeRefreshTrustedTime();
             synchronized (mUidRulesFirstLock) {
                 synchronized (mNetworkPoliciesSecondLock) {
                     mSubscriptionPlans.put(subId, plans);
@@ -4020,7 +4026,6 @@
                 case MSG_LIMIT_REACHED: {
                     final String iface = (String) msg.obj;
 
-                    maybeRefreshTrustedTime();
                     synchronized (mNetworkPoliciesSecondLock) {
                         if (mMeteredIfaces.contains(iface)) {
                             try {
@@ -4385,19 +4390,6 @@
         }
     }
 
-    /**
-     * Try refreshing {@link #mTime} when stale.
-     */
-    void maybeRefreshTrustedTime() {
-        if (mTime.getCacheAge() > TIME_CACHE_MAX_AGE) {
-            mTime.forceRefresh();
-        }
-    }
-
-    private long currentTimeMillis() {
-        return mTime.hasCache() ? mTime.currentTimeMillis() : System.currentTimeMillis();
-    }
-
     private static Intent buildAllowBackgroundDataIntent() {
         return new Intent(ACTION_ALLOW_BACKGROUND);
     }
@@ -4678,10 +4670,12 @@
         return subId;
     }
 
+    @GuardedBy("mNetworkPoliciesSecondLock")
     private int getSubIdLocked(Network network) {
         return mNetIdToSubId.get(network.netId, INVALID_SUBSCRIPTION_ID);
     }
 
+    @GuardedBy("mNetworkPoliciesSecondLock")
     private SubscriptionPlan getPrimarySubscriptionPlanLocked(int subId) {
         final SubscriptionPlan[] plans = mSubscriptionPlans.get(subId);
         return ArrayUtils.isEmpty(plans) ? null : plans[0];
diff --git a/services/core/java/com/android/server/net/NetworkStatsCollection.java b/services/core/java/com/android/server/net/NetworkStatsCollection.java
index 961a451..3cc4d83 100644
--- a/services/core/java/com/android/server/net/NetworkStatsCollection.java
+++ b/services/core/java/com/android/server/net/NetworkStatsCollection.java
@@ -187,6 +187,7 @@
      */
     @VisibleForTesting
     public static long multiplySafe(long value, long num, long den) {
+        if (den == 0) den = 1;
         long x = value;
         long y = num;
 
diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java
index bfc150e..4b80e98 100644
--- a/services/core/java/com/android/server/net/NetworkStatsService.java
+++ b/services/core/java/com/android/server/net/NetworkStatsService.java
@@ -68,6 +68,7 @@
 import static com.android.server.NetworkManagementSocketTagger.resetKernelUidStats;
 import static com.android.server.NetworkManagementSocketTagger.setKernelCounterSet;
 
+import android.annotation.NonNull;
 import android.app.AlarmManager;
 import android.app.PendingIntent;
 import android.app.usage.NetworkStatsManager;
@@ -97,6 +98,7 @@
 import android.os.Binder;
 import android.os.DropBoxManager;
 import android.os.Environment;
+import android.os.BestClock;
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.IBinder;
@@ -120,10 +122,8 @@
 import android.util.EventLog;
 import android.util.Log;
 import android.util.MathUtils;
-import android.util.NtpTrustedTime;
 import android.util.Slog;
 import android.util.SparseIntArray;
-import android.util.TrustedTime;
 import android.util.proto.ProtoOutputStream;
 
 import com.android.internal.annotations.GuardedBy;
@@ -140,6 +140,8 @@
 import java.io.FileDescriptor;
 import java.io.IOException;
 import java.io.PrintWriter;
+import java.time.Clock;
+import java.time.ZoneOffset;
 import java.util.Arrays;
 import java.util.HashSet;
 import java.util.List;
@@ -167,7 +169,7 @@
     private final Context mContext;
     private final INetworkManagementService mNetworkManager;
     private final AlarmManager mAlarmManager;
-    private final TrustedTime mTime;
+    private final Clock mClock;
     private final TelephonyManager mTeleManager;
     private final NetworkStatsSettings mSettings;
     private final NetworkStatsObservers mStatsObservers;
@@ -202,7 +204,6 @@
      */
     public interface NetworkStatsSettings {
         public long getPollInterval();
-        public long getTimeCacheMaxAge();
         public boolean getSampleEnabled();
         public boolean getAugmentEnabled();
 
@@ -281,16 +282,21 @@
     private long mPersistThreshold = 2 * MB_IN_BYTES;
     private long mGlobalAlertBytes;
 
-    private static File getDefaultSystemDir() {
+    private static @NonNull File getDefaultSystemDir() {
         return new File(Environment.getDataDirectory(), "system");
     }
 
-    private static File getDefaultBaseDir() {
+    private static @NonNull File getDefaultBaseDir() {
         File baseDir = new File(getDefaultSystemDir(), "netstats");
         baseDir.mkdirs();
         return baseDir;
     }
 
+    private static @NonNull Clock getDefaultClock() {
+        return new BestClock(ZoneOffset.UTC, SystemClock.currentNetworkTimeClock(),
+                Clock.systemUTC());
+    }
+
     public static NetworkStatsService create(Context context,
                 INetworkManagementService networkManager) {
         AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
@@ -299,7 +305,7 @@
                 powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
 
         NetworkStatsService service = new NetworkStatsService(context, networkManager, alarmManager,
-                wakeLock, NtpTrustedTime.getInstance(context), TelephonyManager.getDefault(),
+                wakeLock, getDefaultClock(), TelephonyManager.getDefault(),
                 new DefaultNetworkStatsSettings(context), new NetworkStatsObservers(),
                 getDefaultSystemDir(), getDefaultBaseDir());
 
@@ -313,13 +319,13 @@
 
     @VisibleForTesting
     NetworkStatsService(Context context, INetworkManagementService networkManager,
-            AlarmManager alarmManager, PowerManager.WakeLock wakeLock, TrustedTime time,
+            AlarmManager alarmManager, PowerManager.WakeLock wakeLock, Clock clock,
             TelephonyManager teleManager, NetworkStatsSettings settings,
             NetworkStatsObservers statsObservers, File systemDir, File baseDir) {
         mContext = checkNotNull(context, "missing Context");
         mNetworkManager = checkNotNull(networkManager, "missing INetworkManagementService");
         mAlarmManager = checkNotNull(alarmManager, "missing AlarmManager");
-        mTime = checkNotNull(time, "missing TrustedTime");
+        mClock = checkNotNull(clock, "missing Clock");
         mSettings = checkNotNull(settings, "missing NetworkStatsSettings");
         mTeleManager = checkNotNull(teleManager, "missing TelephonyManager");
         mWakeLock = checkNotNull(wakeLock, "missing WakeLock");
@@ -405,6 +411,7 @@
                 mNonMonotonicObserver, dropBox, prefix, config.bucketDuration, includeTags);
     }
 
+    @GuardedBy("mStatsLock")
     private void shutdownLocked() {
         mContext.unregisterReceiver(mTetherReceiver);
         mContext.unregisterReceiver(mPollReceiver);
@@ -412,8 +419,7 @@
         mContext.unregisterReceiver(mUserReceiver);
         mContext.unregisterReceiver(mShutdownReceiver);
 
-        final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis()
-                : System.currentTimeMillis();
+        final long currentTime = mClock.millis();
 
         // persist any pending stats
         mDevRecorder.forcePersistLocked(currentTime);
@@ -421,16 +427,10 @@
         mUidRecorder.forcePersistLocked(currentTime);
         mUidTagRecorder.forcePersistLocked(currentTime);
 
-        mDevRecorder = null;
-        mXtRecorder = null;
-        mUidRecorder = null;
-        mUidTagRecorder = null;
-
-        mXtStatsCached = null;
-
         mSystemReady = false;
     }
 
+    @GuardedBy("mStatsLock")
     private void maybeUpgradeLegacyStatsLocked() {
         File file;
         try {
@@ -829,8 +829,7 @@
         }
 
         // update and persist if beyond new thresholds
-        final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis()
-                : System.currentTimeMillis();
+        final long currentTime = mClock.millis();
         synchronized (mStatsLock) {
             if (!mSystemReady) return;
 
@@ -909,6 +908,7 @@
      * reflect current {@link #mPersistThreshold} value. Always defers to
      * {@link Global} values when defined.
      */
+    @GuardedBy("mStatsLock")
     private void updatePersistThresholdsLocked() {
         mDevRecorder.setPersistThreshold(mSettings.getDevPersistBytes(mPersistThreshold));
         mXtRecorder.setPersistThreshold(mSettings.getXtPersistBytes(mPersistThreshold));
@@ -1029,6 +1029,7 @@
      * are active on a single {@code iface}, they are combined under a single
      * {@link NetworkIdentitySet}.
      */
+    @GuardedBy("mStatsLock")
     private void updateIfacesLocked(Network[] defaultNetworks) {
         if (!mSystemReady) return;
         if (LOGV) Slog.v(TAG, "updateIfacesLocked()");
@@ -1128,6 +1129,7 @@
         return ident;
     }
 
+    @GuardedBy("mStatsLock")
     private void recordSnapshotLocked(long currentTime) throws RemoteException {
         // snapshot and record current counters; read UID stats first to
         // avoid over counting dev stats.
@@ -1163,9 +1165,9 @@
      * Bootstrap initial stats snapshot, usually during {@link #systemReady()}
      * so we have baseline values without double-counting.
      */
+    @GuardedBy("mStatsLock")
     private void bootstrapStatsLocked() {
-        final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis()
-                : System.currentTimeMillis();
+        final long currentTime = mClock.millis();
 
         try {
             recordSnapshotLocked(currentTime);
@@ -1177,11 +1179,6 @@
     }
 
     private void performPoll(int flags) {
-        // try refreshing time source when stale
-        if (mTime.getCacheAge() > mSettings.getTimeCacheMaxAge()) {
-            mTime.forceRefresh();
-        }
-
         synchronized (mStatsLock) {
             mWakeLock.acquire();
 
@@ -1197,6 +1194,7 @@
      * Periodic poll operation, reading current statistics and recording into
      * {@link NetworkStatsHistory}.
      */
+    @GuardedBy("mStatsLock")
     private void performPollLocked(int flags) {
         if (!mSystemReady) return;
         if (LOGV) Slog.v(TAG, "performPollLocked(flags=0x" + Integer.toHexString(flags) + ")");
@@ -1208,8 +1206,7 @@
         final boolean persistForce = (flags & FLAG_PERSIST_FORCE) != 0;
 
         // TODO: consider marking "untrusted" times in historical stats
-        final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis()
-                : System.currentTimeMillis();
+        final long currentTime = mClock.millis();
 
         try {
             recordSnapshotLocked(currentTime);
@@ -1258,9 +1255,10 @@
     /**
      * Sample recent statistics summary into {@link EventLog}.
      */
+    @GuardedBy("mStatsLock")
     private void performSampleLocked() {
         // TODO: migrate trustedtime fixes to separate binary log events
-        final long trustedTime = mTime.hasCache() ? mTime.currentTimeMillis() : -1;
+        final long currentTime = mClock.millis();
 
         NetworkTemplate template;
         NetworkStats.Entry devTotal;
@@ -1277,7 +1275,7 @@
                 devTotal.rxBytes, devTotal.rxPackets, devTotal.txBytes, devTotal.txPackets,
                 xtTotal.rxBytes, xtTotal.rxPackets, xtTotal.txBytes, xtTotal.txPackets,
                 uidTotal.rxBytes, uidTotal.rxPackets, uidTotal.txBytes, uidTotal.txPackets,
-                trustedTime);
+                currentTime);
 
         // collect wifi sample
         template = buildTemplateWifiWildcard();
@@ -1289,12 +1287,13 @@
                 devTotal.rxBytes, devTotal.rxPackets, devTotal.txBytes, devTotal.txPackets,
                 xtTotal.rxBytes, xtTotal.rxPackets, xtTotal.txBytes, xtTotal.txPackets,
                 uidTotal.rxBytes, uidTotal.rxPackets, uidTotal.txBytes, uidTotal.txPackets,
-                trustedTime);
+                currentTime);
     }
 
     /**
      * Clean up {@link #mUidRecorder} after UID is removed.
      */
+    @GuardedBy("mStatsLock")
     private void removeUidsLocked(int... uids) {
         if (LOGV) Slog.v(TAG, "removeUidsLocked() for UIDs " + Arrays.toString(uids));
 
@@ -1313,6 +1312,7 @@
     /**
      * Clean up {@link #mUidRecorder} after user is removed.
      */
+    @GuardedBy("mStatsLock")
     private void removeUserLocked(int userId) {
         if (LOGV) Slog.v(TAG, "removeUserLocked() for userId=" + userId);
 
@@ -1434,6 +1434,7 @@
         }
     }
 
+    @GuardedBy("mStatsLock")
     private void dumpProtoLocked(FileDescriptor fd) {
         final ProtoOutputStream proto = new ProtoOutputStream(fd);
 
@@ -1610,10 +1611,6 @@
             return getGlobalLong(NETSTATS_POLL_INTERVAL, 30 * MINUTE_IN_MILLIS);
         }
         @Override
-        public long getTimeCacheMaxAge() {
-            return getGlobalLong(NETSTATS_TIME_CACHE_MAX_AGE, DAY_IN_MILLIS);
-        }
-        @Override
         public long getGlobalAlertBytes(long def) {
             return getGlobalLong(NETSTATS_GLOBAL_ALERT_BYTES, def);
         }
diff --git a/services/core/java/com/android/server/net/watchlist/WatchlistLoggingHandler.java b/services/core/java/com/android/server/net/watchlist/WatchlistLoggingHandler.java
index c4de4ac..e8b39c0 100644
--- a/services/core/java/com/android/server/net/watchlist/WatchlistLoggingHandler.java
+++ b/services/core/java/com/android/server/net/watchlist/WatchlistLoggingHandler.java
@@ -22,12 +22,14 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.UserInfo;
 import android.os.Bundle;
 import android.os.DropBoxManager;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
 import android.os.UserHandle;
+import android.os.UserManager;
 import android.provider.Settings;
 import android.text.TextUtils;
 import android.util.Slog;
@@ -128,7 +130,7 @@
                 Slog.e(TAG, "Couldn't find package: " + packageNames);
                 return false;
             }
-            ai = mPm.getApplicationInfo(packageNames[0],0);
+            ai = mPm.getApplicationInfo(packageNames[0], 0);
         } catch (NameNotFoundException e) {
             // Should not happen.
             return false;
@@ -136,7 +138,7 @@
         return (ai.flags & ApplicationInfo.FLAG_TEST_ONLY) != 0;
     }
 
-     /**
+    /**
      * Report network watchlist records if we collected enough data.
      */
     public void reportWatchlistIfNecessary() {
@@ -180,6 +182,10 @@
             return true;
         }
         final byte[] digest = getDigestFromUid(uid);
+        if (digest == null) {
+            Slog.e(TAG, "Cannot get digest from uid: " + uid);
+            return false;
+        }
         final boolean result = mDbHelper.insertNewRecord(digest, cncHost, timestamp);
         tryAggregateRecords();
         return result;
@@ -234,15 +240,34 @@
      * if an app is really visited C&C site.
      * (2) App digests that previously recorded in database.
      */
-    private List<String> getAllDigestsForReport(WatchlistReportDbHelper.AggregatedResult record) {
+    @VisibleForTesting
+    List<String> getAllDigestsForReport(WatchlistReportDbHelper.AggregatedResult record) {
         // Step 1: Get all installed application digests.
+        final List<UserInfo> users = ((UserManager) mContext.getSystemService(
+                Context.USER_SERVICE)).getUsers();
+        final int totalUsers = users.size();
         final List<ApplicationInfo> apps = mContext.getPackageManager().getInstalledApplications(
                 PackageManager.MATCH_ANY_USER | PackageManager.MATCH_ALL);
         final HashSet<String> result = new HashSet<>(apps.size() + record.appDigestCNCList.size());
         final int size = apps.size();
         for (int i = 0; i < size; i++) {
-            byte[] digest = getDigestFromUid(apps.get(i).uid);
-            result.add(HexDump.toHexString(digest));
+            final int appUid = apps.get(i).uid;
+            boolean added = false;
+            // As the uid returned by getInstalledApplications() is for primary user only, it
+            // may exist in secondary users but not primary user, so we need to loop and see if
+            // that user has the app enabled.
+            for (int j = 0; j < totalUsers && !added; j++) {
+                int uid = UserHandle.getUid(users.get(j).id, appUid);
+                byte[] digest = getDigestFromUid(uid);
+                if (digest != null) {
+                    result.add(HexDump.toHexString(digest));
+                    added = true;
+                }
+            }
+            if (!added) {
+                Slog.e(TAG, "Cannot get digest from uid: " + apps.get(i).uid
+                        + ",pkg: " + apps.get(i).packageName);
+            }
         }
         // Step 2: Add all digests from records
         result.addAll(record.appDigestCNCList.keySet());
@@ -279,9 +304,9 @@
                         return null;
                     }
                 }
-            } else {
-                Slog.e(TAG, "Should not happen");
             }
+            // Not able to find a package name for this uid, possibly the package is installed on
+            // another user.
             return null;
         });
     }
diff --git a/services/core/java/com/android/server/notification/ManagedServices.java b/services/core/java/com/android/server/notification/ManagedServices.java
index fd435f9..b7842d5 100644
--- a/services/core/java/com/android/server/notification/ManagedServices.java
+++ b/services/core/java/com/android/server/notification/ManagedServices.java
@@ -376,9 +376,7 @@
     protected void upgradeXml(final int xmlVersion, final int userId) {}
 
     private void loadAllowedComponentsFromSettings() {
-
-        UserManager userManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
-        for (UserInfo user : userManager.getUsers()) {
+        for (UserInfo user : mUm.getUsers()) {
             final ContentResolver cr = mContext.getContentResolver();
             addApprovedList(Settings.Secure.getStringForUser(
                     cr,
@@ -482,7 +480,9 @@
         for (int i = 0; i < allowedByType.size(); i++) {
             final ArraySet<String> allowed = allowedByType.valueAt(i);
             allowedPackages.addAll(
-                    allowed.stream().map(this::getPackageName).collect(Collectors.toList()));
+                    allowed.stream().map(this::getPackageName).
+                            filter(value -> !TextUtils.isEmpty(value))
+                            .collect(Collectors.toList()));
         }
         return allowedPackages;
     }
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index e7eed03..548f154 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -25,7 +25,9 @@
 import static android.content.pm.PackageManager.FEATURE_LEANBACK;
 import static android.content.pm.PackageManager.FEATURE_TELEVISION;
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+import static android.os.UserHandle.USER_ALL;
 import static android.os.UserHandle.USER_NULL;
+import static android.os.UserHandle.USER_SYSTEM;
 import static android.service.notification.NotificationListenerService
         .HINT_HOST_DISABLE_CALL_EFFECTS;
 import static android.service.notification.NotificationListenerService.HINT_HOST_DISABLE_EFFECTS;
@@ -88,6 +90,7 @@
 import android.companion.ICompanionDeviceManager;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
+import android.content.ContentProvider;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
@@ -115,6 +118,7 @@
 import android.os.IInterface;
 import android.os.Looper;
 import android.os.Message;
+import android.os.Parcelable;
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.ResultReceiver;
@@ -206,6 +210,7 @@
 import java.util.ArrayDeque;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map.Entry;
@@ -288,6 +293,7 @@
     private ICompanionDeviceManager mCompanionManager;
     private AccessibilityManager mAccessibilityManager;
     private IDeviceIdleController mDeviceIdleController;
+    private IBinder mPermissionOwner;
 
     final IBinder mForegroundToken = new Binder();
     private WorkerHandler mHandler;
@@ -524,7 +530,7 @@
             } catch (FileNotFoundException e) {
                 // No data yet
                 // Load default managed services approvals
-                readDefaultApprovedServices(UserHandle.USER_SYSTEM);
+                readDefaultApprovedServices(USER_SYSTEM);
             } catch (IOException e) {
                 Log.wtf(TAG, "Unable to read notification policy", e);
             } catch (NumberFormatException e) {
@@ -680,6 +686,7 @@
                         sbn.getId(), Notification.FLAG_AUTO_CANCEL,
                         Notification.FLAG_FOREGROUND_SERVICE, false, r.getUserId(),
                         REASON_CLICK, null);
+                reportUserInteraction(r);
             }
         }
 
@@ -700,7 +707,7 @@
                         .setSubtype(actionIndex));
                 EventLogTags.writeNotificationActionClicked(key, actionIndex,
                         r.getLifespanMs(now), r.getFreshnessMs(now), r.getExposureMs(now));
-                // TODO: Log action click via UsageStats.
+                reportUserInteraction(r);
             }
         }
 
@@ -821,6 +828,7 @@
                 NotificationRecord r = mNotificationsByKey.get(key);
                 if (r != null) {
                     r.recordDirectReplied();
+                    reportUserInteraction(r);
                 }
             }
         }
@@ -974,7 +982,7 @@
                             final int enabled = mPackageManager.getApplicationEnabledSetting(
                                     pkgName,
                                     changeUserId != UserHandle.USER_ALL ? changeUserId :
-                                            UserHandle.USER_SYSTEM);
+                                            USER_SYSTEM);
                             if (enabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED
                                     || enabled == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) {
                                 cancelNotifications = false;
@@ -1061,6 +1069,7 @@
                 }
             } else if (action.equals(Intent.ACTION_USER_REMOVED)) {
                 final int user = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, USER_NULL);
+                mUserProfiles.updateCache(context);
                 mZenModeHelper.onUserRemoved(user);
                 mRankingHelper.onUserRemoved(user);
                 mListeners.onUserRemoved(user);
@@ -1268,7 +1277,7 @@
             NotificationAssistants notificationAssistants, ConditionProviders conditionProviders,
             ICompanionDeviceManager companionManager, SnoozeHelper snoozeHelper,
             NotificationUsageStats usageStats, AtomicFile policyFile,
-            ActivityManager activityManager, GroupHelper groupHelper) {
+            ActivityManager activityManager, GroupHelper groupHelper, IActivityManager am) {
         Resources resources = getContext().getResources();
         mMaxPackageEnqueueRate = Settings.Global.getFloat(getContext().getContentResolver(),
                 Settings.Global.MAX_NOTIFICATION_ENQUEUE_RATE,
@@ -1276,7 +1285,7 @@
 
         mAccessibilityManager =
                 (AccessibilityManager) getContext().getSystemService(Context.ACCESSIBILITY_SERVICE);
-        mAm = ActivityManager.getService();
+        mAm = am;
         mPackageManager = packageManager;
         mPackageManagerClient = packageManagerClient;
         mAppOps = (AppOpsManager) getContext().getSystemService(Context.APP_OPS_SERVICE);
@@ -1287,6 +1296,11 @@
         mActivityManager = activityManager;
         mDeviceIdleController = IDeviceIdleController.Stub.asInterface(
                 ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER));
+        try {
+            mPermissionOwner = mAm.newUriPermissionOwner("notification");
+        } catch (RemoteException e) {
+            Slog.w(TAG, "AM dead", e);
+        }
 
         mHandler = new WorkerHandler(looper);
         mRankingThread.start();
@@ -1415,7 +1429,7 @@
                 null, snoozeHelper, new NotificationUsageStats(getContext()),
                 new AtomicFile(new File(systemDir, "notification_policy.xml"), "notification-policy"),
                 (ActivityManager) getContext().getSystemService(Context.ACTIVITY_SERVICE),
-                getGroupHelper());
+                getGroupHelper(), ActivityManager.getService());
 
         // register for various Intents
         IntentFilter filter = new IntentFilter();
@@ -1746,14 +1760,29 @@
         return INotificationManager.Stub.asInterface(mService);
     }
 
+    /**
+     * Report to usage stats that the notification was seen.
+     * @param r notification record
+     */
     protected void reportSeen(NotificationRecord r) {
         final int userId = r.sbn.getUserId();
         mAppUsageStats.reportEvent(r.sbn.getPackageName(),
-                userId == UserHandle.USER_ALL ? UserHandle.USER_SYSTEM
+                userId == UserHandle.USER_ALL ? USER_SYSTEM
                         : userId,
                 UsageEvents.Event.NOTIFICATION_SEEN);
     }
 
+    /**
+     * Report to usage stats that the notification was clicked.
+     * @param r notification record
+     */
+    protected void reportUserInteraction(NotificationRecord r) {
+        final int userId = r.sbn.getUserId();
+        mAppUsageStats.reportEvent(r.sbn.getPackageName(),
+                userId == UserHandle.USER_ALL ? UserHandle.USER_SYSTEM : userId,
+                UsageEvents.Event.USER_INTERACTION);
+    }
+
     @VisibleForTesting
     NotificationManagerInternal getInternalService() {
         return mInternalService;
@@ -1807,6 +1836,10 @@
                     if (index >= 0) {
                         record = mToastQueue.get(index);
                         record.update(duration);
+                        try {
+                            record.callback.hide();
+                        } catch (RemoteException e) {
+                        }
                         record.update(callback);
                     } else {
                         Binder token = new Binder();
@@ -2894,7 +2927,7 @@
             checkCallerIsSystem();
             if (DBG) Slog.d(TAG, "getBackupPayload u=" + user);
             //TODO: http://b/22388012
-            if (user != UserHandle.USER_SYSTEM) {
+            if (user != USER_SYSTEM) {
                 Slog.w(TAG, "getBackupPayload: cannot backup policy for user " + user);
                 return null;
             }
@@ -2920,7 +2953,7 @@
                 return;
             }
             //TODO: http://b/22388012
-            if (user != UserHandle.USER_SYSTEM) {
+            if (user != USER_SYSTEM) {
                 Slog.w(TAG, "applyRestore: cannot restore policy for user " + user);
                 return;
             }
@@ -3678,7 +3711,7 @@
             sbn.getNotification().flags =
                     (r.mOriginalFlags & ~Notification.FLAG_FOREGROUND_SERVICE);
             mRankingHelper.sort(mNotificationList);
-            mListeners.notifyPostedLocked(sbn, sbn /* oldSbn */);
+            mListeners.notifyPostedLocked(r, sbn /* oldSbn */);
         }
     };
 
@@ -3707,7 +3740,7 @@
         try {
             final ApplicationInfo ai = mPackageManagerClient.getApplicationInfoAsUser(
                     pkg, PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
-                    (userId == UserHandle.USER_ALL) ? UserHandle.USER_SYSTEM : userId);
+                    (userId == UserHandle.USER_ALL) ? USER_SYSTEM : userId);
             Notification.addFieldsFromContext(ai, notification);
 
             int canColorize = mPackageManagerClient.checkPermission(
@@ -3897,6 +3930,7 @@
         return true;
     }
 
+    @GuardedBy("mNotificationLock")
     protected int getNotificationCountLocked(String pkg, int userId, int excludedId,
             String excludedTag) {
         int count = 0;
@@ -4126,6 +4160,8 @@
                         // Make sure we don't lose the foreground service state.
                         notification.flags |=
                                 old.getNotification().flags & Notification.FLAG_FOREGROUND_SERVICE;
+                        // revoke uri permissions for changed uris
+                        revokeUriPermissions(r, old);
                         r.isUpdate = true;
                     }
 
@@ -4147,7 +4183,7 @@
 
                     if (notification.getSmallIcon() != null) {
                         StatusBarNotification oldSbn = (old != null) ? old.sbn : null;
-                        mListeners.notifyPostedLocked(n, oldSbn);
+                        mListeners.notifyPostedLocked(r, oldSbn);
                         if (oldSbn == null || !Objects.equals(oldSbn.getGroup(), n.getGroup())) {
                             mHandler.post(new Runnable() {
                                 @Override
@@ -4912,6 +4948,9 @@
             r.recordDismissalSurface(NotificationStats.DISMISSAL_OTHER);
         }
 
+        // Revoke permissions
+        revokeUriPermissions(null, r);
+
         // tell the app
         if (sendDelete) {
             if (r.getNotification().deleteIntent != null) {
@@ -5009,6 +5048,30 @@
                 r.getLifespanMs(now), r.getFreshnessMs(now), r.getExposureMs(now), listenerName);
     }
 
+    void revokeUriPermissions(NotificationRecord newRecord, NotificationRecord oldRecord) {
+        Set<Uri> oldUris = oldRecord.getNotificationUris();
+        Set<Uri> newUris = newRecord == null ? new HashSet<>() : newRecord.getNotificationUris();
+        oldUris.removeAll(newUris);
+
+        long ident = Binder.clearCallingIdentity();
+        try {
+            for (Uri uri : oldUris) {
+                if (uri != null) {
+                    int notiUserId = oldRecord.getUserId();
+                    int sourceUserId = notiUserId == USER_ALL ? USER_SYSTEM
+                            : ContentProvider.getUserIdFromUri(uri, notiUserId);
+                    uri = ContentProvider.getUriWithoutUserId(uri);
+                    mAm.revokeUriPermissionFromOwner(mPermissionOwner,
+                            uri, Intent.FLAG_GRANT_READ_URI_PERMISSION, sourceUserId);
+                }
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, "Count not revoke uri permissions", e);
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+    }
+
     /**
      * Cancels a notification ONLY if it has all of the {@code mustHaveFlags}
      * and none of the {@code mustNotHaveFlags}.
@@ -5851,10 +5914,13 @@
          * but isn't anymore.
          */
         @GuardedBy("mNotificationLock")
-        public void notifyPostedLocked(StatusBarNotification sbn, StatusBarNotification oldSbn) {
+        public void notifyPostedLocked(NotificationRecord r, StatusBarNotification oldSbn) {
             // Lazily initialized snapshots of the notification.
+            StatusBarNotification sbn = r.sbn;
             TrimCache trimCache = new TrimCache(sbn);
 
+            Set<Uri> uris = r.getNotificationUris();
+
             for (final ManagedServiceInfo info : getServices()) {
                 boolean sbnVisible = isVisibleToListener(sbn, info);
                 boolean oldSbnVisible = oldSbn != null ? isVisibleToListener(oldSbn, info) : false;
@@ -5877,6 +5943,9 @@
                     continue;
                 }
 
+                grantUriPermissions(uris, sbn.getUserId(), info.component.getPackageName(),
+                        info.userid);
+
                 final StatusBarNotification sbnToPost =  trimCache.ForListener(info);
                 mHandler.post(new Runnable() {
                     @Override
@@ -5887,6 +5956,28 @@
             }
         }
 
+        private void grantUriPermissions(Set<Uri> uris, int notiUserId, String listenerPkg,
+                int listenerUserId) {
+            long ident = Binder.clearCallingIdentity();
+            try {
+                for (Uri uri : uris) {
+                    if (uri != null) {
+                        int sourceUserId = notiUserId == USER_ALL ? USER_SYSTEM
+                                : ContentProvider.getUserIdFromUri(uri, notiUserId);
+                        uri = ContentProvider.getUriWithoutUserId(uri);
+                        mAm.grantUriPermissionFromOwner(mPermissionOwner, Process.myUid(),
+                                listenerPkg,
+                                uri, Intent.FLAG_GRANT_READ_URI_PERMISSION, sourceUserId,
+                                listenerUserId == USER_ALL ? USER_SYSTEM : listenerUserId);
+                    }
+                }
+            } catch (RemoteException e) {
+                Log.e(TAG, "Count not grant uri permission to " + listenerPkg, e);
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+
         /**
          * asynchronously notify all listeners about a removed notification
          */
diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java
index 23b9743..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;
@@ -38,6 +41,7 @@
 import android.net.Uri;
 import android.os.Build;
 import android.os.Bundle;
+import android.os.Parcelable;
 import android.os.UserHandle;
 import android.provider.Settings;
 import android.service.notification.Adjustment;
@@ -47,6 +51,7 @@
 import android.service.notification.SnoozeCriterion;
 import android.service.notification.StatusBarNotification;
 import android.text.TextUtils;
+import android.util.ArraySet;
 import android.util.Log;
 import android.util.Slog;
 import android.util.TimeUtils;
@@ -64,6 +69,7 @@
 import java.util.Arrays;
 import java.util.List;
 import java.util.Objects;
+import java.util.Set;
 
 /**
  * Holds data about notifications that should not be shared with the
@@ -160,6 +166,7 @@
         mLight = calculateLights();
         mAdjustments = new ArrayList<>();
         mStats = new NotificationStats();
+        calculateUserSentiment();
     }
 
     private boolean isPreChannelsNotification() {
@@ -317,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;
             }
@@ -582,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));
+                    }
                 }
             }
         }
@@ -842,10 +853,6 @@
         }
     }
 
-    public boolean isImportanceFromUser() {
-        return mImportance == mUserImportance;
-    }
-
     public NotificationChannel getChannel() {
         return mChannel;
     }
@@ -854,6 +861,7 @@
         if (channel != null) {
             mChannel = channel;
             calculateImportance();
+            calculateUserSentiment();
         }
     }
 
@@ -897,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;
     }
@@ -929,6 +943,42 @@
         mStats.setViewedSettings();
     }
 
+    public Set<Uri> getNotificationUris() {
+        Notification notification = getNotification();
+        Set<Uri> uris = new ArraySet<>();
+
+        if (notification.sound != null) {
+            uris.add(notification.sound);
+        }
+        if (notification.getChannelId() != null) {
+            NotificationChannel channel = getChannel();
+            if (channel != null && channel.getSound() != null) {
+                uris.add(channel.getSound());
+            }
+        }
+        if (notification.extras.containsKey(Notification.EXTRA_AUDIO_CONTENTS_URI)) {
+            uris.add(notification.extras.getParcelable(Notification.EXTRA_AUDIO_CONTENTS_URI));
+        }
+        if (notification.extras.containsKey(Notification.EXTRA_BACKGROUND_IMAGE_URI)) {
+            uris.add(notification.extras.getParcelable(Notification.EXTRA_BACKGROUND_IMAGE_URI));
+        }
+        if (Notification.MessagingStyle.class.equals(notification.getNotificationStyle())) {
+            Parcelable[] newMessages =
+                    notification.extras.getParcelableArray(Notification.EXTRA_MESSAGES);
+            List<Notification.MessagingStyle.Message> messages
+                    = Notification.MessagingStyle.Message.getMessagesFromBundleArray(newMessages);
+            Parcelable[] histMessages =
+                    notification.extras.getParcelableArray(Notification.EXTRA_HISTORIC_MESSAGES);
+            messages.addAll(
+                    Notification.MessagingStyle.Message.getMessagesFromBundleArray(histMessages));
+            for (Notification.MessagingStyle.Message message : messages) {
+                uris.add(message.getDataUri());
+            }
+        }
+
+        return uris;
+    }
+
     public LogMaker getLogMaker(long now) {
         if (mLogMaker == null) {
             // initialize fields that only change on update (so a new record)
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/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index 7e3b551..0a87097 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -18,8 +18,10 @@
 
 import android.app.AppOpsManager;
 import android.app.AutomaticZenRule;
+import android.app.Notification;
 import android.app.NotificationManager;
 import android.app.NotificationManager.Policy;
+import android.app.PendingIntent;
 import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -44,6 +46,7 @@
 import android.os.Process;
 import android.os.SystemClock;
 import android.os.UserHandle;
+import android.provider.Settings;
 import android.provider.Settings.Global;
 import android.service.notification.Condition;
 import android.service.notification.ConditionProviderService;
@@ -61,6 +64,8 @@
 import com.android.internal.R;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.logging.MetricsLogger;
+import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
+import com.android.internal.notification.SystemNotificationChannels;
 import com.android.server.LocalServices;
 
 import libcore.io.IoUtils;
@@ -89,6 +94,7 @@
     private final H mHandler;
     private final SettingsObserver mSettingsObserver;
     @VisibleForTesting protected final AppOpsManager mAppOps;
+    @VisibleForTesting protected final NotificationManager mNotificationManager;
     protected ZenModeConfig mDefaultConfig;
     private final ArrayList<Callback> mCallbacks = new ArrayList<Callback>();
     private final ZenModeFiltering mFiltering;
@@ -112,12 +118,14 @@
 
     protected String mDefaultRuleEveryNightName;
     protected String mDefaultRuleEventsName;
+    @VisibleForTesting protected boolean mIsBootComplete;
 
     public ZenModeHelper(Context context, Looper looper, ConditionProviders conditionProviders) {
         mContext = context;
         mHandler = new H(looper);
         addCallback(mMetrics);
         mAppOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
+        mNotificationManager =  context.getSystemService(NotificationManager.class);
 
         mDefaultConfig = new ZenModeConfig();
         setDefaultZenRules(mContext);
@@ -197,6 +205,8 @@
         mHandler.postMetricsTimer();
         cleanUpZenRules();
         evaluateZenMode("onSystemReady", true);
+        mIsBootComplete = true;
+        showZenUpgradeNotification(mZenMode);
     }
 
     public void onUserSwitched(int user) {
@@ -612,6 +622,10 @@
             throws XmlPullParserException, IOException {
         final ZenModeConfig config = ZenModeConfig.readXml(parser);
         if (config != null) {
+            if (config.version < ZenModeConfig.XML_VERSION) {
+                Settings.Global.putInt(mContext.getContentResolver(),
+                        Global.SHOW_ZEN_UPGRADE_NOTIFICATION, 1);
+            }
             if (forRestore) {
                 //TODO: http://b/22388012
                 if (config.user != UserHandle.USER_SYSTEM) {
@@ -755,8 +769,10 @@
         return Global.getInt(mContext.getContentResolver(), Global.ZEN_MODE, Global.ZEN_MODE_OFF);
     }
 
-    private void setZenModeSetting(int zen) {
+    @VisibleForTesting
+    protected void setZenModeSetting(int zen) {
         Global.putInt(mContext.getContentResolver(), Global.ZEN_MODE, zen);
+        showZenUpgradeNotification(zen);
     }
 
     private int getPreviousRingerModeSetting() {
@@ -1139,6 +1155,41 @@
         }
     }
 
+    private void showZenUpgradeNotification(int zen) {
+        final boolean showNotification = mIsBootComplete
+                && zen == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS
+                && Settings.Global.getInt(mContext.getContentResolver(),
+                Settings.Global.SHOW_ZEN_UPGRADE_NOTIFICATION, 0) != 0;
+
+        if (showNotification) {
+            mNotificationManager.notify(TAG, SystemMessage.NOTE_ZEN_UPGRADE,
+                    createZenUpgradeNotification());
+            Settings.Global.putInt(mContext.getContentResolver(),
+                    Global.SHOW_ZEN_UPGRADE_NOTIFICATION, 0);
+        }
+    }
+
+    @VisibleForTesting
+    protected Notification createZenUpgradeNotification() {
+        Intent intent = new Intent(Settings.ACTION_ZEN_MODE_PRIORITY_SETTINGS)
+                .setPackage("com.android.settings")
+                .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        final Bundle extras = new Bundle();
+        extras.putString(Notification.EXTRA_SUBSTITUTE_APP_NAME,
+                mContext.getResources().getString(R.string.global_action_settings));
+        return new Notification.Builder(mContext, SystemNotificationChannels.SYSTEM_CHANGES)
+                .setSmallIcon(R.drawable.ic_settings_24dp)
+                .setContentTitle(mContext.getResources().getString(
+                        R.string.zen_upgrade_notification_title))
+                .setContentText(mContext.getResources().getString(
+                        R.string.zen_upgrade_notification_content))
+                .setAutoCancel(true)
+                .setLocalOnly(true)
+                .addExtras(extras)
+                .setContentIntent(PendingIntent.getActivity(mContext, 0, intent, 0, null))
+                .build();
+    }
+
     private final class Metrics extends Callback {
         private static final String COUNTER_PREFIX = "dnd_mode_";
         private static final long MINIMUM_LOG_PERIOD_MS = 60 * 1000;
diff --git a/services/core/java/com/android/server/om/OverlayManagerService.java b/services/core/java/com/android/server/om/OverlayManagerService.java
index 4bc4a7e..7467954 100644
--- a/services/core/java/com/android/server/om/OverlayManagerService.java
+++ b/services/core/java/com/android/server/om/OverlayManagerService.java
@@ -544,7 +544,28 @@
             final long ident = Binder.clearCallingIdentity();
             try {
                 synchronized (mLock) {
-                    return mImpl.setEnabledExclusive(packageName, userId);
+                    return mImpl.setEnabledExclusive(packageName, false /* withinCategory */,
+                            userId);
+                }
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+
+        @Override
+        public boolean setEnabledExclusiveInCategory(@Nullable String packageName, int userId)
+                throws RemoteException {
+            enforceChangeOverlayPackagesPermission("setEnabled");
+            userId = handleIncomingUser(userId, "setEnabled");
+            if (packageName == null) {
+                return false;
+            }
+
+            final long ident = Binder.clearCallingIdentity();
+            try {
+                synchronized (mLock) {
+                    return mImpl.setEnabledExclusive(packageName, true /* withinCategory */,
+                            userId);
                 }
             } finally {
                 Binder.restoreCallingIdentity(ident);
diff --git a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
index 6e02db7..a027fc6 100644
--- a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
+++ b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
@@ -35,6 +35,8 @@
 import android.util.ArraySet;
 import android.util.Slog;
 
+import libcore.util.Objects;
+
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Iterator;
@@ -103,12 +105,14 @@
         for (int i = 0; i < overlayPackagesSize; i++) {
             final PackageInfo overlayPackage = overlayPackages.get(i);
             final OverlayInfo oi = storedOverlayInfos.get(overlayPackage.packageName);
-            if (oi == null || !oi.targetPackageName.equals(overlayPackage.overlayTarget)) {
+            if (oi == null || !oi.targetPackageName.equals(overlayPackage.overlayTarget)
+                    || !Objects.equal(oi.category, overlayPackage.overlayCategory)) {
                 // Update the overlay if it didn't exist or had the wrong target package.
                 mSettings.init(overlayPackage.packageName, newUserId,
                         overlayPackage.overlayTarget,
                         overlayPackage.applicationInfo.getBaseCodePath(),
-                        overlayPackage.isStaticOverlayPackage(), overlayPackage.overlayPriority);
+                        overlayPackage.isStaticOverlayPackage(), overlayPackage.overlayPriority,
+                        overlayPackage.overlayCategory);
 
                 if (oi == null) {
                     // This overlay does not exist in our settings.
@@ -259,7 +263,8 @@
 
         mSettings.init(packageName, userId, overlayPackage.overlayTarget,
                 overlayPackage.applicationInfo.getBaseCodePath(),
-                overlayPackage.isStaticOverlayPackage(), overlayPackage.overlayPriority);
+                overlayPackage.isStaticOverlayPackage(), overlayPackage.overlayPriority,
+                overlayPackage.overlayCategory);
         try {
             if (updateState(overlayPackage.overlayTarget, packageName, userId, 0)) {
                 mListener.onOverlaysChanged(overlayPackage.overlayTarget, userId);
@@ -320,7 +325,7 @@
             if (!oldOi.targetPackageName.equals(pkg.overlayTarget)) {
                 mSettings.init(packageName, userId, pkg.overlayTarget,
                         pkg.applicationInfo.getBaseCodePath(), pkg.isStaticOverlayPackage(),
-                        pkg.overlayPriority);
+                        pkg.overlayPriority, pkg.overlayCategory);
             }
 
             if (updateState(pkg.overlayTarget, packageName, userId, 0)) {
@@ -394,10 +399,11 @@
         }
     }
 
-    boolean setEnabledExclusive(@NonNull final String packageName, final int userId) {
+    boolean setEnabledExclusive(@NonNull final String packageName, boolean withinCategory,
+            final int userId) {
         if (DEBUG) {
-            Slog.d(TAG, String.format("setEnabledExclusive packageName=%s userId=%d", packageName,
-                    userId));
+            Slog.d(TAG, String.format("setEnabledExclusive packageName=%s"
+                    + " withinCategory=%s userId=%d", packageName, withinCategory, userId));
         }
 
         final PackageInfo overlayPackage = mPackageManager.getPackageInfo(packageName, userId);
@@ -428,6 +434,11 @@
                     // Don't touch static overlays.
                     continue;
                 }
+                if (withinCategory && !Objects.equal(disabledOverlayPackageInfo.overlayCategory,
+                        oi.category)) {
+                    // Don't touch overlays from other categories.
+                    continue;
+                }
 
                 // Disable the overlay.
                 modified |= mSettings.setEnabled(disabledOverlayPackageName, userId, false);
diff --git a/services/core/java/com/android/server/om/OverlayManagerSettings.java b/services/core/java/com/android/server/om/OverlayManagerSettings.java
index a80cae4..e57fa0b 100644
--- a/services/core/java/com/android/server/om/OverlayManagerSettings.java
+++ b/services/core/java/com/android/server/om/OverlayManagerSettings.java
@@ -20,10 +20,7 @@
 import static com.android.server.om.OverlayManagerService.TAG;
 
 import android.annotation.NonNull;
-import android.annotation.Nullable;
 import android.content.om.OverlayInfo;
-import android.os.UserHandle;
-import android.util.AndroidRuntimeException;
 import android.util.ArrayMap;
 import android.util.Slog;
 import android.util.Xml;
@@ -67,11 +64,11 @@
 
     void init(@NonNull final String packageName, final int userId,
             @NonNull final String targetPackageName, @NonNull final String baseCodePath,
-            boolean isStatic, int priority) {
+            boolean isStatic, int priority, String overlayCategory) {
         remove(packageName, userId);
         final SettingsItem item =
                 new SettingsItem(packageName, userId, targetPackageName, baseCodePath,
-                        isStatic, priority);
+                        isStatic, priority, overlayCategory);
         if (isStatic) {
             int i;
             for (i = mItems.size() - 1; i >= 0; i--) {
@@ -292,6 +289,7 @@
             pw.print("mState.............: "); pw.println(OverlayInfo.stateToString(item.getState()));
             pw.print("mIsEnabled.........: "); pw.println(item.isEnabled());
             pw.print("mIsStatic..........: "); pw.println(item.isStatic());
+            pw.print("mCategory..........: "); pw.println(item.mCategory);
 
             pw.decreaseIndent();
             pw.println("}");
@@ -317,6 +315,7 @@
         private static final String ATTR_TARGET_PACKAGE_NAME = "targetPackageName";
         private static final String ATTR_IS_STATIC = "isStatic";
         private static final String ATTR_PRIORITY = "priority";
+        private static final String ATTR_CATEGORY = "category";
         private static final String ATTR_USER_ID = "userId";
         private static final String ATTR_VERSION = "version";
 
@@ -371,9 +370,10 @@
             final boolean isEnabled = XmlUtils.readBooleanAttribute(parser, ATTR_IS_ENABLED);
             final boolean isStatic = XmlUtils.readBooleanAttribute(parser, ATTR_IS_STATIC);
             final int priority = XmlUtils.readIntAttribute(parser, ATTR_PRIORITY);
+            final String category = XmlUtils.readStringAttribute(parser, ATTR_CATEGORY);
 
-            return new SettingsItem(packageName, userId, targetPackageName, baseCodePath, state,
-                    isEnabled, isStatic, priority);
+            return new SettingsItem(packageName, userId, targetPackageName, baseCodePath,
+                    state, isEnabled, isStatic, priority, category);
         }
 
         public static void persist(@NonNull final ArrayList<SettingsItem> table,
@@ -405,6 +405,7 @@
             XmlUtils.writeBooleanAttribute(xml, ATTR_IS_ENABLED, item.mIsEnabled);
             XmlUtils.writeBooleanAttribute(xml, ATTR_IS_STATIC, item.mIsStatic);
             XmlUtils.writeIntAttribute(xml, ATTR_PRIORITY, item.mPriority);
+            XmlUtils.writeStringAttribute(xml, ATTR_CATEGORY, item.mCategory);
             xml.endTag(null, TAG_ITEM);
         }
     }
@@ -419,17 +420,19 @@
         private OverlayInfo mCache;
         private boolean mIsStatic;
         private int mPriority;
+        private final String mCategory;
 
         SettingsItem(@NonNull final String packageName, final int userId,
                 @NonNull final String targetPackageName, @NonNull final String baseCodePath,
                 final @OverlayInfo.State int state, final boolean isEnabled, final boolean isStatic,
-                final int priority) {
+                final int priority, String category) {
             mPackageName = packageName;
             mUserId = userId;
             mTargetPackageName = targetPackageName;
             mBaseCodePath = baseCodePath;
             mState = state;
             mIsEnabled = isEnabled;
+            mCategory = category;
             mCache = null;
             mIsStatic = isStatic;
             mPriority = priority;
@@ -437,9 +440,9 @@
 
         SettingsItem(@NonNull final String packageName, final int userId,
                 @NonNull final String targetPackageName, @NonNull final String baseCodePath,
-                final boolean isStatic, final int priority) {
+                final boolean isStatic, final int priority, String category) {
             this(packageName, userId, targetPackageName, baseCodePath, OverlayInfo.STATE_UNKNOWN,
-                    false, isStatic, priority);
+                    false, isStatic, priority, category);
         }
 
         private String getTargetPackageName() {
@@ -491,8 +494,8 @@
 
         private OverlayInfo getOverlayInfo() {
             if (mCache == null) {
-                mCache = new OverlayInfo(mPackageName, mTargetPackageName, mBaseCodePath, mState,
-                        mUserId);
+                mCache = new OverlayInfo(mPackageName, mTargetPackageName, mCategory, mBaseCodePath,
+                        mState, mUserId);
             }
             return mCache;
         }
diff --git a/services/core/java/com/android/server/om/OverlayManagerShellCommand.java b/services/core/java/com/android/server/om/OverlayManagerShellCommand.java
index 29ddaf4..54bb115 100644
--- a/services/core/java/com/android/server/om/OverlayManagerShellCommand.java
+++ b/services/core/java/com/android/server/om/OverlayManagerShellCommand.java
@@ -56,6 +56,8 @@
                     return runEnableDisable(true);
                 case "disable":
                     return runEnableDisable(false);
+                case "enable-exclusive":
+                    return runEnableExclusive();
                 case "set-priority":
                     return runSetPriority();
                 default:
@@ -86,6 +88,10 @@
         out.println("    Enable overlay package PACKAGE.");
         out.println("  disable [--user USER_ID] PACKAGE");
         out.println("    Disable overlay package PACKAGE.");
+        out.println("  enable-exclusive [--user USER_ID] [--category] PACKAGE");
+        out.println("    Enable overlay package PACKAGE and disable all other overlays for");
+        out.println("    its target package. If the --category option is given, only disables");
+        out.println("    other overlays in the same category.");
         out.println("  set-priority [--user USER_ID] PACKAGE PARENT|lowest|highest");
         out.println("    Change the priority of the overlay PACKAGE to be just higher than");
         out.println("    the priority of PACKAGE_PARENT If PARENT is the special keyword");
@@ -157,6 +163,33 @@
         return mInterface.setEnabled(packageName, enable, userId) ? 0 : 1;
     }
 
+    private int runEnableExclusive() throws RemoteException {
+        final PrintWriter err = getErrPrintWriter();
+
+        int userId = UserHandle.USER_SYSTEM;
+        boolean inCategory = false;
+        String opt;
+        while ((opt = getNextOption()) != null) {
+            switch (opt) {
+                case "--user":
+                    userId = UserHandle.parseUserArg(getNextArgRequired());
+                    break;
+                case "--category":
+                    inCategory = true;
+                    break;
+                default:
+                    err.println("Error: Unknown option: " + opt);
+                    return 1;
+            }
+        }
+        final String overlay = getNextArgRequired();
+        if (inCategory) {
+            return mInterface.setEnabledExclusiveInCategory(overlay, userId) ? 0 : 1;
+        } else {
+            return mInterface.setEnabledExclusive(overlay, true, userId) ? 0 : 1;
+        }
+    }
+
     private int runSetPriority() throws RemoteException {
         final PrintWriter err = getErrPrintWriter();
 
diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java
index b79caca..9bba9ed 100644
--- a/services/core/java/com/android/server/pm/Installer.java
+++ b/services/core/java/com/android/server/pm/Installer.java
@@ -63,9 +63,8 @@
     public static final int DEXOPT_STORAGE_DE     = 1 << 8;
     /** Indicates that dexopt is invoked from the background service. */
     public static final int DEXOPT_IDLE_BACKGROUND_JOB = 1 << 9;
-    /* Indicates that dexopt should not restrict access to private APIs.
-     * Must be kept in sync with com.android.internal.os.ZygoteInit. */
-    public static final int DEXOPT_DISABLE_HIDDEN_API_CHECKS = 1 << 10;
+    /** Indicates that dexopt should restrict access to private APIs. */
+    public static final int DEXOPT_ENABLE_HIDDEN_API_CHECKS = 1 << 10;
 
     // NOTE: keep in sync with installd
     public static final int FLAG_CLEAR_CACHE_ONLY = 1 << 8;
@@ -290,14 +289,14 @@
             int dexoptNeeded, @Nullable String outputPath, int dexFlags,
             String compilerFilter, @Nullable String volumeUuid, @Nullable String sharedLibraries,
             @Nullable String seInfo, boolean downgrade, int targetSdkVersion,
-            @Nullable String profileName, @Nullable String dexMetadataPath)
-            throws InstallerException {
+            @Nullable String profileName, @Nullable String dexMetadataPath,
+            @Nullable String compilationReason) throws InstallerException {
         assertValidInstructionSet(instructionSet);
         if (!checkBeforeRemote()) return;
         try {
             mInstalld.dexopt(apkPath, uid, pkgName, instructionSet, dexoptNeeded, outputPath,
                     dexFlags, compilerFilter, volumeUuid, sharedLibraries, seInfo, downgrade,
-                    targetSdkVersion, profileName, dexMetadataPath);
+                    targetSdkVersion, profileName, dexMetadataPath, compilationReason);
         } catch (Exception e) {
             throw InstallerException.from(e);
         }
diff --git a/services/core/java/com/android/server/pm/InstantAppRegistry.java b/services/core/java/com/android/server/pm/InstantAppRegistry.java
index 30088dd..fb81ebf 100644
--- a/services/core/java/com/android/server/pm/InstantAppRegistry.java
+++ b/services/core/java/com/android/server/pm/InstantAppRegistry.java
@@ -274,7 +274,7 @@
             }
 
             // Propagate permissions before removing any state
-            propagateInstantAppPermissionsIfNeeded(pkg.packageName, userId);
+            propagateInstantAppPermissionsIfNeeded(pkg, userId);
 
             // Track instant apps
             if (ps.getInstantApp(userId)) {
@@ -869,10 +869,10 @@
         return uninstalledApps;
     }
 
-    private void propagateInstantAppPermissionsIfNeeded(@NonNull String packageName,
+    private void propagateInstantAppPermissionsIfNeeded(@NonNull PackageParser.Package pkg,
             @UserIdInt int userId) {
         InstantAppInfo appInfo = peekOrParseUninstalledInstantAppInfo(
-                packageName, userId);
+                pkg.packageName, userId);
         if (appInfo == null) {
             return;
         }
@@ -884,8 +884,8 @@
             for (String grantedPermission : appInfo.getGrantedPermissions()) {
                 final boolean propagatePermission =
                         mService.mSettings.canPropagatePermissionToInstantApp(grantedPermission);
-                if (propagatePermission) {
-                    mService.grantRuntimePermission(packageName, grantedPermission, userId);
+                if (propagatePermission && pkg.requestedPermissions.contains(grantedPermission)) {
+                    mService.grantRuntimePermission(pkg.packageName, grantedPermission, userId);
                 }
             }
         } finally {
diff --git a/services/core/java/com/android/server/pm/InstantAppResolver.java b/services/core/java/com/android/server/pm/InstantAppResolver.java
index 6e898bb..bc9fa4b 100644
--- a/services/core/java/com/android/server/pm/InstantAppResolver.java
+++ b/services/core/java/com/android/server/pm/InstantAppResolver.java
@@ -126,17 +126,16 @@
         final Intent origIntent = requestObj.origIntent;
         final Intent sanitizedIntent = sanitizeIntent(origIntent);
 
-        final InstantAppDigest digest = getInstantAppDigest(origIntent);
-        final int[] shaPrefix = digest.getDigestPrefix();
         AuxiliaryResolveInfo resolveInfo = null;
         @ResolutionStatus int resolutionStatus = RESOLUTION_SUCCESS;
         try {
             final List<InstantAppResolveInfo> instantAppResolveInfoList =
-                    connection.getInstantAppResolveInfoList(sanitizedIntent, shaPrefix, token);
+                    connection.getInstantAppResolveInfoList(sanitizedIntent,
+                            requestObj.digest.getDigestPrefixSecure(), token);
             if (instantAppResolveInfoList != null && instantAppResolveInfoList.size() > 0) {
                 resolveInfo = InstantAppResolver.filterInstantAppIntent(
                         instantAppResolveInfoList, origIntent, requestObj.resolvedType,
-                        requestObj.userId, origIntent.getPackage(), digest, token);
+                        requestObj.userId, origIntent.getPackage(), requestObj.digest, token);
             }
         } catch (ConnectionException e) {
             if (e.failure == ConnectionException.FAILURE_BIND) {
@@ -166,12 +165,6 @@
         return resolveInfo;
     }
 
-    private static InstantAppDigest getInstantAppDigest(Intent origIntent) {
-        return origIntent.getData() != null && !TextUtils.isEmpty(origIntent.getData().getHost())
-                ? new InstantAppDigest(origIntent.getData().getHost(), 5 /*maxDigests*/)
-                : InstantAppDigest.UNDEFINED;
-    }
-
     public static void doInstantAppResolutionPhaseTwo(Context context,
             InstantAppResolverConnection connection, InstantAppRequest requestObj,
             ActivityInfo instantAppInstaller, Handler callbackHandler) {
@@ -182,8 +175,6 @@
         }
         final Intent origIntent = requestObj.origIntent;
         final Intent sanitizedIntent = sanitizeIntent(origIntent);
-        final InstantAppDigest digest = getInstantAppDigest(origIntent);
-        final int[] shaPrefix = digest.getDigestPrefix();
 
         final PhaseTwoCallback callback = new PhaseTwoCallback() {
             @Override
@@ -194,7 +185,8 @@
                     final AuxiliaryResolveInfo instantAppIntentInfo =
                             InstantAppResolver.filterInstantAppIntent(
                                     instantAppResolveInfoList, origIntent, null /*resolvedType*/,
-                                    0 /*userId*/, origIntent.getPackage(), digest, token);
+                                    0 /*userId*/, origIntent.getPackage(), requestObj.digest,
+                                    token);
                     if (instantAppIntentInfo != null) {
                         failureIntent = instantAppIntentInfo.failureIntent;
                     } else {
@@ -225,8 +217,9 @@
             }
         };
         try {
-            connection.getInstantAppIntentFilterList(sanitizedIntent, shaPrefix, token, callback,
-                    callbackHandler, startTime);
+            connection.getInstantAppIntentFilterList(sanitizedIntent,
+                    requestObj.digest.getDigestPrefixSecure(), token, callback, callbackHandler,
+                    startTime);
         } catch (ConnectionException e) {
             @ResolutionStatus int resolutionStatus = RESOLUTION_FAILURE;
             if (e.failure == ConnectionException.FAILURE_BIND) {
diff --git a/services/core/java/com/android/server/pm/InstantAppResolverConnection.java b/services/core/java/com/android/server/pm/InstantAppResolverConnection.java
index a9ee411..98f421e 100644
--- a/services/core/java/com/android/server/pm/InstantAppResolverConnection.java
+++ b/services/core/java/com/android/server/pm/InstantAppResolverConnection.java
@@ -141,6 +141,7 @@
         }
     }
 
+    @GuardedBy("mLock")
     private void waitForBindLocked(String token) throws TimeoutException, InterruptedException {
         final long startMillis = SystemClock.uptimeMillis();
         while (mBindState != STATE_IDLE) {
@@ -250,6 +251,7 @@
         }
     }
 
+    @GuardedBy("mLock")
     private void handleBinderDiedLocked() {
         if (mRemoteInstance != null) {
             try {
diff --git a/services/core/java/com/android/server/pm/OtaDexoptService.java b/services/core/java/com/android/server/pm/OtaDexoptService.java
index fc73142..9420a6c 100644
--- a/services/core/java/com/android/server/pm/OtaDexoptService.java
+++ b/services/core/java/com/android/server/pm/OtaDexoptService.java
@@ -262,11 +262,12 @@
                     int dexFlags, String compilerFilter, @Nullable String volumeUuid,
                     @Nullable String sharedLibraries, @Nullable String seInfo, boolean downgrade,
                     int targetSdkVersion, @Nullable String profileName,
-                    @Nullable String dexMetadataPath) throws InstallerException {
+                    @Nullable String dexMetadataPath, @Nullable String dexoptCompilationReason)
+                    throws InstallerException {
                 final StringBuilder builder = new StringBuilder();
 
-                // The version. Right now it's 6.
-                builder.append("6 ");
+                // The version. Right now it's 7.
+                builder.append("7 ");
 
                 builder.append("dexopt");
 
@@ -285,6 +286,7 @@
                 encodeParameter(builder, targetSdkVersion);
                 encodeParameter(builder, profileName);
                 encodeParameter(builder, dexMetadataPath);
+                encodeParameter(builder, dexoptCompilationReason);
 
                 commands.add(builder.toString());
             }
diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
index 2c68e67..77bf67d 100644
--- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java
+++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
@@ -34,7 +34,6 @@
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.server.pm.Installer.InstallerException;
-import com.android.server.pm.dex.DexManager;
 import com.android.server.pm.dex.DexoptOptions;
 import com.android.server.pm.dex.DexoptUtils;
 import com.android.server.pm.dex.PackageDexUsage;
@@ -57,13 +56,14 @@
 import static com.android.server.pm.Installer.DEXOPT_STORAGE_CE;
 import static com.android.server.pm.Installer.DEXOPT_STORAGE_DE;
 import static com.android.server.pm.Installer.DEXOPT_IDLE_BACKGROUND_JOB;
-import static com.android.server.pm.Installer.DEXOPT_DISABLE_HIDDEN_API_CHECKS;
+import static com.android.server.pm.Installer.DEXOPT_ENABLE_HIDDEN_API_CHECKS;
 import static com.android.server.pm.InstructionSets.getAppDexInstructionSets;
 import static com.android.server.pm.InstructionSets.getDexCodeInstructionSets;
 
 import static com.android.server.pm.PackageManagerService.WATCHDOG_TIMEOUT;
 
-import static dalvik.system.DexFile.getNonProfileGuidedCompilerFilter;
+import static com.android.server.pm.PackageManagerServiceCompilerMapping.getReasonName;
+
 import static dalvik.system.DexFile.getSafeModeCompilerFilter;
 import static dalvik.system.DexFile.isProfileGuidedCompilerFilter;
 
@@ -231,7 +231,8 @@
             for (String dexCodeIsa : dexCodeInstructionSets) {
                 int newResult = dexOptPath(pkg, path, dexCodeIsa, compilerFilter,
                         profileUpdated, classLoaderContexts[i], dexoptFlags, sharedGid,
-                        packageStats, options.isDowngrade(), profileName, dexMetadataPath);
+                        packageStats, options.isDowngrade(), profileName, dexMetadataPath,
+                        options.getCompilationReason());
                 // The end result is:
                 //  - FAILED if any path failed,
                 //  - PERFORMED if at least one path needed compilation,
@@ -256,7 +257,7 @@
     private int dexOptPath(PackageParser.Package pkg, String path, String isa,
             String compilerFilter, boolean profileUpdated, String classLoaderContext,
             int dexoptFlags, int uid, CompilerStats.PackageStats packageStats, boolean downgrade,
-            String profileName, String dexMetadataPath) {
+            String profileName, String dexMetadataPath, int compilationReason) {
         int dexoptNeeded = getDexoptNeeded(path, isa, compilerFilter, classLoaderContext,
                 profileUpdated, downgrade);
         if (Math.abs(dexoptNeeded) == DexFile.NO_DEXOPT_NEEDED) {
@@ -283,7 +284,7 @@
             mInstaller.dexopt(path, uid, pkg.packageName, isa, dexoptNeeded, oatDir, dexoptFlags,
                     compilerFilter, pkg.volumeUuid, classLoaderContext, pkg.applicationInfo.seInfo,
                     false /* downgrade*/, pkg.applicationInfo.targetSdkVersion,
-                    profileName, dexMetadataPath);
+                    profileName, dexMetadataPath, getReasonName(compilationReason));
 
             if (packageStats != null) {
                 long endTime = System.currentTimeMillis();
@@ -394,7 +395,7 @@
         // Note this trades correctness for performance since the resulting slow down is
         // unacceptable in some cases until b/64530081 is fixed.
         String classLoaderContext = SKIP_SHARED_LIBRARY_CHECK;
-
+        int reason = options.getCompilationReason();
         try {
             for (String isa : dexUseInfo.getLoaderIsas()) {
                 // Reuse the same dexopt path as for the primary apks. We don't need all the
@@ -405,7 +406,7 @@
                         /*oatDir*/ null, dexoptFlags,
                         compilerFilter, info.volumeUuid, classLoaderContext, info.seInfoUser,
                         options.isDowngrade(), info.targetSdkVersion, /*profileName*/ null,
-                        /*dexMetadataPath*/ null);
+                        /*dexMetadataPath*/ null, getReasonName(reason));
             }
 
             return DEX_OPT_PERFORMED;
@@ -528,11 +529,9 @@
         boolean isPublic = !info.isForwardLocked() &&
                 (!isProfileGuidedFilter || options.isDexoptInstallWithDexMetadata());
         int profileFlag = isProfileGuidedFilter ? DEXOPT_PROFILE_GUIDED : 0;
-        // System apps are invoked with a runtime flag which exempts them from
-        // restrictions on hidden API usage. We dexopt with the same runtime flag
-        // otherwise offending methods would have to be re-verified at runtime
-        // and we want to avoid the performance overhead of that.
-        int hiddenApiFlag = info.isAllowedToUseHiddenApi() ? DEXOPT_DISABLE_HIDDEN_API_CHECKS : 0;
+        // Some apps are executed with restrictions on hidden API usage. If this app is one
+        // of them, pass a flag to dexopt to enable the same restrictions during compilation.
+        int hiddenApiFlag = info.isAllowedToUseHiddenApi() ? 0 : DEXOPT_ENABLE_HIDDEN_API_CHECKS;
         int dexFlags =
                 (isPublic ? DEXOPT_PUBLIC : 0)
                 | (debuggable ? DEXOPT_DEBUGGABLE : 0)
@@ -655,8 +654,8 @@
         if ((flags & DEXOPT_IDLE_BACKGROUND_JOB) == DEXOPT_IDLE_BACKGROUND_JOB) {
             flagsList.add("idle_background_job");
         }
-        if ((flags & DEXOPT_DISABLE_HIDDEN_API_CHECKS) == DEXOPT_DISABLE_HIDDEN_API_CHECKS) {
-            flagsList.add("disable_hidden_api_checks");
+        if ((flags & DEXOPT_ENABLE_HIDDEN_API_CHECKS) == DEXOPT_ENABLE_HIDDEN_API_CHECKS) {
+            flagsList.add("enable_hidden_api_checks");
         }
 
         return String.join(",", flagsList);
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 59f9dae..0b32d1a 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -226,6 +226,7 @@
         }
     }
 
+    @GuardedBy("mSessions")
     private void reconcileStagesLocked(String volumeUuid, boolean isEphemeral) {
         final File stagingDir = buildStagingDir(volumeUuid, isEphemeral);
         final ArraySet<File> unclaimedStages = newArraySet(
@@ -283,6 +284,7 @@
         }
     }
 
+    @GuardedBy("mSessions")
     private void readSessionsLocked() {
         if (LOGD) Slog.v(TAG, "readSessionsLocked()");
 
@@ -340,6 +342,7 @@
         }
     }
 
+    @GuardedBy("mSessions")
     private void addHistoricalSessionLocked(PackageInstallerSession session) {
         CharArrayWriter writer = new CharArrayWriter();
         IndentingPrintWriter pw = new IndentingPrintWriter(writer, "    ");
@@ -352,6 +355,7 @@
                 mHistoricalSessionsByInstaller.get(installerUid) + 1);
     }
 
+    @GuardedBy("mSessions")
     private void writeSessionsLocked() {
         if (LOGD) Slog.v(TAG, "writeSessionsLocked()");
 
@@ -612,6 +616,7 @@
         }
     }
 
+    @GuardedBy("mSessions")
     private int allocateSessionIdLocked() {
         int n = 0;
         int sessionId;
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 3dd5a34..9c69281 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -318,6 +318,7 @@
     /**
      * @return {@code true} iff the installing is app an device owner or affiliated profile owner.
      */
+    @GuardedBy("mLock")
     private boolean isInstallerDeviceOwnerOrAffiliatedProfileOwnerLocked() {
         DevicePolicyManagerInternal dpmi =
                 LocalServices.getService(DevicePolicyManagerInternal.class);
@@ -334,6 +335,7 @@
      *
      * @return {@code true} iff we need to ask to confirm the permissions?
      */
+    @GuardedBy("mLock")
     private boolean needToAskForPermissionsLocked() {
         if (mPermissionsManuallyAccepted) {
             return false;
@@ -456,6 +458,7 @@
         }
     }
 
+    @GuardedBy("mLock")
     private void assertPreparedAndNotSealedLocked(String cookie) {
         assertPreparedAndNotCommittedOrDestroyedLocked(cookie);
         if (mSealed) {
@@ -463,6 +466,7 @@
         }
     }
 
+    @GuardedBy("mLock")
     private void assertPreparedAndNotCommittedOrDestroyedLocked(String cookie) {
         assertPreparedAndNotDestroyedLocked(cookie);
         if (mCommitted) {
@@ -470,6 +474,7 @@
         }
     }
 
+    @GuardedBy("mLock")
     private void assertPreparedAndNotDestroyedLocked(String cookie) {
         if (!mPrepared) {
             throw new IllegalStateException(cookie + " before prepared");
@@ -484,6 +489,7 @@
      * might point at an ASEC mount point, which is why we delay path resolution
      * until someone actively works with the session.
      */
+    @GuardedBy("mLock")
     private File resolveStageDirLocked() throws IOException {
         if (mResolvedStageDir == null) {
             if (stageDir != null) {
@@ -516,6 +522,7 @@
         }
     }
 
+    @GuardedBy("mLock")
     private void computeProgressLocked(boolean forcePublish) {
         mProgress = MathUtils.constrain(mClientProgress * 0.8f, 0f, 0.8f)
                 + MathUtils.constrain(mInternalProgress * 0.2f, 0f, 0.2f);
@@ -728,6 +735,7 @@
      * Check if the caller is the owner of this session. Otherwise throw a
      * {@link SecurityException}.
      */
+    @GuardedBy("mLock")
     private void assertCallerIsOwnerOrRootLocked() {
         final int callingUid = Binder.getCallingUid();
         if (callingUid != Process.ROOT_UID && callingUid != mInstallerUid) {
@@ -738,6 +746,7 @@
     /**
      * If anybody is reading or writing data of the session, throw an {@link SecurityException}.
      */
+    @GuardedBy("mLock")
     private void assertNoWriteFileTransfersOpenLocked() {
         // Verify that all writers are hands-off
         for (RevocableFileDescriptor fd : mFds) {
@@ -820,6 +829,7 @@
      * @throws PackageManagerException if the session was sealed but something went wrong. If the
      *                                 session was sealed this is the only possible exception.
      */
+    @GuardedBy("mLock")
     private void sealAndValidateLocked() throws PackageManagerException, IOException {
         assertNoWriteFileTransfersOpenLocked();
         assertPreparedAndNotDestroyedLocked("sealing of session");
@@ -901,6 +911,7 @@
         mCallback.onSessionSealedBlocking(this);
     }
 
+    @GuardedBy("mLock")
     private void commitLocked()
             throws PackageManagerException {
         if (mDestroyed) {
@@ -1016,6 +1027,7 @@
      * Note that upgrade compatibility is still performed by
      * {@link PackageManagerService}.
      */
+    @GuardedBy("mLock")
     private void validateInstallLocked(@Nullable PackageInfo pkgInfo)
             throws PackageManagerException {
         mPackageName = null;
@@ -1228,6 +1240,7 @@
         }
     }
 
+    @GuardedBy("mLock")
     private void assertApkConsistentLocked(String tag, ApkLite apk)
             throws PackageManagerException {
         if (!mPackageName.equals(apk.packageName)) {
@@ -1511,6 +1524,7 @@
         }
     }
 
+    @GuardedBy("mLock")
     private void dumpLocked(IndentingPrintWriter pw) {
         pw.println("Session " + sessionId + ":");
         pw.increaseIndent();
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 4993708..de5adb9 100755
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -554,9 +554,9 @@
 
     public static final String PLATFORM_PACKAGE_NAME = "android";
 
-    static final String DEFAULT_CONTAINER_PACKAGE = "com.android.defcontainer";
+    public static final String DEFAULT_CONTAINER_PACKAGE = "com.android.defcontainer";
 
-    static final ComponentName DEFAULT_CONTAINER_COMPONENT = new ComponentName(
+    public static final ComponentName DEFAULT_CONTAINER_COMPONENT = new ComponentName(
             DEFAULT_CONTAINER_PACKAGE,
             "com.android.defcontainer.DefaultContainerService");
 
@@ -599,6 +599,7 @@
     }
 
     // Compilation reasons.
+    public static final int REASON_UNKNOWN = -1;
     public static final int REASON_FIRST_BOOT = 0;
     public static final int REASON_BOOT = 1;
     public static final int REASON_INSTALL = 2;
@@ -798,6 +799,7 @@
             return overlayPackages;
         }
 
+        @GuardedBy("mInstallLock")
         final String[] getStaticOverlayPathsLocked(Collection<PackageParser.Package> allPackages,
                 String targetPackageName, String targetPath) {
             if ("android".equals(targetPackageName)) {
@@ -965,7 +967,7 @@
     volatile boolean mSystemReady;
     volatile boolean mSafeMode;
     volatile boolean mHasSystemUidErrors;
-    private volatile boolean mEphemeralAppsDisabled;
+    private volatile boolean mWebInstantAppsDisabled;
 
     ApplicationInfo mAndroidApplication;
     final ActivityInfo mResolveActivity = new ActivityInfo();
@@ -2743,11 +2745,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);
                         }
@@ -2776,18 +2779,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();
 
@@ -5240,7 +5231,13 @@
 
     @Override
     public int checkUidPermission(String permName, int uid) {
-        return mPermissionManager.checkUidPermission(permName, uid, getCallingUid());
+        synchronized (mPackages) {
+            final String[] packageNames = getPackagesForUid(uid);
+            final PackageParser.Package pkg = (packageNames != null && packageNames.length > 0)
+                    ? mPackages.get(packageNames[0])
+                    : null;
+            return mPermissionManager.checkUidPermission(permName, pkg, uid, getCallingUid());
+        }
     }
 
     @Override
@@ -5974,11 +5971,11 @@
     /**
      * Returns whether or not instant apps have been disabled remotely.
      */
-    private boolean isEphemeralDisabled() {
-        return mEphemeralAppsDisabled;
+    private boolean areWebInstantAppsDisabled() {
+        return mWebInstantAppsDisabled;
     }
 
-    private boolean isInstantAppAllowed(
+    private boolean isInstantAppResolutionAllowed(
             Intent intent, List<ResolveInfo> resolvedActivities, int userId,
             boolean skipPackageCheck) {
         if (mInstantAppResolverConnection == null) {
@@ -6003,8 +6000,12 @@
                     || (intent.getFlags() & Intent.FLAG_ACTIVITY_MATCH_EXTERNAL) == 0) {
                 return false;
             }
-        } else if (intent.getData() == null || TextUtils.isEmpty(intent.getData().getHost())) {
-            return false;
+        } else {
+            if (intent.getData() == null || TextUtils.isEmpty(intent.getData().getHost())) {
+                return false;
+            } else if (areWebInstantAppsDisabled()) {
+                return false;
+            }
         }
         // Deny ephemeral apps if the user chose _ALWAYS or _ALWAYS_ASK for intent resolution.
         // Or if there's already an ephemeral app installed that handles the action
@@ -6535,14 +6536,13 @@
                 }
             }
             return applyPostResolutionFilter(
-                    list, instantAppPkgName, allowDynamicSplits, filterCallingUid, userId);
+                    list, instantAppPkgName, allowDynamicSplits, filterCallingUid, userId, intent);
         }
 
         // reader
         boolean sortResult = false;
-        boolean addEphemeral = false;
+        boolean addInstant = false;
         List<ResolveInfo> result;
-        final boolean ephemeralDisabled = isEphemeralDisabled();
         synchronized (mPackages) {
             if (pkgName == null) {
                 List<CrossProfileIntentFilter> matchingFilters =
@@ -6555,14 +6555,14 @@
                     xpResult.add(xpResolveInfo);
                     return applyPostResolutionFilter(
                             filterIfNotSystemUser(xpResult, userId), instantAppPkgName,
-                            allowDynamicSplits, filterCallingUid, userId);
+                            allowDynamicSplits, filterCallingUid, userId, intent);
                 }
 
                 // Check for results in the current profile.
                 result = filterIfNotSystemUser(mActivities.queryIntent(
                         intent, resolvedType, flags, userId), userId);
-                addEphemeral = !ephemeralDisabled
-                        && isInstantAppAllowed(intent, result, userId, false /*skipPackageCheck*/);
+                addInstant = isInstantAppResolutionAllowed(intent, result, userId,
+                        false /*skipPackageCheck*/);
                 // Check for cross profile results.
                 boolean hasNonNegativePriorityResult = hasNonNegativePriority(result);
                 xpResolveInfo = queryCrossProfileIntents(
@@ -6589,20 +6589,20 @@
                             // in the result.
                             result.remove(xpResolveInfo);
                         }
-                        if (result.size() == 0 && !addEphemeral) {
+                        if (result.size() == 0 && !addInstant) {
                             // No result in current profile, but found candidate in parent user.
                             // And we are not going to add emphemeral app, so we can return the
                             // result straight away.
                             result.add(xpDomainInfo.resolveInfo);
                             return applyPostResolutionFilter(result, instantAppPkgName,
-                                    allowDynamicSplits, filterCallingUid, userId);
+                                    allowDynamicSplits, filterCallingUid, userId, intent);
                         }
-                    } else if (result.size() <= 1 && !addEphemeral) {
+                    } else if (result.size() <= 1 && !addInstant) {
                         // No result in parent user and <= 1 result in current profile, and we
                         // are not going to add emphemeral app, so we can return the result without
                         // further processing.
                         return applyPostResolutionFilter(result, instantAppPkgName,
-                                allowDynamicSplits, filterCallingUid, userId);
+                                allowDynamicSplits, filterCallingUid, userId, intent);
                     }
                     // We have more than one candidate (combining results from current and parent
                     // profile), so we need filtering and sorting.
@@ -6622,8 +6622,7 @@
                 if (result == null || result.size() == 0) {
                     // the caller wants to resolve for a particular package; however, there
                     // were no installed results, so, try to find an ephemeral result
-                    addEphemeral = !ephemeralDisabled
-                            && isInstantAppAllowed(
+                    addInstant = isInstantAppResolutionAllowed(
                                     intent, null /*result*/, userId, true /*skipPackageCheck*/);
                     if (result == null) {
                         result = new ArrayList<>();
@@ -6631,7 +6630,7 @@
                 }
             }
         }
-        if (addEphemeral) {
+        if (addInstant) {
             result = maybeAddInstantAppInstaller(
                     result, intent, resolvedType, flags, userId, resolveForStart);
         }
@@ -6639,7 +6638,7 @@
             Collections.sort(result, mResolvePrioritySorter);
         }
         return applyPostResolutionFilter(
-                result, instantAppPkgName, allowDynamicSplits, filterCallingUid, userId);
+                result, instantAppPkgName, allowDynamicSplits, filterCallingUid, userId, intent);
     }
 
     private List<ResolveInfo> maybeAddInstantAppInstaller(List<ResolveInfo> result, Intent intent,
@@ -6843,12 +6842,20 @@
      * @param resolveInfos The pre-filtered list of resolved activities
      * @param ephemeralPkgName The ephemeral package name. If {@code null}, no filtering
      *          is performed.
+     * @param intent
      * @return A filtered list of resolved activities.
      */
     private List<ResolveInfo> applyPostResolutionFilter(List<ResolveInfo> resolveInfos,
-            String ephemeralPkgName, boolean allowDynamicSplits, int filterCallingUid, int userId) {
+            String ephemeralPkgName, boolean allowDynamicSplits, int filterCallingUid, int userId,
+            Intent intent) {
+        final boolean blockInstant = intent.isWebIntent() && areWebInstantAppsDisabled();
         for (int i = resolveInfos.size() - 1; i >= 0; i--) {
             final ResolveInfo info = resolveInfos.get(i);
+            // remove locally resolved instant app web results when disabled
+            if (info.isInstantAppAvailable && blockInstant) {
+                resolveInfos.remove(i);
+                continue;
+            }
             // allow activities that are defined in the provided package
             if (allowDynamicSplits
                     && info.activityInfo != null
@@ -7480,7 +7487,7 @@
                 }
             }
             return applyPostResolutionFilter(
-                    list, instantAppPkgName, allowDynamicSplits, callingUid, userId);
+                    list, instantAppPkgName, allowDynamicSplits, callingUid, userId, intent);
         }
 
         // reader
@@ -7490,14 +7497,14 @@
                 final List<ResolveInfo> result =
                         mReceivers.queryIntent(intent, resolvedType, flags, userId);
                 return applyPostResolutionFilter(
-                        result, instantAppPkgName, allowDynamicSplits, callingUid, userId);
+                        result, instantAppPkgName, allowDynamicSplits, callingUid, userId, intent);
             }
             final PackageParser.Package pkg = mPackages.get(pkgName);
             if (pkg != null) {
                 final List<ResolveInfo> result = mReceivers.queryIntentForPackage(
                         intent, resolvedType, flags, pkg.receivers, userId);
                 return applyPostResolutionFilter(
-                        result, instantAppPkgName, allowDynamicSplits, callingUid, userId);
+                        result, instantAppPkgName, allowDynamicSplits, callingUid, userId, intent);
             }
             return Collections.emptyList();
         }
@@ -7967,7 +7974,7 @@
 
     @Override
     public ParceledListSlice<InstantAppInfo> getInstantApps(int userId) {
-        if (HIDE_EPHEMERAL_APIS || isEphemeralDisabled()) {
+        if (HIDE_EPHEMERAL_APIS) {
             return null;
         }
         if (!canViewInstantApps(Binder.getCallingUid(), userId)) {
@@ -7992,7 +7999,7 @@
         mPermissionManager.enforceCrossUserPermission(Binder.getCallingUid(), userId,
                 true /* requireFullPermission */, false /* checkShell */,
                 "isInstantApp");
-        if (HIDE_EPHEMERAL_APIS || isEphemeralDisabled()) {
+        if (HIDE_EPHEMERAL_APIS) {
             return false;
         }
 
@@ -8018,7 +8025,7 @@
 
     @Override
     public byte[] getInstantAppCookie(String packageName, int userId) {
-        if (HIDE_EPHEMERAL_APIS || isEphemeralDisabled()) {
+        if (HIDE_EPHEMERAL_APIS) {
             return null;
         }
 
@@ -8036,7 +8043,7 @@
 
     @Override
     public boolean setInstantAppCookie(String packageName, byte[] cookie, int userId) {
-        if (HIDE_EPHEMERAL_APIS || isEphemeralDisabled()) {
+        if (HIDE_EPHEMERAL_APIS) {
             return true;
         }
 
@@ -8054,7 +8061,7 @@
 
     @Override
     public Bitmap getInstantAppIcon(String packageName, int userId) {
-        if (HIDE_EPHEMERAL_APIS || isEphemeralDisabled()) {
+        if (HIDE_EPHEMERAL_APIS) {
             return null;
         }
 
@@ -8861,7 +8868,7 @@
 
         final long startTime = System.nanoTime();
         final int[] stats = performDexOptUpgrade(pkgs, mIsPreNUpgrade /* showDialog */,
-                    getCompilerFilterForReason(causeFirstBoot ? REASON_FIRST_BOOT : REASON_BOOT),
+                    causeFirstBoot ? REASON_FIRST_BOOT : REASON_BOOT,
                     false /* bootComplete */);
 
         final int elapsedTimeSeconds =
@@ -8888,7 +8895,7 @@
      * and {@code numberOfPackagesFailed}.
      */
     private int[] performDexOptUpgrade(List<PackageParser.Package> pkgs, boolean showDialog,
-            final String compilerFilter, boolean bootComplete) {
+            final int compilationReason, boolean bootComplete) {
 
         int numberOfPackagesVisited = 0;
         int numberOfPackagesOptimized = 0;
@@ -8988,13 +8995,11 @@
                 }
             }
 
-            String pkgCompilerFilter = compilerFilter;
+            int pkgCompilationReason = compilationReason;
             if (useProfileForDexopt) {
                 // Use background dexopt mode to try and use the profile. Note that this does not
                 // guarantee usage of the profile.
-                pkgCompilerFilter =
-                        PackageManagerServiceCompilerMapping.getCompilerFilterForReason(
-                                PackageManagerService.REASON_BACKGROUND_DEXOPT);
+                pkgCompilationReason = PackageManagerService.REASON_BACKGROUND_DEXOPT;
             }
 
             // checkProfiles is false to avoid merging profiles during boot which
@@ -9005,7 +9010,7 @@
             int dexoptFlags = bootComplete ? DexoptOptions.DEXOPT_BOOT_COMPLETE : 0;
             int primaryDexOptStaus = performDexOptTraced(new DexoptOptions(
                     pkg.packageName,
-                    pkgCompilerFilter,
+                    pkgCompilationReason,
                     dexoptFlags));
 
             switch (primaryDexOptStaus) {
@@ -9046,6 +9051,7 @@
         }
     }
 
+    @GuardedBy("mPackages")
     private void notifyPackageUseLocked(String packageName, int reason) {
         final PackageParser.Package p = mPackages.get(packageName);
         if (p == null) {
@@ -9105,8 +9111,8 @@
         int flags = (checkProfiles ? DexoptOptions.DEXOPT_CHECK_FOR_PROFILES_UPDATES : 0) |
                 (force ? DexoptOptions.DEXOPT_FORCE : 0) |
                 (bootComplete ? DexoptOptions.DEXOPT_BOOT_COMPLETE : 0);
-        return performDexOpt(new DexoptOptions(packageName, targetCompilerFilter,
-                splitName, flags));
+        return performDexOpt(new DexoptOptions(packageName, REASON_UNKNOWN,
+                targetCompilerFilter, splitName, flags));
     }
 
     /**
@@ -9215,7 +9221,8 @@
         final String[] instructionSets = getAppDexInstructionSets(p.applicationInfo);
         if (!deps.isEmpty()) {
             DexoptOptions libraryOptions = new DexoptOptions(options.getPackageName(),
-                    options.getCompilerFilter(), options.getSplitName(),
+                    options.getCompilationReason(), options.getCompilerFilter(),
+                    options.getSplitName(),
                     options.getFlags() | DexoptOptions.DEXOPT_AS_SHARED_LIBRARY);
             for (PackageParser.Package depPackage : deps) {
                 // TODO: Analyze and investigate if we (should) profile libraries.
@@ -10656,8 +10663,6 @@
                     ~ApplicationInfo.PRIVATE_FLAG_DEFAULT_TO_DEVICE_PROTECTED_STORAGE;
             pkg.applicationInfo.privateFlags &=
                     ~ApplicationInfo.PRIVATE_FLAG_DIRECT_BOOT_AWARE;
-            // clear protected broadcasts
-            pkg.protectedBroadcasts = null;
             // cap permission priorities
             if (pkg.permissionGroups != null && pkg.permissionGroups.size() > 0) {
                 for (int i = pkg.permissionGroups.size() - 1; i >= 0; --i) {
@@ -10666,6 +10671,8 @@
             }
         }
         if ((scanFlags & SCAN_AS_PRIVILEGED) == 0) {
+            // clear protected broadcasts
+            pkg.protectedBroadcasts = null;
             // ignore export request for single user receivers
             if (pkg.receivers != null) {
                 for (int i = pkg.receivers.size() - 1; i >= 0; --i) {
@@ -13985,6 +13992,7 @@
         }
     }
 
+    @GuardedBy("mPackages")
     private boolean canSuspendPackageForUserLocked(String packageName, int userId) {
         if (isPackageDeviceAdmin(packageName, userId)) {
             Slog.w(TAG, "Cannot suspend/un-suspend package \"" + packageName
@@ -16586,17 +16594,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) {
@@ -16641,6 +16639,12 @@
                 if (userId != UserHandle.USER_ALL) {
                     ps.setInstalled(true, userId);
                     ps.setEnabled(COMPONENT_ENABLED_STATE_DEFAULT, userId, installerPackageName);
+                } else {
+                    for (int currentUserId : sUserManager.getUserIds()) {
+                        ps.setInstalled(true, currentUserId);
+                        ps.setEnabled(COMPONENT_ENABLED_STATE_DEFAULT, currentUserId,
+                                installerPackageName);
+                    }
                 }
 
                 // When replacing an existing package, preserve the original install reason for all
@@ -16671,7 +16675,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
@@ -18757,7 +18760,7 @@
         return true;
     }
 
-    private final class ClearStorageConnection implements ServiceConnection {
+    private static final class ClearStorageConnection implements ServiceConnection {
         IMediaContainerService mContainerService;
 
         @Override
@@ -19124,8 +19127,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");
@@ -20659,10 +20675,6 @@
     @Override
     public String getInstallerPackageName(String packageName) {
         final int callingUid = Binder.getCallingUid();
-        if (getInstantAppPackageName(callingUid) != null) {
-            return null;
-        }
-        // reader
         synchronized (mPackages) {
             final PackageSetting ps = mSettings.mPackages.get(packageName);
             if (filterAppAccessLPr(ps, callingUid, UserHandle.getUserId(callingUid))) {
@@ -20727,7 +20739,7 @@
         ContentObserver co = new ContentObserver(mHandler) {
             @Override
             public void onChange(boolean selfChange) {
-                mEphemeralAppsDisabled =
+                mWebInstantAppsDisabled =
                         (Global.getInt(resolver, Global.ENABLE_EPHEMERAL_FEATURE, 1) == 0) ||
                                 (Secure.getInt(resolver, Secure.INSTANT_APPS_ENABLED, 1) == 0);
             }
@@ -20735,7 +20747,7 @@
         mContext.getContentResolver().registerContentObserver(android.provider.Settings.Global
                         .getUriFor(Global.ENABLE_EPHEMERAL_FEATURE),
                 false, co, UserHandle.USER_SYSTEM);
-        mContext.getContentResolver().registerContentObserver(android.provider.Settings.Global
+        mContext.getContentResolver().registerContentObserver(android.provider.Settings.Secure
                         .getUriFor(Secure.INSTANT_APPS_ENABLED), false, co, UserHandle.USER_SYSTEM);
         co.onChange(true);
 
@@ -20967,7 +20979,6 @@
                 pw.println("    check-permission <permission> <package> [<user>]: does pkg hold perm?");
                 pw.println("    dexopt: dump dexopt state");
                 pw.println("    compiler-stats: dump compiler statistics");
-                pw.println("    enabled-overlays: dump list of enabled overlay packages");
                 pw.println("    service-permissions: dump permissions required by services");
                 pw.println("    <package.name>: info about given package");
                 return;
@@ -21455,35 +21466,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)
@@ -21612,61 +21625,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();
+            }
         }
     }
 
@@ -22245,8 +22260,16 @@
                 Slog.e(TAG, "Failed to create app data for " + packageName + ": " + e);
             }
         }
-        // Prepare the application profiles.
-        mArtManagerService.prepareAppProfiles(pkg, userId);
+        // Prepare the application profiles only for upgrades and first boot (so that we don't
+        // repeat the same operation at each boot).
+        // We only have to cover the upgrade and first boot here because for app installs we
+        // prepare the profiles before invoking dexopt (in installPackageLI).
+        //
+        // We also have to cover non system users because we do not call the usual install package
+        // methods for them.
+        if (mIsUpgrade || mFirstBoot || (userId != UserHandle.USER_SYSTEM)) {
+            mArtManagerService.prepareAppProfiles(pkg, userId);
+        }
 
         if ((flags & StorageManager.FLAG_STORAGE_CE) != 0 && ceDataInode != -1) {
             // TODO: mark this structure as dirty so we persist it!
diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceCompilerMapping.java b/services/core/java/com/android/server/pm/PackageManagerServiceCompilerMapping.java
index 19b0d9b..fce8285 100644
--- a/services/core/java/com/android/server/pm/PackageManagerServiceCompilerMapping.java
+++ b/services/core/java/com/android/server/pm/PackageManagerServiceCompilerMapping.java
@@ -123,4 +123,14 @@
 
         return value;
     }
+
+    public static String getReasonName(int reason) {
+        if (reason == PackageManagerService.REASON_UNKNOWN) {
+            return "unknown";
+        }
+        if (reason < 0 || reason >= REASON_STRINGS.length) {
+            throw new IllegalArgumentException("reason " + reason + " invalid");
+        }
+        return REASON_STRINGS[reason];
+    }
 }
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..a38cbda 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,10 +4633,15 @@
         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();
 
+        if (ps.pkg.mOverlayTarget != null) {
+            pw.print(prefix); pw.print("  overlayTarget="); pw.println(ps.pkg.mOverlayTarget);
+            pw.print(prefix); pw.print("  overlayCategory="); pw.println(ps.pkg.mOverlayCategory);
+        }
+
         if (ps.pkg != null && ps.pkg.permissions != null && ps.pkg.permissions.size() > 0) {
             final ArrayList<PackageParser.Permission> perms = ps.pkg.permissions;
             pw.print(prefix); pw.println("  declared permissions:");
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index a85d6d8..034fd23 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -530,6 +530,7 @@
         return processState <= PROCESS_STATE_FOREGROUND_THRESHOLD;
     }
 
+    @GuardedBy("mLock")
     boolean isUidForegroundLocked(int uid) {
         if (uid == Process.SYSTEM_UID) {
             // IUidObserver doesn't report the state of SYSTEM, but it always has bound services,
@@ -545,6 +546,7 @@
         return isProcessStateForeground(mActivityManagerInternal.getUidProcessState(uid));
     }
 
+    @GuardedBy("mLock")
     long getUidLastForegroundElapsedTimeLocked(int uid) {
         return mUidLastForegroundElapsedTime.get(uid);
     }
@@ -638,6 +640,7 @@
         }
     }
 
+    @GuardedBy("mLock")
     private void unloadUserLocked(int userId) {
         if (DEBUG) {
             Slog.d(TAG, "unloadUserLocked: user=" + userId);
@@ -864,6 +867,7 @@
         writeAttr(out, name, intent.toUri(/* flags =*/ 0));
     }
 
+    @GuardedBy("mLock")
     @VisibleForTesting
     void saveBaseStateLocked() {
         final AtomicFile file = getBaseStateFile();
@@ -896,6 +900,7 @@
         }
     }
 
+    @GuardedBy("mLock")
     private void loadBaseStateLocked() {
         mRawLastResetTime = 0;
 
@@ -948,6 +953,7 @@
         return new File(injectUserDataPath(userId), FILENAME_USER_PACKAGES);
     }
 
+    @GuardedBy("mLock")
     private void saveUserLocked(@UserIdInt int userId) {
         final File path = getUserFile(userId);
         if (DEBUG) {
@@ -974,6 +980,7 @@
         }
     }
 
+    @GuardedBy("mLock")
     private void saveUserInternalLocked(@UserIdInt int userId, OutputStream os,
             boolean forBackup) throws IOException, XmlPullParserException {
 
@@ -1107,12 +1114,14 @@
     }
 
     /** Return the last reset time. */
+    @GuardedBy("mLock")
     long getLastResetTimeLocked() {
         updateTimesLocked();
         return mRawLastResetTime;
     }
 
     /** Return the next reset time. */
+    @GuardedBy("mLock")
     long getNextResetTimeLocked() {
         updateTimesLocked();
         return mRawLastResetTime + mResetInterval;
@@ -1125,6 +1134,7 @@
     /**
      * Update the last reset time.
      */
+    @GuardedBy("mLock")
     private void updateTimesLocked() {
 
         final long now = injectCurrentTimeMillis();
@@ -1220,6 +1230,7 @@
         return ret;
     }
 
+    @GuardedBy("mLock")
     void forEachLoadedUserLocked(@NonNull Consumer<ShortcutUser> c) {
         for (int i = mUsers.size() - 1; i >= 0; i--) {
             c.accept(mUsers.valueAt(i));
@@ -1279,6 +1290,7 @@
      * {@link ShortcutBitmapSaver#waitForAllSavesLocked()} to make sure there's no pending bitmap
      * saves are going on.
      */
+    @GuardedBy("mLock")
     private void cleanupDanglingBitmapDirectoriesLocked(@UserIdInt int userId) {
         if (DEBUG) {
             Slog.d(TAG, "cleanupDanglingBitmaps: userId=" + userId);
@@ -2108,6 +2120,7 @@
         }
     }
 
+    @GuardedBy("mLock")
     private ParceledListSlice<ShortcutInfo> getShortcutsWithQueryLocked(@NonNull String packageName,
             @UserIdInt int userId, int cloneFlags, @NonNull Predicate<ShortcutInfo> query) {
 
@@ -2418,6 +2431,7 @@
      *
      * This is called when an app is uninstalled, or an app gets "clear data"ed.
      */
+    @GuardedBy("mLock")
     @VisibleForTesting
     void cleanUpPackageLocked(String packageName, int owningUserId, int packageUserId,
             boolean appStillExists) {
@@ -2508,6 +2522,7 @@
             return setReturnedByServer(ret);
         }
 
+        @GuardedBy("ShortcutService.this.mLock")
         private void getShortcutsInnerLocked(int launcherUserId, @NonNull String callingPackage,
                 @Nullable String packageName, @Nullable List<String> shortcutIds, long changedSince,
                 @Nullable ComponentName componentName, int queryFlags,
@@ -2579,6 +2594,7 @@
             }
         }
 
+        @GuardedBy("ShortcutService.this.mLock")
         private ShortcutInfo getShortcutInfoLocked(
                 int launcherUserId, @NonNull String callingPackage,
                 @NonNull String packageName, @NonNull String shortcutId, int userId,
@@ -2940,6 +2956,7 @@
         verifyStates();
     }
 
+    @GuardedBy("mLock")
     private void rescanUpdatedPackagesLocked(@UserIdInt int userId, long lastScanTime) {
         final ShortcutUser user = getUserShortcutsLocked(userId);
 
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index b53d83b..0eeaf66 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -1486,6 +1486,23 @@
         return restrictions != null && restrictions.getBoolean(restrictionKey);
     }
 
+    /** @return if any user has the given restriction. */
+    @Override
+    public boolean hasUserRestrictionOnAnyUser(String restrictionKey) {
+        if (!UserRestrictionsUtils.isValidRestriction(restrictionKey)) {
+            return false;
+        }
+        final List<UserInfo> users = getUsers(/* excludeDying= */ true);
+        for (int i = 0; i < users.size(); i++) {
+            final int userId = users.get(i).id;
+            Bundle restrictions = getEffectiveUserRestrictions(userId);
+            if (restrictions != null && restrictions.getBoolean(restrictionKey)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     /**
      * @hide
      *
@@ -1547,6 +1564,7 @@
         return result;
     }
 
+    @GuardedBy("mRestrictionsLock")
     private EnforcingUser getEnforcingUserLocked(@UserIdInt int userId) {
         int source = mDeviceOwnerUserId == userId ? UserManager.RESTRICTION_SOURCE_DEVICE_OWNER
                 : UserManager.RESTRICTION_SOURCE_PROFILE_OWNER;
@@ -2896,6 +2914,7 @@
         }
     }
 
+    @GuardedBy("mUsersLock")
     @VisibleForTesting
     void addRemovingUserIdLocked(int userId) {
         // We remember deleted user IDs to prevent them from being
@@ -3405,6 +3424,7 @@
         return nextId;
     }
 
+    @GuardedBy("mUsersLock")
     private int scanNextAvailableIdLocked() {
         for (int i = MIN_USER_ID; i < MAX_USER_ID; i++) {
             if (mUsers.indexOfKey(i) < 0 && !mRemovingUserIds.get(i)) {
diff --git a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
index 842f8d0..41570c4 100644
--- a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
+++ b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
@@ -33,6 +33,7 @@
 import android.os.UserManager;
 import android.os.UserManagerInternal;
 import android.provider.Settings;
+import android.provider.Settings.Global;
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
 import android.util.Log;
@@ -122,7 +123,8 @@
             UserManager.DISALLOW_CONFIG_BRIGHTNESS,
             UserManager.DISALLOW_SHARE_INTO_MANAGED_PROFILE,
             UserManager.DISALLOW_AMBIENT_DISPLAY,
-            UserManager.DISALLOW_CONFIG_SCREEN_TIMEOUT
+            UserManager.DISALLOW_CONFIG_SCREEN_TIMEOUT,
+            UserManager.DISALLOW_PRINTING
     });
 
     /**
@@ -580,6 +582,15 @@
                                 Settings.Secure.DOZE_PULSE_ON_DOUBLE_TAP, "0");
                     }
                     break;
+                case UserManager.DISALLOW_CONFIG_LOCATION:
+                    // When DISALLOW_CONFIG_LOCATION is set on any user, we undo the global
+                    // kill switch.
+                    if (newValue) {
+                        android.provider.Settings.Global.putString(
+                                context.getContentResolver(),
+                                Global.LOCATION_GLOBAL_KILL_SWITCH, "0");
+                    }
+                    break;
             }
         } finally {
             Binder.restoreCallingIdentity(id);
diff --git a/services/core/java/com/android/server/pm/dex/DexManager.java b/services/core/java/com/android/server/pm/dex/DexManager.java
index 0e2730c..3e63fb4 100644
--- a/services/core/java/com/android/server/pm/dex/DexManager.java
+++ b/services/core/java/com/android/server/pm/dex/DexManager.java
@@ -549,13 +549,12 @@
             mPackageDexUsage.maybeWriteAsync();
         }
 
-        // Try to optimize the package according to the install reason.
-        String compilerFilter = PackageManagerServiceCompilerMapping.getCompilerFilterForReason(
-                PackageManagerService.REASON_INSTALL);
         DexUseInfo dexUseInfo = mPackageDexUsage.getPackageUseInfo(searchResult.mOwningPackageName)
                 .getDexUseInfoMap().get(dexPath);
 
-        DexoptOptions options = new DexoptOptions(info.packageName, compilerFilter, /*flags*/0);
+        // Try to optimize the package according to the install reason.
+        DexoptOptions options = new DexoptOptions(info.packageName,
+                PackageManagerService.REASON_INSTALL, /*flags*/0);
 
         int result = mPackageDexOptimizer.dexOptSecondaryDexPath(info, dexPath, dexUseInfo,
                 options);
diff --git a/services/core/java/com/android/server/pm/dex/DexoptOptions.java b/services/core/java/com/android/server/pm/dex/DexoptOptions.java
index d4f95cb..a7a7686 100644
--- a/services/core/java/com/android/server/pm/dex/DexoptOptions.java
+++ b/services/core/java/com/android/server/pm/dex/DexoptOptions.java
@@ -77,15 +77,21 @@
     // It only applies for primary apk and it's always null if mOnlySecondaryDex is true.
     private final String mSplitName;
 
+    // The reason for invoking dexopt (see PackageManagerService.REASON_* constants).
+    // A -1 value denotes an unknown reason.
+    private final int mCompilationReason;
+
     public DexoptOptions(String packageName, String compilerFilter, int flags) {
-        this(packageName, compilerFilter, /*splitName*/ null, flags);
+        this(packageName, /*compilationReason*/ -1, compilerFilter, /*splitName*/ null, flags);
     }
 
-    public DexoptOptions(String packageName, int compilerReason, int flags) {
-        this(packageName, getCompilerFilterForReason(compilerReason), flags);
+    public DexoptOptions(String packageName, int compilationReason, int flags) {
+        this(packageName, compilationReason, getCompilerFilterForReason(compilationReason),
+                /*splitName*/ null, flags);
     }
 
-    public DexoptOptions(String packageName, String compilerFilter, String splitName, int flags) {
+    public DexoptOptions(String packageName, int compilationReason, String compilerFilter,
+                String splitName, int flags) {
         int validityMask =
                 DEXOPT_CHECK_FOR_PROFILES_UPDATES |
                 DEXOPT_FORCE |
@@ -104,6 +110,7 @@
         mCompilerFilter = compilerFilter;
         mFlags = flags;
         mSplitName = splitName;
+        mCompilationReason = compilationReason;
     }
 
     public String getPackageName() {
@@ -157,4 +164,8 @@
     public int getFlags() {
         return mFlags;
     }
+
+    public int getCompilationReason() {
+        return mCompilationReason;
+    }
 }
diff --git a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
index 6308766..4abcce1 100644
--- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
@@ -16,7 +16,7 @@
 
 package com.android.server.pm.permission;
 
-import static com.android.server.pm.PackageManagerServiceUtils.compareSignatures;
+import static android.os.Process.FIRST_APPLICATION_UID;
 
 import android.Manifest;
 import android.annotation.NonNull;
@@ -25,18 +25,18 @@
 import android.app.DownloadManager;
 import android.app.admin.DevicePolicyManager;
 import android.companion.CompanionDeviceManager;
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.ApplicationInfo;
-import android.content.pm.IPackageManager;
 import android.content.pm.PackageList;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManagerInternal;
+import android.content.pm.PackageManagerInternal.PackagesProvider;
+import android.content.pm.PackageManagerInternal.SyncAdapterPackagesProvider;
 import android.content.pm.PackageParser;
 import android.content.pm.ProviderInfo;
 import android.content.pm.ResolveInfo;
-import android.content.pm.PackageManagerInternal.PackagesProvider;
-import android.content.pm.PackageManagerInternal.SyncAdapterPackagesProvider;
 import android.media.RingtoneManager;
 import android.net.Uri;
 import android.os.Binder;
@@ -52,15 +52,18 @@
 import android.provider.ContactsContract;
 import android.provider.MediaStore;
 import android.provider.Telephony.Sms.Intents;
-import android.telephony.TelephonyManager;
 import android.security.Credentials;
+import android.service.textclassifier.TextClassifierService;
+import android.telephony.TelephonyManager;
 import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.Log;
 import android.util.Slog;
 import android.util.Xml;
+
 import com.android.internal.util.XmlUtils;
 import com.android.server.LocalServices;
+import com.android.server.pm.PackageManagerService;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
@@ -71,14 +74,11 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.ArrayList;
-import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
-import static android.os.Process.FIRST_APPLICATION_UID;
-
 /**
  * This class is the policy for granting runtime permissions to
  * platform components and default handlers in the system such
@@ -433,6 +433,13 @@
             grantRuntimePermissions(storagePackage, STORAGE_PERMISSIONS, true, userId);
         }
 
+        // Container service
+        PackageParser.Package containerPackage = getSystemPackage(
+                PackageManagerService.DEFAULT_CONTAINER_PACKAGE);
+        if (containerPackage != null) {
+            grantRuntimePermissions(containerPackage, STORAGE_PERMISSIONS, true, userId);
+        }
+
         // CertInstaller
         Intent certInstallerIntent = new Intent(Credentials.INSTALL_ACTION);
         PackageParser.Package certInstallerPackage = getDefaultSystemHandlerActivityPackage(
@@ -821,6 +828,24 @@
                     STORAGE_PERMISSIONS, true, userId);
         }
 
+        // TextClassifier Service
+        ComponentName textClassifierComponent =
+                TextClassifierService.getServiceComponentName(mContext);
+        if (textClassifierComponent != null) {
+            Intent textClassifierServiceIntent = new Intent(TextClassifierService.SERVICE_INTERFACE)
+                    .setComponent(textClassifierComponent);
+            PackageParser.Package textClassifierPackage =
+                    getDefaultSystemHandlerServicePackage(textClassifierServiceIntent, userId);
+            if (textClassifierPackage != null
+                    && doesPackageSupportRuntimePermissions(textClassifierPackage)) {
+                grantRuntimePermissions(textClassifierPackage, PHONE_PERMISSIONS, true, userId);
+                grantRuntimePermissions(textClassifierPackage, SMS_PERMISSIONS, true, userId);
+                grantRuntimePermissions(textClassifierPackage, CALENDAR_PERMISSIONS, true, userId);
+                grantRuntimePermissions(textClassifierPackage, LOCATION_PERMISSIONS, true, userId);
+                grantRuntimePermissions(textClassifierPackage, CONTACTS_PERMISSIONS, true, userId);
+            }
+        }
+
         if (mPermissionGrantedCallback != null) {
             mPermissionGrantedCallback.onDefaultRuntimePermissionsGranted(userId);
         }
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerInternal.java b/services/core/java/com/android/server/pm/permission/PermissionManagerInternal.java
index 60c118b..859bbe3 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerInternal.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerInternal.java
@@ -146,7 +146,8 @@
 
     public abstract int checkPermission(@NonNull String permName, @NonNull String packageName,
             int callingUid, int userId);
-    public abstract int checkUidPermission(String permName, int uid, int callingUid);
+    public abstract int checkUidPermission(@NonNull String permName,
+            @Nullable PackageParser.Package pkg, int uid, int callingUid);
 
     /**
      * Enforces the request is from the system or an app that has INTERACT_ACROSS_USERS
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index 08f8bbd..afaafbc 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -242,7 +242,8 @@
         return PackageManager.PERMISSION_DENIED;
     }
 
-    private int checkUidPermission(String permName, int uid, int callingUid) {
+    private int checkUidPermission(String permName, PackageParser.Package pkg, int uid,
+            int callingUid) {
         final int callingUserId = UserHandle.getUserId(callingUid);
         final boolean isCallerInstantApp =
                 mPackageManagerInt.getInstantAppPackageName(callingUid) != null;
@@ -253,28 +254,13 @@
             return PackageManager.PERMISSION_DENIED;
         }
 
-        final String[] packages = mContext.getPackageManager().getPackagesForUid(uid);
-        if (packages != null && packages.length > 0) {
-            PackageParser.Package pkg = null;
-            for (String packageName : packages) {
-                pkg = mPackageManagerInt.getPackage(packageName);
-                if (pkg != null) {
-                    break;
-                }
-            }
-            if (pkg == null) {
-Slog.e(TAG, "TODD: No package not found; UID: " + uid);
-Slog.e(TAG, "TODD: Packages: " + Arrays.toString(packages));
-                return PackageManager.PERMISSION_DENIED;
-            }
+        if (pkg != null) {
             if (pkg.mSharedUserId != null) {
                 if (isCallerInstantApp) {
                     return PackageManager.PERMISSION_DENIED;
                 }
-            } else {
-                if (mPackageManagerInt.filterAppAccess(pkg, callingUid, callingUserId)) {
-                    return PackageManager.PERMISSION_DENIED;
-                }
+            } else if (mPackageManagerInt.filterAppAccess(pkg, callingUid, callingUserId)) {
+                return PackageManager.PERMISSION_DENIED;
             }
             final PermissionsState permissionsState =
                     ((PackageSetting) pkg.mExtras).getPermissionsState();
@@ -1210,6 +1196,7 @@
         return false;
     }
 
+    @GuardedBy("mLock")
     private void grantRuntimePermissionsGrantedToDisabledPackageLocked(
             PackageParser.Package pkg, int callingUid, PermissionCallback callback) {
         if (pkg.parentPackage == null) {
@@ -1499,6 +1486,7 @@
         }
     }
 
+    @GuardedBy("mLock")
     private int[] revokeUnusedSharedUserPermissionsLocked(
             SharedUserSetting suSetting, int[] allUserIds) {
         // Collect all used permissions in the UID
@@ -2066,8 +2054,9 @@
                     permName, packageName, callingUid, userId);
         }
         @Override
-        public int checkUidPermission(String permName, int uid, int callingUid) {
-            return PermissionManagerService.this.checkUidPermission(permName, uid, callingUid);
+        public int checkUidPermission(String permName, PackageParser.Package pkg, int uid,
+                int callingUid) {
+            return PermissionManagerService.this.checkUidPermission(permName, pkg, uid, callingUid);
         }
         @Override
         public PermissionGroupInfo getPermissionGroupInfo(String groupName, int flags,
diff --git a/services/core/java/com/android/server/pm/permission/PermissionSettings.java b/services/core/java/com/android/server/pm/permission/PermissionSettings.java
index f6c4990..b3f2833 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionSettings.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionSettings.java
@@ -201,34 +201,42 @@
         }
     }
 
+    @GuardedBy("mLock")
     @Nullable BasePermission getPermissionLocked(@NonNull String permName) {
         return mPermissions.get(permName);
     }
 
+    @GuardedBy("mLock")
     @Nullable BasePermission getPermissionTreeLocked(@NonNull String permName) {
         return mPermissionTrees.get(permName);
     }
 
+    @GuardedBy("mLock")
     void putPermissionLocked(@NonNull String permName, @NonNull BasePermission permission) {
         mPermissions.put(permName, permission);
     }
 
+    @GuardedBy("mLock")
     void putPermissionTreeLocked(@NonNull String permName, @NonNull BasePermission permission) {
         mPermissionTrees.put(permName, permission);
     }
 
+    @GuardedBy("mLock")
     void removePermissionLocked(@NonNull String permName) {
         mPermissions.remove(permName);
     }
 
+    @GuardedBy("mLock")
     void removePermissionTreeLocked(@NonNull String permName) {
         mPermissionTrees.remove(permName);
     }
 
+    @GuardedBy("mLock")
     @NonNull Collection<BasePermission> getAllPermissionsLocked() {
         return mPermissions.values();
     }
 
+    @GuardedBy("mLock")
     @NonNull Collection<BasePermission> getAllPermissionTreesLocked() {
         return mPermissionTrees.values();
     }
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index ff44615..094a7c7 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -1332,30 +1332,38 @@
                 // When interactive, we're already awake.
                 // Wait for a long press or for the button to be released to decide what to do.
                 if (hasLongPressOnPowerBehavior()) {
-                    Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS);
-                    msg.setAsynchronous(true);
-                    mHandler.sendMessageDelayed(msg,
-                            ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
+                    if ((event.getFlags() & KeyEvent.FLAG_LONG_PRESS) != 0) {
+                        powerLongPress();
+                    } else {
+                        Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS);
+                        msg.setAsynchronous(true);
+                        mHandler.sendMessageDelayed(msg,
+                                ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
 
-                    if (hasVeryLongPressOnPowerBehavior()) {
-                        Message longMsg = mHandler.obtainMessage(MSG_POWER_VERY_LONG_PRESS);
-                        longMsg.setAsynchronous(true);
-                        mHandler.sendMessageDelayed(longMsg, mVeryLongPressTimeout);
+                        if (hasVeryLongPressOnPowerBehavior()) {
+                            Message longMsg = mHandler.obtainMessage(MSG_POWER_VERY_LONG_PRESS);
+                            longMsg.setAsynchronous(true);
+                            mHandler.sendMessageDelayed(longMsg, mVeryLongPressTimeout);
+                        }
                     }
                 }
             } else {
                 wakeUpFromPowerKey(event.getDownTime());
 
                 if (mSupportLongPressPowerWhenNonInteractive && hasLongPressOnPowerBehavior()) {
-                    Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS);
-                    msg.setAsynchronous(true);
-                    mHandler.sendMessageDelayed(msg,
-                            ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
+                    if ((event.getFlags() & KeyEvent.FLAG_LONG_PRESS) != 0) {
+                        powerLongPress();
+                    } else {
+                        Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS);
+                        msg.setAsynchronous(true);
+                        mHandler.sendMessageDelayed(msg,
+                                ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
 
-                    if (hasVeryLongPressOnPowerBehavior()) {
-                        Message longMsg = mHandler.obtainMessage(MSG_POWER_VERY_LONG_PRESS);
-                        longMsg.setAsynchronous(true);
-                        mHandler.sendMessageDelayed(longMsg, mVeryLongPressTimeout);
+                        if (hasVeryLongPressOnPowerBehavior()) {
+                            Message longMsg = mHandler.obtainMessage(MSG_POWER_VERY_LONG_PRESS);
+                            longMsg.setAsynchronous(true);
+                            mHandler.sendMessageDelayed(longMsg, mVeryLongPressTimeout);
+                        }
                     }
 
                     mBeganFromNonInteractive = true;
@@ -5242,9 +5250,12 @@
         }
 
         final int cutoutMode = attrs.layoutInDisplayCutoutMode;
+        final boolean attachedInParent = attached != null && !layoutInScreen;
         // Ensure that windows with a DEFAULT or NEVER display cutout mode are laid out in
         // the cutout safe zone.
-        if (cutoutMode != LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS) {
+        // Windows that are attached to a parent and laid out in said parent are already avoiding
+        // the cutout according to that parent and don't need to be further constrained.
+        if (cutoutMode != LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS && !attachedInParent) {
             final Rect displayCutoutSafeExceptMaybeTop = mTmpRect;
             displayCutoutSafeExceptMaybeTop.set(displayFrames.mDisplayCutoutSafe);
             if (layoutInScreen && layoutInsetDecor && !requestedFullscreen
diff --git a/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java b/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java
index 941cd44..efcadad 100644
--- a/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java
+++ b/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java
@@ -19,6 +19,8 @@
 import android.app.ActivityManager;
 import android.content.Context;
 import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.security.IKeystoreService;
 import android.util.Slog;
 
 import com.android.internal.policy.IKeyguardService;
@@ -51,11 +53,16 @@
     private final LockPatternUtils mLockPatternUtils;
     private final StateCallback mCallback;
 
+    IKeystoreService mKeystoreService;
+
     public KeyguardStateMonitor(Context context, IKeyguardService service, StateCallback callback) {
         mLockPatternUtils = new LockPatternUtils(context);
         mCurrentUserId = ActivityManager.getCurrentUser();
         mCallback = callback;
 
+        mKeystoreService = IKeystoreService.Stub.asInterface(ServiceManager
+                .getService("android.security.keystore"));
+
         try {
             service.addStateMonitorCallback(this);
         } catch (RemoteException e) {
@@ -86,6 +93,12 @@
     @Override // Binder interface
     public void onShowingStateChanged(boolean showing) {
         mIsShowing = showing;
+
+        if (showing) try {
+            mKeystoreService.lock(mCurrentUserId); // as long as this doesn't recur...
+        } catch (RemoteException e) {
+            Slog.e(TAG, "Error locking keystore", e);
+        }
     }
 
     @Override // Binder interface
diff --git a/services/core/java/com/android/server/power/BatterySaverPolicy.java b/services/core/java/com/android/server/power/BatterySaverPolicy.java
index 847c90a..08dc97e 100644
--- a/services/core/java/com/android/server/power/BatterySaverPolicy.java
+++ b/services/core/java/com/android/server/power/BatterySaverPolicy.java
@@ -306,6 +306,7 @@
         }
     }
 
+    @GuardedBy("mLock")
     @VisibleForTesting
     void updateConstantsLocked(final String setting, final String deviceSpecificSetting) {
         mSettings = setting;
diff --git a/services/core/java/com/android/server/power/Notifier.java b/services/core/java/com/android/server/power/Notifier.java
index a536270..3072f21 100644
--- a/services/core/java/com/android/server/power/Notifier.java
+++ b/services/core/java/com/android/server/power/Notifier.java
@@ -85,6 +85,7 @@
     private static final int MSG_WIRELESS_CHARGING_STARTED = 3;
     private static final int MSG_SCREEN_BRIGHTNESS_BOOST_CHANGED = 4;
     private static final int MSG_PROFILE_TIMED_OUT = 5;
+    private static final int MSG_WIRED_CHARGING_STARTED = 6;
 
     private final Object mLock = new Object();
 
@@ -571,6 +572,20 @@
         mHandler.sendMessage(msg);
     }
 
+    /**
+     * Called when wired charging has started so as to provide user feedback
+     */
+    public void onWiredChargingStarted() {
+        if (DEBUG) {
+            Slog.d(TAG, "onWiredChargingStarted");
+        }
+
+        mSuspendBlocker.acquire();
+        Message msg = mHandler.obtainMessage(MSG_WIRED_CHARGING_STARTED);
+        msg.setAsynchronous(true);
+        mHandler.sendMessage(msg);
+    }
+
     private void updatePendingBroadcastLocked() {
         if (!mBroadcastInProgress
                 && mPendingInteractiveState != INTERACTIVE_STATE_UNKNOWN
@@ -703,11 +718,14 @@
         }
     };
 
-    private void playWirelessChargingStartedSound() {
+    /**
+     * Plays the wireless charging sound for both wireless and non-wireless charging
+     */
+    private void playChargingStartedSound() {
         final boolean enabled = Settings.Global.getInt(mContext.getContentResolver(),
                 Settings.Global.CHARGING_SOUNDS_ENABLED, 1) != 0;
         final String soundPath = Settings.Global.getString(mContext.getContentResolver(),
-                Settings.Global.WIRELESS_CHARGING_STARTED_SOUND);
+                Settings.Global.CHARGING_STARTED_SOUND);
         if (enabled && soundPath != null) {
             final Uri soundUri = Uri.parse("file://" + soundPath);
             if (soundUri != null) {
@@ -721,11 +739,16 @@
     }
 
     private void showWirelessChargingStarted(int batteryLevel) {
-        playWirelessChargingStartedSound();
+        playChargingStartedSound();
         mStatusBarManagerInternal.showChargingAnimation(batteryLevel);
         mSuspendBlocker.release();
     }
 
+    private void showWiredChargingStarted() {
+        playChargingStartedSound();
+        mSuspendBlocker.release();
+    }
+
     private void lockProfile(@UserIdInt int userId) {
         mTrustManager.setDeviceLockedForUser(userId, true /*locked*/);
     }
@@ -753,6 +776,8 @@
                 case MSG_PROFILE_TIMED_OUT:
                     lockProfile(msg.arg1);
                     break;
+                case MSG_WIRED_CHARGING_STARTED:
+                    showWiredChargingStarted();
             }
         }
     }
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index db83158..38dc820 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -120,9 +120,6 @@
     private static final boolean DEBUG = false;
     private static final boolean DEBUG_SPEW = DEBUG && true;
 
-    // if DEBUG_WIRELESS=true, plays wireless charging animation w/ sound on every plug + unplug
-    private static final boolean DEBUG_WIRELESS = false;
-
     // Message: Sent when a user activity timeout occurs to update the power state.
     private static final int MSG_USER_ACTIVITY_TIMEOUT = 1;
     // Message: Sent when the device enters or exits a dreaming or dozing state.
@@ -1743,10 +1740,15 @@
                 userActivityNoUpdateLocked(
                         now, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID);
 
-                // Tell the notifier whether wireless charging has started so that
-                // it can provide feedback to the user.
-                if (dockedOnWirelessCharger || DEBUG_WIRELESS) {
-                    mNotifier.onWirelessChargingStarted(mBatteryLevel);
+                // only play charging sounds if boot is completed so charging sounds don't play
+                // with potential notification sounds
+                if (mBootCompleted) {
+                    if (mIsPowered && !BatteryManager.isPlugWired(oldPlugType)
+                            && BatteryManager.isPlugWired(mPlugType)) {
+                        mNotifier.onWiredChargingStarted();
+                    } else if (dockedOnWirelessCharger) {
+                        mNotifier.onWirelessChargingStarted(mBatteryLevel);
+                    }
                 }
             }
 
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/power/batterysaver/BatterySavingStats.java b/services/core/java/com/android/server/power/batterysaver/BatterySavingStats.java
index b0b07ea..5d76329 100644
--- a/services/core/java/com/android/server/power/batterysaver/BatterySavingStats.java
+++ b/services/core/java/com/android/server/power/batterysaver/BatterySavingStats.java
@@ -15,6 +15,7 @@
  */
 package com.android.server.power.batterysaver;
 
+import android.metrics.LogMaker;
 import android.os.BatteryManagerInternal;
 import android.os.SystemClock;
 import android.util.ArrayMap;
@@ -23,6 +24,8 @@
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.nano.MetricsProto;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.server.EventLogTags;
 import com.android.server.LocalServices;
 import com.android.server.power.BatterySaverPolicy;
@@ -43,6 +46,9 @@
 
     private static final boolean DEBUG = BatterySaverPolicy.DEBUG;
 
+    @VisibleForTesting
+    static final boolean SEND_TRON_EVENTS = true;
+
     private final Object mLock = new Object();
 
     /** Whether battery saver is on or off. */
@@ -132,15 +138,6 @@
         }
     }
 
-    @VisibleForTesting
-    static final String COUNTER_POWER_PERCENT_PREFIX = "battery_saver_stats_percent_";
-
-    @VisibleForTesting
-    static final String COUNTER_POWER_MILLIAMPS_PREFIX = "battery_saver_stats_milliamps_";
-
-    @VisibleForTesting
-    static final String COUNTER_TIME_SECONDS_PREFIX = "battery_saver_stats_seconds_";
-
     private static BatterySavingStats sInstance;
 
     private BatteryManagerInternal mBatteryManagerInternal;
@@ -285,6 +282,7 @@
         }
     }
 
+    @GuardedBy("mLock")
     private void transitionStateLocked(int newState) {
         if (mCurrentState == newState) {
             return;
@@ -298,6 +296,7 @@
         mMetricsLoggerHelper.transitionState(newState, now, batteryLevel, batteryPercent);
     }
 
+    @GuardedBy("mLock")
     private void endLastStateLocked(long now, int batteryLevel, int batteryPercent) {
         if (mCurrentState < 0) {
             return;
@@ -338,6 +337,7 @@
 
     }
 
+    @GuardedBy("mLock")
     private void startNewStateLocked(int newState, long now, int batteryLevel, int batteryPercent) {
         if (DEBUG) {
             Slog.d(TAG, "New state: " + stateToString(newState));
@@ -363,7 +363,7 @@
             indent = indent + "  ";
 
             pw.print(indent);
-            pw.println("Battery Saver:       Off                                        On");
+            pw.println("Battery Saver:     w/Off                                      w/On");
             dumpLineLocked(pw, indent, InteractiveState.NON_INTERACTIVE, "NonIntr",
                     DozeState.NOT_DOZING, "NonDoze");
             dumpLineLocked(pw, indent, InteractiveState.INTERACTIVE, "   Intr",
@@ -424,10 +424,9 @@
             if (stateChanging) {
                 if (mLastState >= 0) {
                     final long deltaTime = now - mStartTime;
-                    final int deltaBattery = mStartBatteryLevel - batteryLevel;
-                    final int deltaPercent = mStartPercent - batteryPercent;
 
-                    report(mLastState, deltaTime, deltaBattery, deltaPercent);
+                    report(mLastState, deltaTime, mStartBatteryLevel, mStartPercent,
+                            batteryLevel, batteryPercent);
                 }
                 mStartTime = now;
                 mStartBatteryLevel = batteryLevel;
@@ -436,23 +435,28 @@
             mLastState = newState;
         }
 
-        String getCounterSuffix(int state) {
-            final boolean batterySaver =
+        void report(int state, long deltaTimeMs,
+                int startBatteryLevelUa, int startBatteryLevelPercent,
+                int endBatteryLevelUa, int endBatteryLevelPercent) {
+            if (!SEND_TRON_EVENTS) {
+                return;
+            }
+            final boolean batterySaverOn =
                     BatterySaverState.fromIndex(state) != BatterySaverState.OFF;
             final boolean interactive =
                     InteractiveState.fromIndex(state) != InteractiveState.NON_INTERACTIVE;
-            if (batterySaver) {
-                return interactive ? "11" : "10";
-            } else {
-                return interactive ? "01" : "00";
-            }
-        }
 
-        void report(int state, long deltaTimeMs, int deltaBatteryUa, int deltaPercent) {
-            final String suffix = getCounterSuffix(state);
-            mMetricsLogger.count(COUNTER_POWER_MILLIAMPS_PREFIX + suffix, deltaBatteryUa / 1000);
-            mMetricsLogger.count(COUNTER_POWER_PERCENT_PREFIX + suffix, deltaPercent);
-            mMetricsLogger.count(COUNTER_TIME_SECONDS_PREFIX + suffix, (int) (deltaTimeMs / 1000));
+            final LogMaker logMaker = new LogMaker(MetricsProto.MetricsEvent.BATTERY_SAVER)
+                    .setSubtype(batterySaverOn ? 1 : 0)
+                    .addTaggedData(MetricsEvent.FIELD_INTERACTIVE, interactive ? 1 : 0)
+                    .addTaggedData(MetricsEvent.FIELD_DURATION_MILLIS, deltaTimeMs)
+                    .addTaggedData(MetricsEvent.FIELD_START_BATTERY_UA, startBatteryLevelUa)
+                    .addTaggedData(MetricsEvent.FIELD_START_BATTERY_PERCENT,
+                            startBatteryLevelPercent)
+                    .addTaggedData(MetricsEvent.FIELD_END_BATTERY_UA, endBatteryLevelUa)
+                    .addTaggedData(MetricsEvent.FIELD_END_BATTERY_PERCENT, endBatteryLevelPercent);
+
+            mMetricsLogger.write(logMaker);
         }
     }
 }
diff --git a/services/core/java/com/android/server/power/batterysaver/FileUpdater.java b/services/core/java/com/android/server/power/batterysaver/FileUpdater.java
index e0ab9e9..c08b610 100644
--- a/services/core/java/com/android/server/power/batterysaver/FileUpdater.java
+++ b/services/core/java/com/android/server/power/batterysaver/FileUpdater.java
@@ -306,6 +306,7 @@
         }
     }
 
+    @GuardedBy("mLock")
     private void saveDefaultValuesLocked() {
         final AtomicFile file = new AtomicFile(injectDefaultValuesFilename());
 
@@ -334,6 +335,7 @@
         }
     }
 
+    @GuardedBy("mLock")
     @VisibleForTesting
     boolean loadDefaultValuesLocked() {
         final AtomicFile file = new AtomicFile(injectDefaultValuesFilename());
diff --git a/services/core/java/com/android/server/stats/OWNERS b/services/core/java/com/android/server/stats/OWNERS
new file mode 100644
index 0000000..8d7f882
--- /dev/null
+++ b/services/core/java/com/android/server/stats/OWNERS
@@ -0,0 +1,9 @@
+bookatz@google.com
+cjyu@google.com
+dwchen@google.com
+joeo@google.com
+singhtejinder@google.com
+stlafon@google.com
+yaochen@google.com
+yanglu@google.com
+yro@google.com
\ No newline at end of file
diff --git a/services/core/java/com/android/server/stats/StatsCompanionService.java b/services/core/java/com/android/server/stats/StatsCompanionService.java
index c280739..d6359b8 100644
--- a/services/core/java/com/android/server/stats/StatsCompanionService.java
+++ b/services/core/java/com/android/server/stats/StatsCompanionService.java
@@ -16,8 +16,10 @@
 package com.android.server.stats;
 
 import android.annotation.Nullable;
+import android.app.ActivityManagerInternal;
 import android.app.AlarmManager;
 import android.app.PendingIntent;
+import android.app.ProcessMemoryState;
 import android.app.StatsManager;
 import android.bluetooth.BluetoothActivityEnergyInfo;
 import android.bluetooth.BluetoothAdapter;
@@ -85,11 +87,9 @@
     public static final String RESULT_RECEIVER_CONTROLLER_KEY = "controller_activity";
 
     static final String TAG = "StatsCompanionService";
-    static final boolean DEBUG = true;
+    static final boolean DEBUG = false;
 
-    public static final String ACTION_TRIGGER_COLLECTION =
-        "com.android.server.stats.action.TRIGGER_COLLECTION";
-
+    public static final int CODE_DATA_BROADCAST = 1;
     public static final int CODE_SUBSCRIBER_BROADCAST = 1;
 
     private final Context mContext;
@@ -110,9 +110,9 @@
     private TelephonyManager mTelephony = null;
     private final StatFs mStatFsData = new StatFs(Environment.getDataDirectory().getAbsolutePath());
     private final StatFs mStatFsSystem =
-        new StatFs(Environment.getRootDirectory().getAbsolutePath());
+            new StatFs(Environment.getRootDirectory().getAbsolutePath());
     private final StatFs mStatFsTemp =
-        new StatFs(Environment.getDownloadCacheDirectory().getAbsolutePath());
+            new StatFs(Environment.getDownloadCacheDirectory().getAbsolutePath());
 
     public StatsCompanionService(Context context) {
         super();
@@ -122,7 +122,7 @@
         mAnomalyAlarmIntent = PendingIntent.getBroadcast(mContext, 0,
                 new Intent(mContext, AnomalyAlarmReceiver.class), 0);
         mPullingAlarmIntent = PendingIntent.getBroadcast(
-            mContext, 0, new Intent(mContext, PullingAlarmReceiver.class), 0);
+                mContext, 0, new Intent(mContext, PullingAlarmReceiver.class), 0);
         mAppUpdateReceiver = new AppUpdateReceiver();
         mUserUpdateReceiver = new BroadcastReceiver() {
             @Override
@@ -130,7 +130,7 @@
                 synchronized (sStatsdLock) {
                     sStatsd = fetchStatsdService();
                     if (sStatsd == null) {
-                        Slog.w(TAG, "Could not access statsd");
+                        Slog.w(TAG, "Could not access statsd for UserUpdateReceiver");
                         return;
                     }
                     try {
@@ -145,7 +145,7 @@
             }
         };
         mShutdownEventReceiver = new ShutdownEventReceiver();
-        Slog.w(TAG, "Registered receiver for ACTION_PACKAGE_REPLACE AND ADDED.");
+        if (DEBUG) Slog.d(TAG, "Registered receiver for ACTION_PACKAGE_REPLACED and ADDED.");
         PowerProfile powerProfile = new PowerProfile(context);
         final int numClusters = powerProfile.getNumCpuClusters();
         mKernelCpuSpeedReaders = new KernelCpuSpeedReader[numClusters];
@@ -153,24 +153,27 @@
         for (int i = 0; i < numClusters; i++) {
             final int numSpeedSteps = powerProfile.getNumSpeedStepsInCpuCluster(i);
             mKernelCpuSpeedReaders[i] = new KernelCpuSpeedReader(firstCpuOfCluster,
-                            numSpeedSteps);
+                    numSpeedSteps);
             firstCpuOfCluster += powerProfile.getNumCoresInCpuCluster(i);
         }
     }
 
     @Override
-    public void sendBroadcast(String pkg, String cls) {
-        // TODO: Use a pending intent.
+    public void sendDataBroadcast(IBinder intentSenderBinder) {
         enforceCallingPermission();
-        mContext.sendBroadcastAsUser(new Intent(ACTION_TRIGGER_COLLECTION).setClassName(pkg, cls),
-                UserHandle.SYSTEM);
+        IntentSender intentSender = new IntentSender(intentSenderBinder);
+        Intent intent = new Intent();
+        try {
+            intentSender.sendIntent(mContext, CODE_DATA_BROADCAST, intent, null, null);
+        } catch (IntentSender.SendIntentException e) {
+            Slog.w(TAG, "Unable to send using IntentSender");
+        }
     }
 
     @Override
     public void sendSubscriberBroadcast(IBinder intentSenderBinder, long configUid, long configKey,
                                         long subscriptionId, long subscriptionRuleId,
                                         StatsDimensionsValue dimensionsValue) {
-        if (DEBUG) Slog.d(TAG, "Statsd requested to sendSubscriberBroadcast.");
         enforceCallingPermission();
         IntentSender intentSender = new IntentSender(intentSenderBinder);
         Intent intent = new Intent()
@@ -179,16 +182,16 @@
                 .putExtra(StatsManager.EXTRA_STATS_SUBSCRIPTION_ID, subscriptionId)
                 .putExtra(StatsManager.EXTRA_STATS_SUBSCRIPTION_RULE_ID, subscriptionRuleId)
                 .putExtra(StatsManager.EXTRA_STATS_DIMENSIONS_VALUE, dimensionsValue);
+        if (DEBUG) {
+            Slog.d(TAG, String.format("Statsd sendSubscriberBroadcast with params {%d %d %d %d %s}",
+                    configUid, configKey, subscriptionId,
+                    subscriptionRuleId, dimensionsValue));
+        }
         try {
             intentSender.sendIntent(mContext, CODE_SUBSCRIBER_BROADCAST, intent, null, null);
         } catch (IntentSender.SendIntentException e) {
             Slog.w(TAG, "Unable to send using IntentSender from uid " + configUid
                     + "; presumably it had been cancelled.");
-            if (DEBUG) {
-                Slog.d(TAG, String.format("SubscriberBroadcast params {%d %d %d %d %s}",
-                        configUid, configKey, subscriptionId,
-                        subscriptionRuleId, dimensionsValue));
-            }
         }
     }
 
@@ -209,17 +212,18 @@
     }
 
     // Assumes that sStatsdLock is held.
+    @GuardedBy("sStatsdLock")
     private final void informAllUidsLocked(Context context) throws RemoteException {
         UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE);
         PackageManager pm = context.getPackageManager();
         final List<UserInfo> users = um.getUsers(true);
         if (DEBUG) {
-            Slog.w(TAG, "Iterating over " + users.size() + " profiles.");
+            Slog.d(TAG, "Iterating over " + users.size() + " profiles.");
         }
 
-        List<Integer> uids = new ArrayList();
-        List<Long> versions = new ArrayList();
-        List<String> apps = new ArrayList();
+        List<Integer> uids = new ArrayList<>();
+        List<Long> versions = new ArrayList<>();
+        List<String> apps = new ArrayList<>();
 
         // Add in all the apps for every user/profile.
         for (UserInfo profile : users) {
@@ -235,7 +239,7 @@
         sStatsd.informAllUidData(toIntArray(uids), toLongArray(versions), apps.toArray(new
                 String[apps.size()]));
         if (DEBUG) {
-            Slog.w(TAG, "Sent data for " + uids.size() + " apps");
+            Slog.d(TAG, "Sent data for " + uids.size() + " apps");
         }
     }
 
@@ -284,10 +288,11 @@
         }
     }
 
-    private final static class AnomalyAlarmReceiver extends BroadcastReceiver {
+    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");
@@ -304,25 +309,24 @@
         }
     }
 
-    private final static class PullingAlarmReceiver extends BroadcastReceiver {
-      @Override
-      public void onReceive(Context context, Intent intent) {
-        if (DEBUG)
-          Slog.d(TAG, "Time to poll something.");
-        synchronized (sStatsdLock) {
-          if (sStatsd == null) {
-            Slog.w(TAG, "Could not access statsd to inform it of pulling alarm firing.");
-            return;
-          }
-          try {
-            // Two-way call to statsd to retain AlarmManager wakelock
-            sStatsd.informPollAlarmFired();
-          } catch (RemoteException e) {
-            Slog.w(TAG, "Failed to inform statsd of pulling alarm firing.", e);
-          }
+    public final static class PullingAlarmReceiver extends BroadcastReceiver {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            if (DEBUG)
+                Slog.d(TAG, "Time to poll something.");
+            synchronized (sStatsdLock) {
+                if (sStatsd == null) {
+                    Slog.w(TAG, "Could not access statsd to inform it of pulling alarm firing.");
+                    return;
+                }
+                try {
+                    // Two-way call to statsd to retain AlarmManager wakelock
+                    sStatsd.informPollAlarmFired();
+                } catch (RemoteException e) {
+                    Slog.w(TAG, "Failed to inform statsd of pulling alarm firing.", e);
+                }
+            }
         }
-        // AlarmManager releases its own wakelock here.
-      }
     }
 
     private final static class ShutdownEventReceiver extends BroadcastReceiver {
@@ -332,9 +336,9 @@
              * Skip immediately if intent is not relevant to device shutdown.
              */
             if (!intent.getAction().equals(Intent.ACTION_REBOOT)
-                && !(intent.getAction().equals(Intent.ACTION_SHUTDOWN)
-                       && (intent.getFlags() & Intent.FLAG_RECEIVER_FOREGROUND) != 0)) {
-              return;
+                    && !(intent.getAction().equals(Intent.ACTION_SHUTDOWN)
+                    && (intent.getFlags() & Intent.FLAG_RECEIVER_FOREGROUND) != 0)) {
+                return;
             }
 
             Slog.i(TAG, "StatsCompanionService noticed a shutdown.");
@@ -358,10 +362,11 @@
         if (DEBUG) Slog.d(TAG, "Setting anomaly alarm for " + timestampMs);
         final long callingToken = Binder.clearCallingIdentity();
         try {
-            // using RTC, not RTC_WAKEUP, so if device is asleep, will only fire when it awakens.
+            // using ELAPSED_REALTIME, not ELAPSED_REALTIME_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.ELAPSED_REALTIME, timestampMs, mAnomalyAlarmIntent);
         } finally {
             Binder.restoreCallingIdentity(callingToken);
         }
@@ -381,50 +386,52 @@
 
     @Override // Binder call
     public void setPullingAlarms(long timestampMs, long intervalMs) {
-      enforceCallingPermission();
-      if (DEBUG)
-        Slog.d(TAG, "Setting pulling alarm for " + timestampMs + " every " + intervalMs + "ms");
-      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.
-        // TODO: totally inexact means that stats per bucket could be quite off. Is this okay?
-        mAlarmManager.setRepeating(AlarmManager.RTC, timestampMs, intervalMs, mPullingAlarmIntent);
-      } finally {
-        Binder.restoreCallingIdentity(callingToken);
-      }
+        enforceCallingPermission();
+        if (DEBUG)
+            Slog.d(TAG, "Setting pulling alarm for " + timestampMs + " every " + intervalMs + "ms");
+        final long callingToken = Binder.clearCallingIdentity();
+        try {
+            // using ELAPSED_REALTIME, not ELAPSED_REALTIME_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.
+            // TODO: totally inexact means that stats per bucket could be quite off. Is this okay?
+            mAlarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME, timestampMs, intervalMs,
+                    mPullingAlarmIntent);
+        } finally {
+            Binder.restoreCallingIdentity(callingToken);
+        }
     }
 
     @Override // Binder call
     public void cancelPullingAlarms() {
-      enforceCallingPermission();
-      if (DEBUG)
-        Slog.d(TAG, "Cancelling pulling alarm");
-      final long callingToken = Binder.clearCallingIdentity();
-      try {
-        mAlarmManager.cancel(mPullingAlarmIntent);
-      } finally {
-        Binder.restoreCallingIdentity(callingToken);
-      }
+        enforceCallingPermission();
+        if (DEBUG)
+            Slog.d(TAG, "Cancelling pulling alarm");
+        final long callingToken = Binder.clearCallingIdentity();
+        try {
+            mAlarmManager.cancel(mPullingAlarmIntent);
+        } finally {
+            Binder.restoreCallingIdentity(callingToken);
+        }
     }
 
     private void addNetworkStats(
-        int tag, List<StatsLogEventWrapper> ret, NetworkStats stats, boolean withFGBG) {
-      int size = stats.size();
-      NetworkStats.Entry entry = new NetworkStats.Entry(); // For recycling
-      for (int j = 0; j < size; j++) {
-        stats.getValues(j, entry);
-        StatsLogEventWrapper e = new StatsLogEventWrapper(tag, withFGBG ? 6 : 5);
-        e.writeInt(entry.uid);
-        if (withFGBG) {
-          e.writeInt(entry.set);
+            int tag, List<StatsLogEventWrapper> ret, NetworkStats stats, boolean withFGBG) {
+        int size = stats.size();
+        NetworkStats.Entry entry = new NetworkStats.Entry(); // For recycling
+        for (int j = 0; j < size; j++) {
+            stats.getValues(j, entry);
+            StatsLogEventWrapper e = new StatsLogEventWrapper(tag, withFGBG ? 6 : 5);
+            e.writeInt(entry.uid);
+            if (withFGBG) {
+                e.writeInt(entry.set);
+            }
+            e.writeLong(entry.rxBytes);
+            e.writeLong(entry.rxPackets);
+            e.writeLong(entry.txBytes);
+            e.writeLong(entry.txPackets);
+            ret.add(e);
         }
-        e.writeLong(entry.rxBytes);
-        e.writeLong(entry.rxPackets);
-        e.writeLong(entry.txBytes);
-        e.writeLong(entry.txPackets);
-        ret.add(e);
-      }
     }
 
     /**
@@ -491,220 +498,238 @@
     }
 
     private void pullKernelWakelock(int tagId, List<StatsLogEventWrapper> pulledData) {
-      final KernelWakelockStats wakelockStats =
-          mKernelWakelockReader.readKernelWakelockStats(mTmpWakelockStats);
-      for (Map.Entry<String, KernelWakelockStats.Entry> ent : wakelockStats.entrySet()) {
-        String name = ent.getKey();
-        KernelWakelockStats.Entry kws = ent.getValue();
-        StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, 4);
-        e.writeString(name);
-        e.writeInt(kws.mCount);
-        e.writeInt(kws.mVersion);
-        e.writeLong(kws.mTotalTime);
-        pulledData.add(e);
-      }
+        final KernelWakelockStats wakelockStats =
+                mKernelWakelockReader.readKernelWakelockStats(mTmpWakelockStats);
+        for (Map.Entry<String, KernelWakelockStats.Entry> ent : wakelockStats.entrySet()) {
+            String name = ent.getKey();
+            KernelWakelockStats.Entry kws = ent.getValue();
+            StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, 4);
+            e.writeString(name);
+            e.writeInt(kws.mCount);
+            e.writeInt(kws.mVersion);
+            e.writeLong(kws.mTotalTime);
+            pulledData.add(e);
+        }
     }
 
     private void pullWifiBytesTransfer(int tagId, List<StatsLogEventWrapper> pulledData) {
-      long token = Binder.clearCallingIdentity();
-      try {
-        // TODO: Consider caching the following call to get BatteryStatsInternal.
-        BatteryStatsInternal bs = LocalServices.getService(BatteryStatsInternal.class);
-        String[] ifaces = bs.getWifiIfaces();
-        if (ifaces.length == 0) {
-          return;
+        long token = Binder.clearCallingIdentity();
+        try {
+            // TODO: Consider caching the following call to get BatteryStatsInternal.
+            BatteryStatsInternal bs = LocalServices.getService(BatteryStatsInternal.class);
+            String[] ifaces = bs.getWifiIfaces();
+            if (ifaces.length == 0) {
+                return;
+            }
+            NetworkStatsFactory nsf = new NetworkStatsFactory();
+            // Combine all the metrics per Uid into one record.
+            NetworkStats stats =
+                    nsf.readNetworkStatsDetail(NetworkStats.UID_ALL, ifaces, NetworkStats.TAG_NONE, null)
+                            .groupedByUid();
+            addNetworkStats(tagId, pulledData, stats, false);
+        } catch (java.io.IOException e) {
+            Slog.e(TAG, "Pulling netstats for wifi bytes has error", e);
+        } finally {
+            Binder.restoreCallingIdentity(token);
         }
-        NetworkStatsFactory nsf = new NetworkStatsFactory();
-        // Combine all the metrics per Uid into one record.
-        NetworkStats stats =
-            nsf.readNetworkStatsDetail(NetworkStats.UID_ALL, ifaces, NetworkStats.TAG_NONE, null)
-                .groupedByUid();
-        addNetworkStats(tagId, pulledData, stats, false);
-      } catch (java.io.IOException e) {
-        Slog.e(TAG, "Pulling netstats for wifi bytes has error", e);
-      } finally {
-        Binder.restoreCallingIdentity(token);
-      }
     }
 
     private void pullWifiBytesTransferByFgBg(int tagId, List<StatsLogEventWrapper> pulledData) {
-      long token = Binder.clearCallingIdentity();
-      try {
-        BatteryStatsInternal bs = LocalServices.getService(BatteryStatsInternal.class);
-        String[] ifaces = bs.getWifiIfaces();
-        if (ifaces.length == 0) {
-          return;
+        long token = Binder.clearCallingIdentity();
+        try {
+            BatteryStatsInternal bs = LocalServices.getService(BatteryStatsInternal.class);
+            String[] ifaces = bs.getWifiIfaces();
+            if (ifaces.length == 0) {
+                return;
+            }
+            NetworkStatsFactory nsf = new NetworkStatsFactory();
+            NetworkStats stats = rollupNetworkStatsByFGBG(
+                    nsf.readNetworkStatsDetail(NetworkStats.UID_ALL, ifaces, NetworkStats.TAG_NONE, null));
+            addNetworkStats(tagId, pulledData, stats, true);
+        } catch (java.io.IOException e) {
+            Slog.e(TAG, "Pulling netstats for wifi bytes w/ fg/bg has error", e);
+        } finally {
+            Binder.restoreCallingIdentity(token);
         }
-        NetworkStatsFactory nsf = new NetworkStatsFactory();
-        NetworkStats stats = rollupNetworkStatsByFGBG(
-            nsf.readNetworkStatsDetail(NetworkStats.UID_ALL, ifaces, NetworkStats.TAG_NONE, null));
-        addNetworkStats(tagId, pulledData, stats, true);
-      } catch (java.io.IOException e) {
-        Slog.e(TAG, "Pulling netstats for wifi bytes w/ fg/bg has error", e);
-      } finally {
-        Binder.restoreCallingIdentity(token);
-      }
     }
 
     private void pullMobileBytesTransfer(int tagId, List<StatsLogEventWrapper> pulledData) {
-      long token = Binder.clearCallingIdentity();
-      try {
-        BatteryStatsInternal bs = LocalServices.getService(BatteryStatsInternal.class);
-        String[] ifaces = bs.getMobileIfaces();
-        if (ifaces.length == 0) {
-          return;
+        long token = Binder.clearCallingIdentity();
+        try {
+            BatteryStatsInternal bs = LocalServices.getService(BatteryStatsInternal.class);
+            String[] ifaces = bs.getMobileIfaces();
+            if (ifaces.length == 0) {
+                return;
+            }
+            NetworkStatsFactory nsf = new NetworkStatsFactory();
+            // Combine all the metrics per Uid into one record.
+            NetworkStats stats =
+                    nsf.readNetworkStatsDetail(NetworkStats.UID_ALL, ifaces, NetworkStats.TAG_NONE, null)
+                            .groupedByUid();
+            addNetworkStats(tagId, pulledData, stats, false);
+        } catch (java.io.IOException e) {
+            Slog.e(TAG, "Pulling netstats for mobile bytes has error", e);
+        } finally {
+            Binder.restoreCallingIdentity(token);
         }
-        NetworkStatsFactory nsf = new NetworkStatsFactory();
-        // Combine all the metrics per Uid into one record.
-        NetworkStats stats =
-            nsf.readNetworkStatsDetail(NetworkStats.UID_ALL, ifaces, NetworkStats.TAG_NONE, null)
-                .groupedByUid();
-        addNetworkStats(tagId, pulledData, stats, false);
-      } catch (java.io.IOException e) {
-        Slog.e(TAG, "Pulling netstats for mobile bytes has error", e);
-      } finally {
-        Binder.restoreCallingIdentity(token);
-      }
     }
 
     private void pullBluetoothBytesTransfer(int tagId, List<StatsLogEventWrapper> pulledData) {
-      BluetoothActivityEnergyInfo info = pullBluetoothData();
-      for (UidTraffic traffic : info.getUidTraffic()) {
-        StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, 3);
-        e.writeInt(traffic.getUid());
-        e.writeLong(traffic.getRxBytes());
-        e.writeLong(traffic.getTxBytes());
-        pulledData.add(e);
-      }
+        BluetoothActivityEnergyInfo info = pullBluetoothData();
+        for (UidTraffic traffic : info.getUidTraffic()) {
+            StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, 3);
+            e.writeInt(traffic.getUid());
+            e.writeLong(traffic.getRxBytes());
+            e.writeLong(traffic.getTxBytes());
+            pulledData.add(e);
+        }
     }
 
     private void pullMobileBytesTransferByFgBg(int tagId, List<StatsLogEventWrapper> pulledData) {
-      long token = Binder.clearCallingIdentity();
-      try {
-        BatteryStatsInternal bs = LocalServices.getService(BatteryStatsInternal.class);
-        String[] ifaces = bs.getMobileIfaces();
-        if (ifaces.length == 0) {
-          return;
+        long token = Binder.clearCallingIdentity();
+        try {
+            BatteryStatsInternal bs = LocalServices.getService(BatteryStatsInternal.class);
+            String[] ifaces = bs.getMobileIfaces();
+            if (ifaces.length == 0) {
+                return;
+            }
+            NetworkStatsFactory nsf = new NetworkStatsFactory();
+            NetworkStats stats = rollupNetworkStatsByFGBG(
+                    nsf.readNetworkStatsDetail(NetworkStats.UID_ALL, ifaces, NetworkStats.TAG_NONE, null));
+            addNetworkStats(tagId, pulledData, stats, true);
+        } catch (java.io.IOException e) {
+            Slog.e(TAG, "Pulling netstats for mobile bytes w/ fg/bg has error", e);
+        } finally {
+            Binder.restoreCallingIdentity(token);
         }
-        NetworkStatsFactory nsf = new NetworkStatsFactory();
-        NetworkStats stats = rollupNetworkStatsByFGBG(
-            nsf.readNetworkStatsDetail(NetworkStats.UID_ALL, ifaces, NetworkStats.TAG_NONE, null));
-        addNetworkStats(tagId, pulledData, stats, true);
-      } catch (java.io.IOException e) {
-        Slog.e(TAG, "Pulling netstats for mobile bytes w/ fg/bg has error", e);
-      } finally {
-        Binder.restoreCallingIdentity(token);
-      }
     }
 
     private void pullCpuTimePerFreq(int tagId, List<StatsLogEventWrapper> pulledData) {
-      for (int cluster = 0; cluster < mKernelCpuSpeedReaders.length; cluster++) {
-        long[] clusterTimeMs = mKernelCpuSpeedReaders[cluster].readAbsolute();
-        if (clusterTimeMs != null) {
-          for (int speed = clusterTimeMs.length - 1; speed >= 0; --speed) {
-            StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, 3);
-            e.writeInt(cluster);
-            e.writeInt(speed);
-            e.writeLong(clusterTimeMs[speed]);
-            pulledData.add(e);
-          }
+        for (int cluster = 0; cluster < mKernelCpuSpeedReaders.length; cluster++) {
+            long[] clusterTimeMs = mKernelCpuSpeedReaders[cluster].readAbsolute();
+            if (clusterTimeMs != null) {
+                for (int speed = clusterTimeMs.length - 1; speed >= 0; --speed) {
+                    StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, 3);
+                    e.writeInt(cluster);
+                    e.writeInt(speed);
+                    e.writeLong(clusterTimeMs[speed]);
+                    pulledData.add(e);
+                }
+            }
         }
-      }
     }
 
     private void pullWifiActivityEnergyInfo(int tagId, List<StatsLogEventWrapper> pulledData) {
-      long token = Binder.clearCallingIdentity();
-      if (mWifiManager == null) {
-        mWifiManager =
-            IWifiManager.Stub.asInterface(ServiceManager.getService(Context.WIFI_SERVICE));
-      }
-      if (mWifiManager != null) {
-        try {
-          SynchronousResultReceiver wifiReceiver = new SynchronousResultReceiver("wifi");
-          mWifiManager.requestActivityInfo(wifiReceiver);
-          final WifiActivityEnergyInfo wifiInfo = awaitControllerInfo(wifiReceiver);
-          StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, 6);
-          e.writeLong(wifiInfo.getTimeStamp());
-          e.writeInt(wifiInfo.getStackState());
-          e.writeLong(wifiInfo.getControllerTxTimeMillis());
-          e.writeLong(wifiInfo.getControllerRxTimeMillis());
-          e.writeLong(wifiInfo.getControllerIdleTimeMillis());
-          e.writeLong(wifiInfo.getControllerEnergyUsed());
-          pulledData.add(e);
-        } catch (RemoteException e) {
-          Slog.e(TAG, "Pulling wifiManager for wifi controller activity energy info has error", e);
-        } finally {
-          Binder.restoreCallingIdentity(token);
+        long token = Binder.clearCallingIdentity();
+        if (mWifiManager == null) {
+            mWifiManager =
+                    IWifiManager.Stub.asInterface(ServiceManager.getService(Context.WIFI_SERVICE));
         }
-      }
+        if (mWifiManager != null) {
+            try {
+                SynchronousResultReceiver wifiReceiver = new SynchronousResultReceiver("wifi");
+                mWifiManager.requestActivityInfo(wifiReceiver);
+                final WifiActivityEnergyInfo wifiInfo = awaitControllerInfo(wifiReceiver);
+                StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, 6);
+                e.writeLong(wifiInfo.getTimeStamp());
+                e.writeInt(wifiInfo.getStackState());
+                e.writeLong(wifiInfo.getControllerTxTimeMillis());
+                e.writeLong(wifiInfo.getControllerRxTimeMillis());
+                e.writeLong(wifiInfo.getControllerIdleTimeMillis());
+                e.writeLong(wifiInfo.getControllerEnergyUsed());
+                pulledData.add(e);
+            } catch (RemoteException e) {
+                Slog.e(TAG, "Pulling wifiManager for wifi controller activity energy info has error", e);
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
     }
 
     private void pullModemActivityInfo(int tagId, List<StatsLogEventWrapper> pulledData) {
-      long token = Binder.clearCallingIdentity();
-      if (mTelephony == null) {
-        mTelephony = TelephonyManager.from(mContext);
-      }
-      if (mTelephony != null) {
-        SynchronousResultReceiver modemReceiver = new SynchronousResultReceiver("telephony");
-        mTelephony.requestModemActivityInfo(modemReceiver);
-        final ModemActivityInfo modemInfo = awaitControllerInfo(modemReceiver);
-        StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, 6);
-        e.writeLong(modemInfo.getTimestamp());
-        e.writeLong(modemInfo.getSleepTimeMillis());
-        e.writeLong(modemInfo.getIdleTimeMillis());
-        e.writeLong(modemInfo.getTxTimeMillis()[0]);
-        e.writeLong(modemInfo.getTxTimeMillis()[1]);
-        e.writeLong(modemInfo.getTxTimeMillis()[2]);
-        e.writeLong(modemInfo.getTxTimeMillis()[3]);
-        e.writeLong(modemInfo.getTxTimeMillis()[4]);
-        e.writeLong(modemInfo.getRxTimeMillis());
-        e.writeLong(modemInfo.getEnergyUsed());
-        pulledData.add(e);
-      }
+        long token = Binder.clearCallingIdentity();
+        if (mTelephony == null) {
+            mTelephony = TelephonyManager.from(mContext);
+        }
+        if (mTelephony != null) {
+            SynchronousResultReceiver modemReceiver = new SynchronousResultReceiver("telephony");
+            mTelephony.requestModemActivityInfo(modemReceiver);
+            final ModemActivityInfo modemInfo = awaitControllerInfo(modemReceiver);
+            StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, 6);
+            e.writeLong(modemInfo.getTimestamp());
+            e.writeLong(modemInfo.getSleepTimeMillis());
+            e.writeLong(modemInfo.getIdleTimeMillis());
+            e.writeLong(modemInfo.getTxTimeMillis()[0]);
+            e.writeLong(modemInfo.getTxTimeMillis()[1]);
+            e.writeLong(modemInfo.getTxTimeMillis()[2]);
+            e.writeLong(modemInfo.getTxTimeMillis()[3]);
+            e.writeLong(modemInfo.getTxTimeMillis()[4]);
+            e.writeLong(modemInfo.getRxTimeMillis());
+            e.writeLong(modemInfo.getEnergyUsed());
+            pulledData.add(e);
+        }
     }
 
     private void pullBluetoothActivityInfo(int tagId, List<StatsLogEventWrapper> pulledData) {
-      BluetoothActivityEnergyInfo info = pullBluetoothData();
-      StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, 6);
-      e.writeLong(info.getTimeStamp());
-      e.writeInt(info.getBluetoothStackState());
-      e.writeLong(info.getControllerTxTimeMillis());
-      e.writeLong(info.getControllerRxTimeMillis());
-      e.writeLong(info.getControllerIdleTimeMillis());
-      e.writeLong(info.getControllerEnergyUsed());
-      pulledData.add(e);
+        BluetoothActivityEnergyInfo info = pullBluetoothData();
+        StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, 6);
+        e.writeLong(info.getTimeStamp());
+        e.writeInt(info.getBluetoothStackState());
+        e.writeLong(info.getControllerTxTimeMillis());
+        e.writeLong(info.getControllerRxTimeMillis());
+        e.writeLong(info.getControllerIdleTimeMillis());
+        e.writeLong(info.getControllerEnergyUsed());
+        pulledData.add(e);
     }
 
     private synchronized BluetoothActivityEnergyInfo pullBluetoothData() {
         final BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
-      if (adapter != null) {
-        SynchronousResultReceiver bluetoothReceiver = new SynchronousResultReceiver("bluetooth");
-        adapter.requestControllerActivityEnergyInfo(bluetoothReceiver);
-        return awaitControllerInfo(bluetoothReceiver);
-      } else {
-          Slog.e(TAG, "Failed to get bluetooth adapter!");
-        return null;
-      }
+        if (adapter != null) {
+            SynchronousResultReceiver bluetoothReceiver = new SynchronousResultReceiver("bluetooth");
+            adapter.requestControllerActivityEnergyInfo(bluetoothReceiver);
+            return awaitControllerInfo(bluetoothReceiver);
+        } else {
+            Slog.e(TAG, "Failed to get bluetooth adapter!");
+            return null;
+        }
     }
 
     private void pullSystemElapsedRealtime(int tagId, List<StatsLogEventWrapper> pulledData) {
-      StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, 1);
-      e.writeLong(SystemClock.elapsedRealtime());
-      pulledData.add(e);
+        StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, 1);
+        e.writeLong(SystemClock.elapsedRealtime());
+        pulledData.add(e);
     }
 
     private void pullDiskSpace(int tagId, List<StatsLogEventWrapper> pulledData) {
-      StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, 3);
-      e.writeLong(mStatFsData.getAvailableBytes());
-      e.writeLong(mStatFsSystem.getAvailableBytes());
-      e.writeLong(mStatFsTemp.getAvailableBytes());
-      pulledData.add(e);
+        StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, 3);
+        e.writeLong(mStatFsData.getAvailableBytes());
+        e.writeLong(mStatFsSystem.getAvailableBytes());
+        e.writeLong(mStatFsTemp.getAvailableBytes());
+        pulledData.add(e);
     }
 
     private void pullSystemUpTime(int tagId, List<StatsLogEventWrapper> pulledData) {
-      StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, 1);
-      e.writeLong(SystemClock.uptimeMillis());
-      pulledData.add(e);
+        StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, 1);
+        e.writeLong(SystemClock.uptimeMillis());
+        pulledData.add(e);
+    }
+
+    private void pullProcessMemoryState(int tagId, List<StatsLogEventWrapper> pulledData) {
+        List<ProcessMemoryState> processMemoryStates =
+                LocalServices.getService(ActivityManagerInternal.class)
+                        .getMemoryStateForProcesses();
+        for (ProcessMemoryState processMemoryState : processMemoryStates) {
+            StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, 8 /* fields */);
+            e.writeInt(processMemoryState.uid);
+            e.writeString(processMemoryState.processName);
+            e.writeInt(processMemoryState.oomScore);
+            e.writeLong(processMemoryState.pgfault);
+            e.writeLong(processMemoryState.pgmajfault);
+            e.writeLong(processMemoryState.rssInBytes);
+            e.writeLong(processMemoryState.cacheInBytes);
+            e.writeLong(processMemoryState.swapInBytes);
+            pulledData.add(e);
+        }
     }
 
     /**
@@ -715,59 +740,63 @@
         enforceCallingPermission();
         if (DEBUG)
             Slog.d(TAG, "Pulling " + tagId);
-        List<StatsLogEventWrapper> ret = new ArrayList();
+        List<StatsLogEventWrapper> ret = new ArrayList<>();
         switch (tagId) {
             case StatsLog.WIFI_BYTES_TRANSFER: {
-              pullWifiBytesTransfer(tagId, ret);
-              break;
+                pullWifiBytesTransfer(tagId, ret);
+                break;
             }
             case StatsLog.MOBILE_BYTES_TRANSFER: {
-              pullMobileBytesTransfer(tagId, ret);
-              break;
+                pullMobileBytesTransfer(tagId, ret);
+                break;
             }
             case StatsLog.WIFI_BYTES_TRANSFER_BY_FG_BG: {
-              pullWifiBytesTransferByFgBg(tagId, ret);
-              break;
+                pullWifiBytesTransferByFgBg(tagId, ret);
+                break;
             }
             case StatsLog.MOBILE_BYTES_TRANSFER_BY_FG_BG: {
-              pullMobileBytesTransferByFgBg(tagId, ret);
-              break;
+                pullMobileBytesTransferByFgBg(tagId, ret);
+                break;
             }
             case StatsLog.BLUETOOTH_BYTES_TRANSFER: {
-              pullBluetoothBytesTransfer(tagId, ret);
-              break;
+                pullBluetoothBytesTransfer(tagId, ret);
+                break;
             }
             case StatsLog.KERNEL_WAKELOCK: {
-              pullKernelWakelock(tagId, ret);
-              break;
+                pullKernelWakelock(tagId, ret);
+                break;
             }
             case StatsLog.CPU_TIME_PER_FREQ: {
-              pullCpuTimePerFreq(tagId, ret);
-              break;
+                pullCpuTimePerFreq(tagId, ret);
+                break;
             }
             case StatsLog.WIFI_ACTIVITY_ENERGY_INFO: {
-              pullWifiActivityEnergyInfo(tagId, ret);
-              break;
+                pullWifiActivityEnergyInfo(tagId, ret);
+                break;
             }
             case StatsLog.MODEM_ACTIVITY_INFO: {
-              pullModemActivityInfo(tagId, ret);
-              break;
+                pullModemActivityInfo(tagId, ret);
+                break;
             }
             case StatsLog.BLUETOOTH_ACTIVITY_INFO: {
-              pullBluetoothActivityInfo(tagId, ret);
-              break;
+                pullBluetoothActivityInfo(tagId, ret);
+                break;
             }
             case StatsLog.SYSTEM_UPTIME: {
-              pullSystemUpTime(tagId, ret);
-              break;
+                pullSystemUpTime(tagId, ret);
+                break;
             }
             case StatsLog.SYSTEM_ELAPSED_REALTIME: {
-              pullSystemElapsedRealtime(tagId, ret);
-              break;
+                pullSystemElapsedRealtime(tagId, ret);
+                break;
             }
             case StatsLog.DISK_SPACE: {
-              pullDiskSpace(tagId, ret);
-              break;
+                pullDiskSpace(tagId, ret);
+                break;
+            }
+            case StatsLog.PROCESS_MEMORY_STATE: {
+                pullProcessMemoryState(tagId, ret);
+                break;
             }
             default:
                 Slog.w(TAG, "No such tagId data as " + tagId);
@@ -781,21 +810,23 @@
         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);
     }
 
     @Override
     public void triggerUidSnapshot() {
-      enforceCallingPermission();
-      synchronized (sStatsdLock) {
-        try {
-          informAllUidsLocked(mContext);
-        } catch (RemoteException e) {
-          Slog.e(TAG, "Failed to trigger uid snapshot.", e);
+        enforceCallingPermission();
+        synchronized (sStatsdLock) {
+            try {
+                informAllUidsLocked(mContext);
+            } catch (RemoteException e) {
+                Slog.e(TAG, "Failed to trigger uid snapshot.", e);
+            }
         }
-      }
     }
 
     private void enforceCallingPermission() {
@@ -861,7 +892,7 @@
             }
             sStatsd = fetchStatsdService();
             if (sStatsd == null) {
-                Slog.w(TAG, "Could not access statsd");
+                Slog.i(TAG, "Could not yet find statsd to tell it that StatsCompanion is alive.");
                 return;
             }
             if (DEBUG) Slog.d(TAG, "Saying hi to statsd");
@@ -901,6 +932,7 @@
                 } finally {
                     restoreCallingIdentity(token);
                 }
+                Slog.i(TAG, "Told statsd that StatsCompanionService is alive.");
             } catch (RemoteException e) {
                 Slog.e(TAG, "Failed to inform statsd that statscompanion is ready", e);
                 forgetEverything();
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index 7c170ae..343fb91 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -321,7 +321,7 @@
         public void showChargingAnimation(int batteryLevel) {
             if (mBar != null) {
                 try {
-                    mBar.showChargingAnimation(batteryLevel);
+                    mBar.showWirelessChargingAnimation(batteryLevel);
                 } catch (RemoteException ex){
                 }
             }
diff --git a/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java b/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java
index 853c7eb..0ac853b 100644
--- a/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java
+++ b/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java
@@ -22,7 +22,6 @@
 import android.content.Intent;
 import android.content.ServiceConnection;
 import android.os.Binder;
-import android.os.Handler;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.util.Slog;
@@ -43,7 +42,6 @@
 import java.util.LinkedList;
 import java.util.Queue;
 import java.util.concurrent.Callable;
-import java.util.concurrent.TimeUnit;
 
 /**
  * A manager for TextClassifier services.
@@ -54,9 +52,6 @@
 
     private static final String LOG_TAG = "TextClassificationManagerService";
 
-    // How long after the last interaction with the service we would unbind
-    private static final long TIMEOUT_IDLE_BIND_MILLIS = TimeUnit.MINUTES.toMillis(1);
-
     public static final class Lifecycle extends SystemService {
 
         private final TextClassificationManagerService mManagerService;
@@ -79,10 +74,8 @@
     }
 
     private final Context mContext;
-    private final Handler mHandler;
     private final Intent mServiceIntent;
     private final ServiceConnection mConnection;
-    private final Runnable mUnbind;
     private final Object mLock;
     @GuardedBy("mLock")
     private final Queue<PendingRequest> mPendingRequests;
@@ -94,7 +87,6 @@
 
     private TextClassificationManagerService(Context context) {
         mContext = Preconditions.checkNotNull(context);
-        mHandler = new Handler();
         mServiceIntent = new Intent(TextClassifierService.SERVICE_INTERFACE)
                 .setComponent(TextClassifierService.getServiceComponentName(mContext));
         mConnection = new ServiceConnection() {
@@ -131,7 +123,6 @@
             }
         };
         mPendingRequests = new LinkedList<>();
-        mUnbind = this::unbind;
         mLock = new Object();
     }
 
@@ -152,7 +143,6 @@
             if (isBoundLocked()) {
                 mService.onSuggestSelection(
                         text, selectionStartIndex, selectionEndIndex, options, callback);
-                scheduleUnbindLocked();
             } else {
                 final Callable<Void> request = () -> {
                     onSuggestSelection(
@@ -184,7 +174,6 @@
         synchronized (mLock) {
             if (isBoundLocked()) {
                 mService.onClassifyText(text, startIndex, endIndex, options, callback);
-                scheduleUnbindLocked();
             } else {
                 final Callable<Void> request = () -> {
                     onClassifyText(text, startIndex, endIndex, options, callback);
@@ -213,7 +202,6 @@
         synchronized (mLock) {
             if (isBoundLocked()) {
                 mService.onGenerateLinks(text, options, callback);
-                scheduleUnbindLocked();
             } else {
                 final Callable<Void> request = () -> {
                     onGenerateLinks(text, options, callback);
@@ -270,27 +258,6 @@
         mBinding = binding;
     }
 
-    private void unbind() {
-        synchronized (mLock) {
-            if (!isBoundLocked()) {
-                return;
-            }
-
-            Slog.d(LOG_TAG, "Unbinding from " + mServiceIntent.getComponent());
-            mContext.unbindService(mConnection);
-
-            synchronized (mLock) {
-                mService = null;
-            }
-        }
-    }
-
-    @GuardedBy("mLock")
-    private void scheduleUnbindLocked() {
-        mHandler.removeCallbacks(mUnbind);
-        mHandler.postDelayed(mUnbind, TIMEOUT_IDLE_BIND_MILLIS);
-    }
-
     @GuardedBy("mLock")
     private void enqueueRequestLocked(
             Callable<Void> request, Callable<Void> onServiceFailure, IBinder binder) {
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/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index ce3f512..8155656 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -1766,6 +1766,9 @@
             layer += Z_BOOST_BASE;
         }
         leash.setLayer(layer);
+
+        final DisplayContent dc = getDisplayContent();
+        dc.assignStackOrdering(t);
     }
 
     /**
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 2512dbd..d22828d 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -725,8 +725,9 @@
      *                            wallpaper windows in the window list.
      */
     DisplayContent(Display display, WindowManagerService service,
-            WallpaperController wallpaperController) {
+            WallpaperController wallpaperController, DisplayWindowController controller) {
         super(service);
+        setController(controller);
         if (service.mRoot.getDisplayContent(display.getDisplayId()) != null) {
             throw new IllegalArgumentException("Display with ID=" + display.getDisplayId()
                     + " already exists=" + service.mRoot.getDisplayContent(display.getDisplayId())
@@ -1941,6 +1942,8 @@
         } finally {
             mRemovingDisplay = false;
         }
+
+        mService.onDisplayRemoved(mDisplayId);
     }
 
     /** Returns true if a removal action is still being deferred. */
@@ -1950,7 +1953,6 @@
 
         if (!stillDeferringRemoval && mDeferredRemoval) {
             removeImmediately();
-            mService.onDisplayRemoved(mDisplayId);
             return false;
         }
         return true;
@@ -3531,39 +3533,47 @@
 
         @Override
         void assignChildLayers(SurfaceControl.Transaction t) {
+            assignStackOrdering(t);
 
+            for (int i = 0; i < mChildren.size(); i++) {
+                final TaskStack s = mChildren.get(i);
+                s.assignChildLayers(t);
+            }
+        }
+
+        void assignStackOrdering(SurfaceControl.Transaction t) {
             final int HOME_STACK_STATE = 0;
             final int NORMAL_STACK_STATE = 1;
             final int ALWAYS_ON_TOP_STATE = 2;
 
             int layer = 0;
+            int layerForAnimationLayer = 0;
+
             for (int state = 0; state <= ALWAYS_ON_TOP_STATE; state++) {
                 for (int i = 0; i < mChildren.size(); i++) {
                     final TaskStack s = mChildren.get(i);
-                    if (state == HOME_STACK_STATE && s.isActivityTypeHome()) {
-                        s.assignLayer(t, layer++);
-                    } else if (state == NORMAL_STACK_STATE && !s.isActivityTypeHome()
-                            && !s.isAlwaysOnTop()) {
-                        s.assignLayer(t, layer++);
-                        if (s.inSplitScreenWindowingMode() && mSplitScreenDividerAnchor != null) {
-                            t.setLayer(mSplitScreenDividerAnchor, layer++);
-                        }
-                    } else if (state == ALWAYS_ON_TOP_STATE && s.isAlwaysOnTop()) {
-                        s.assignLayer(t, layer++);
+                    if (state == HOME_STACK_STATE && !s.isActivityTypeHome()) {
+                        continue;
+                    } else if (state == NORMAL_STACK_STATE && (s.isActivityTypeHome()
+                            || s.isAlwaysOnTop())) {
+                        continue;
+                    } else if (state == ALWAYS_ON_TOP_STATE && !s.isAlwaysOnTop()) {
+                        continue;
+                    }
+                    s.assignLayer(t, layer++);
+                    if (s.inSplitScreenWindowingMode() && mSplitScreenDividerAnchor != null) {
+                        t.setLayer(mSplitScreenDividerAnchor, layer++);
+                    }
+                    if (s.isSelfOrChildAnimating()) {
+                        // Ensure the animation layer ends up above the
+                        // highest animating stack and no higher.
+                        layerForAnimationLayer = layer++;
                     }
                 }
-                // The appropriate place for App-Transitions to occur is right
-                // above all other animations but still below things in the Picture-and-Picture
-                // windowing mode.
-                if (state == NORMAL_STACK_STATE && mAppAnimationLayer != null) {
-                    t.setLayer(mAppAnimationLayer, layer++);
-                }
             }
-            for (int i = 0; i < mChildren.size(); i++) {
-                final TaskStack s = mChildren.get(i);
-                s.assignChildLayers(t);
+            if (mAppAnimationLayer != null) {
+                t.setLayer(mAppAnimationLayer, layerForAnimationLayer);
             }
-
         }
 
         @Override
@@ -3876,4 +3886,8 @@
         }
         super.prepareSurfaces();
     }
+
+    void assignStackOrdering(SurfaceControl.Transaction t) {
+        mTaskStackContainers.assignStackOrdering(t);
+    }
 }
diff --git a/services/core/java/com/android/server/wm/DisplayWindowController.java b/services/core/java/com/android/server/wm/DisplayWindowController.java
index ad4957e..0e12838 100644
--- a/services/core/java/com/android/server/wm/DisplayWindowController.java
+++ b/services/core/java/com/android/server/wm/DisplayWindowController.java
@@ -16,11 +16,14 @@
 
 package com.android.server.wm;
 
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DISPLAY;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
 
 import android.content.res.Configuration;
+import android.os.Binder;
 import android.util.Slog;
+import android.view.Display;
 
 /**
  * Controller for the display container. This is created by activity manager to link activity
@@ -36,9 +39,16 @@
         mDisplayId = displayId;
 
         synchronized (mWindowMap) {
-            // TODO: Convert to setContainer() from DisplayContent once everything is hooked up.
-            // Currently we are not setup to register for config changes.
-            mContainer = mRoot.getDisplayContentOrCreate(displayId);
+            final Display display = mService.mDisplayManager.getDisplay(displayId);
+            if (display != null) {
+                final long callingIdentity = Binder.clearCallingIdentity();
+                try {
+                    mRoot.createDisplayContent(display, this /* controller */);
+                } finally {
+                    Binder.restoreCallingIdentity(callingIdentity);
+                }
+            }
+
             if (mContainer == null) {
                 throw new IllegalArgumentException("Trying to add displayId=" + displayId);
             }
@@ -47,14 +57,22 @@
 
     @Override
     public void removeContainer() {
-        // TODO: Pipe through from ActivityDisplay to remove the display
-        throw new UnsupportedOperationException("To be implemented");
+        synchronized (mWindowMap) {
+            if(mContainer == null) {
+                if (DEBUG_DISPLAY) Slog.i(TAG_WM, "removeDisplay: could not find displayId="
+                        + mDisplayId);
+                return;
+            }
+            mContainer.removeIfPossible();
+            super.removeContainer();
+        }
     }
 
     @Override
     public void onOverrideConfigurationChanged(Configuration overrideConfiguration) {
-        // TODO: Pipe through from ActivityDisplay to update the configuration for the display
-        throw new UnsupportedOperationException("To be implemented");
+        // TODO: The container receives override configuration changes through other means. enabling
+        // callbacks through the controller causes layout issues. Investigate consolidating
+        // override configuration propagation to just here.
     }
 
     /**
diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java
index fe5b65c..78dd580 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimationController.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java
@@ -24,15 +24,15 @@
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
 
-import android.app.ActivityManager;
 import android.app.ActivityManager.TaskSnapshot;
 import android.app.WindowConfiguration;
-import android.graphics.GraphicBuffer;
 import android.graphics.Point;
 import android.graphics.Rect;
 import android.os.Binder;
+import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.SystemClock;
+import android.util.ArraySet;
 import android.util.Log;
 import android.util.Slog;
 import android.view.IRecentsAnimationController;
@@ -41,6 +41,7 @@
 import android.view.SurfaceControl;
 import android.view.SurfaceControl.Transaction;
 import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
+import com.google.android.collect.Sets;
 import java.io.PrintWriter;
 import java.util.ArrayList;
 
@@ -59,9 +60,11 @@
     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;
+    private Rect mMinimizedHomeBounds = new Rect();
 
     // We start the RecentsAnimationController in a pending-start state since we need to wait for
     // the wallpaper/activity to draw before we can give control to the handler to start animating
@@ -97,17 +100,13 @@
                         final TaskAnimationAdapter adapter = mPendingAnimations.get(i);
                         final Task task = adapter.mTask;
                         if (task.mTaskId == taskId) {
-                            // TODO: Save this screenshot as the task snapshot?
-                            final Rect taskFrame = new Rect();
-                            task.getBounds(taskFrame);
-                            final GraphicBuffer buffer = SurfaceControl.captureLayers(
-                                    task.getSurfaceControl().getHandle(), taskFrame, 1f);
-                            final AppWindowToken topChild = task.getTopChild();
-                            final WindowState mainWindow = topChild.findMainWindow();
-                            return new TaskSnapshot(buffer, topChild.getConfiguration().orientation,
-                                    mainWindow.mStableInsets,
-                                    ActivityManager.isLowRamDeviceStatic() /* reduced */,
-                                    1.0f /* scale */);
+                            final TaskSnapshotController snapshotController =
+                                    mService.mTaskSnapshotController;
+                            final ArraySet<Task> tasks = Sets.newArraySet(task);
+                            snapshotController.snapshotTasks(tasks);
+                            snapshotController.addSkipClosingAppSnapshotTasks(tasks);
+                            return snapshotController.getSnapshot(taskId, 0 /* userId */,
+                                    false /* restoreFromDisk */, false /* reducedResolution */);
                         }
                     }
                     return null;
@@ -158,13 +157,9 @@
     };
 
     /**
-     * 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
-     * @param restoreHomeBehindStackId The stack id to restore the home stack behind once the
-     *                                 animation is complete. Will be passed to the callback.
      */
     RecentsAnimationController(WindowManagerService service,
             IRecentsAnimationRunner remoteAnimationRunner, RecentsAnimationCallbacks callbacks,
@@ -172,16 +167,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);
@@ -194,19 +192,27 @@
             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();
         if (recentsComponentAppToken != null) {
             if (DEBUG) Log.d(TAG, "setHomeApp(" + recentsComponentAppToken.getName() + ")");
             mHomeAppToken = recentsComponentAppToken;
-            final WallpaperController wc = dc.mWallpaperController;
             if (recentsComponentAppToken.windowsCanBeWallpaperTarget()) {
                 dc.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
                 dc.setLayoutNeeded();
             }
         }
 
+        // Save the minimized home height
+        dc.getDockedDividerController().getHomeStackBoundsInDockedMode(mMinimizedHomeBounds);
+
         mService.mWindowPlacerLocked.performSurfacePlacement();
     }
 
@@ -221,8 +227,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 {
@@ -232,7 +240,15 @@
                 appAnimations[i] = mPendingAnimations.get(i).createRemoteAnimationApp();
             }
             mPendingStart = false;
-            mRunner.onAnimationStart(mController, appAnimations);
+
+            final Rect minimizedHomeBounds =
+                    mHomeAppToken != null && mHomeAppToken.inSplitScreenSecondaryWindowingMode()
+                            ? mMinimizedHomeBounds : null;
+            final Rect contentInsets =
+                    mHomeAppToken != null && mHomeAppToken.findMainWindow() != null
+                            ? mHomeAppToken.findMainWindow().mContentInsets : null;
+            mRunner.onAnimationStart_New(mController, appAnimations, contentInsets,
+                    minimizedHomeBounds);
         } catch (RemoteException e) {
             Slog.e(TAG, "Failed to start recents animation", e);
         }
@@ -334,11 +350,15 @@
         }
 
         RemoteAnimationTarget createRemoteAnimationApp() {
-            // TODO: Do we need position and stack bounds?
+            final Point position = new Point();
+            final Rect bounds = new Rect();
+            final WindowContainer container = mTask.getParent();
+            container.getRelativePosition(position);
+            container.getBounds(bounds);
+            final WindowState mainWindow = mTask.getTopVisibleAppMainWindow();
             return new RemoteAnimationTarget(mTask.mTaskId, MODE_CLOSING, mCapturedLeash,
-                    !mTask.fillsParent(),
-                    mTask.getTopVisibleAppMainWindow().mWinAnimator.mLastClipRect,
-                    mTask.getPrefixOrderIndex(), new Point(), new Rect(),
+                    !mTask.fillsParent(), mainWindow.mWinAnimator.mLastClipRect,
+                    mainWindow.mContentInsets, mTask.getPrefixOrderIndex(), position, bounds,
                     mTask.getWindowConfiguration());
         }
 
diff --git a/services/core/java/com/android/server/wm/RemoteAnimationController.java b/services/core/java/com/android/server/wm/RemoteAnimationController.java
index 9251993..35fc99f 100644
--- a/services/core/java/com/android/server/wm/RemoteAnimationController.java
+++ b/services/core/java/com/android/server/wm/RemoteAnimationController.java
@@ -34,6 +34,7 @@
 
 import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
 
+import java.lang.ref.WeakReference;
 import java.util.ArrayList;
 
 /**
@@ -48,13 +49,7 @@
     private final ArrayList<RemoteAnimationAdapterWrapper> mPendingAnimations = new ArrayList<>();
     private final Rect mTmpRect = new Rect();
     private final Handler mHandler;
-
-    private final IRemoteAnimationFinishedCallback mFinishedCallback = new Stub() {
-        @Override
-        public void onAnimationFinished() throws RemoteException {
-            RemoteAnimationController.this.onAnimationFinished();
-        }
-    };
+    private FinishedCallback mFinishedCallback;
 
     private final Runnable mTimeoutRunnable = () -> {
         onAnimationFinished();
@@ -96,13 +91,18 @@
         // Scale the timeout with the animator scale the controlling app is using.
         mHandler.postDelayed(mTimeoutRunnable,
                 (long) (TIMEOUT_MS * mService.getCurrentAnimatorScale()));
-        try {
-            mRemoteAnimationAdapter.getRunner().onAnimationStart(createAnimations(),
-                    mFinishedCallback);
-        } catch (RemoteException e) {
-            Slog.e(TAG, "Failed to start remote animation", e);
-            onAnimationFinished();
-        }
+        mFinishedCallback = new FinishedCallback(this);
+
+        final RemoteAnimationTarget[] animations = createAnimations();
+        mService.mAnimator.addAfterPrepareSurfacesRunnable(() -> {
+            try {
+                mRemoteAnimationAdapter.getRunner().onAnimationStart(animations,
+                        mFinishedCallback);
+            } catch (RemoteException e) {
+                Slog.e(TAG, "Failed to start remote animation", e);
+                onAnimationFinished();
+            }
+        });
     }
 
     private RemoteAnimationTarget[] createAnimations() {
@@ -120,6 +120,7 @@
     private void onAnimationFinished() {
         mHandler.removeCallbacks(mTimeoutRunnable);
         synchronized (mService.mWindowMap) {
+            releaseFinishedCallback();
             mService.openSurfaceTransaction();
             try {
                 for (int i = mPendingAnimations.size() - 1; i >= 0; i--) {
@@ -140,6 +141,41 @@
         }
     }
 
+    private void releaseFinishedCallback() {
+        if (mFinishedCallback != null) {
+            mFinishedCallback.release();
+            mFinishedCallback = null;
+        }
+    }
+
+    private static final class FinishedCallback extends IRemoteAnimationFinishedCallback.Stub {
+
+        RemoteAnimationController mOuter;
+
+        FinishedCallback(RemoteAnimationController outer) {
+            mOuter = outer;
+        }
+
+        @Override
+        public void onAnimationFinished() throws RemoteException {
+            if (mOuter != null) {
+                mOuter.onAnimationFinished();
+
+                // In case the client holds on to the finish callback, make sure we don't leak
+                // RemoteAnimationController which in turn would leak the runner on the client.
+                mOuter = null;
+            }
+        }
+
+        /**
+         * Marks this callback as not be used anymore by releasing the reference to the outer class
+         * to prevent memory leak.
+         */
+        void release() {
+            mOuter = null;
+        }
+    };
+
     private class RemoteAnimationAdapterWrapper implements AnimationAdapter {
 
         private final AppWindowToken mAppWindowToken;
@@ -166,7 +202,7 @@
             }
             return new RemoteAnimationTarget(task.mTaskId, getMode(),
                     mCapturedLeash, !mAppWindowToken.fillsParent(),
-                    mainWindow.mWinAnimator.mLastClipRect,
+                    mainWindow.mWinAnimator.mLastClipRect, mainWindow.mContentInsets,
                     mAppWindowToken.getPrefixOrderIndex(), mPosition, mStackBounds,
                     task.getWindowConfiguration());
         }
@@ -208,6 +244,7 @@
             mPendingAnimations.remove(this);
             if (mPendingAnimations.isEmpty()) {
                 mHandler.removeCallbacks(mTimeoutRunnable);
+                releaseFinishedCallback();
                 invokeAnimationCancelled();
             }
         }
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index c535fe5..3d60ee4 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -193,30 +193,6 @@
         }
     }
 
-    /**
-     * Retrieve the DisplayContent for the specified displayId. Will create a new DisplayContent if
-     * there is a Display for the displayId.
-     *
-     * @param displayId The display the caller is interested in.
-     * @return The DisplayContent associated with displayId or null if there is no Display for it.
-     */
-    DisplayContent getDisplayContentOrCreate(int displayId) {
-        DisplayContent dc = getDisplayContent(displayId);
-
-        if (dc == null) {
-            final Display display = mService.mDisplayManager.getDisplay(displayId);
-            if (display != null) {
-                final long callingIdentity = Binder.clearCallingIdentity();
-                try {
-                    dc = createDisplayContent(display);
-                } finally {
-                    Binder.restoreCallingIdentity(callingIdentity);
-                }
-            }
-        }
-        return dc;
-    }
-
     DisplayContent getDisplayContent(int displayId) {
         for (int i = mChildren.size() - 1; i >= 0; --i) {
             final DisplayContent current = mChildren.get(i);
@@ -227,9 +203,9 @@
         return null;
     }
 
-    private DisplayContent createDisplayContent(final Display display) {
-        final DisplayContent dc = new DisplayContent(display, mService,
-                mWallpaperController);
+    DisplayContent createDisplayContent(final Display display, DisplayWindowController controller) {
+        final DisplayContent dc =
+                new DisplayContent(display, mService, mWallpaperController, controller);
         final int displayId = display.getDisplayId();
 
         if (DEBUG_DISPLAY) Slog.v(TAG_WM, "Adding display=" + display);
@@ -612,6 +588,8 @@
                     "<<< CLOSE TRANSACTION performLayoutAndPlaceSurfaces");
         }
 
+        mService.mAnimator.executeAfterPrepareSurfacesRunnables();
+
         final WindowSurfacePlacer surfacePlacer = mService.mWindowPlacerLocked;
 
         // If we are ready to perform an app transition, check through all of the app tokens to be
@@ -748,19 +726,6 @@
                     (mSustainedPerformanceModeEnabled ? 1 : 0));
         }
 
-        if (mService.mTurnOnScreen) {
-            if (mService.mAllowTheaterModeWakeFromLayout
-                    || Settings.Global.getInt(mService.mContext.getContentResolver(),
-                    Settings.Global.THEATER_MODE_ON, 0) == 0) {
-                if (DEBUG_VISIBILITY || DEBUG_POWER) {
-                    Slog.v(TAG, "Turning screen on after layout!");
-                }
-                mService.mPowerManager.wakeUp(SystemClock.uptimeMillis(),
-                        "android.server.wm:TURN_ON");
-            }
-            mService.mTurnOnScreen = false;
-        }
-
         if (mUpdateRotation) {
             if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation");
             // TODO(multi-display): Update rotation for different displays separately.
diff --git a/services/core/java/com/android/server/wm/SurfaceAnimationRunner.java b/services/core/java/com/android/server/wm/SurfaceAnimationRunner.java
index dc62cc8..98fcb0b 100644
--- a/services/core/java/com/android/server/wm/SurfaceAnimationRunner.java
+++ b/services/core/java/com/android/server/wm/SurfaceAnimationRunner.java
@@ -151,6 +151,7 @@
         }
     }
 
+    @GuardedBy("mLock")
     private void startPendingAnimationsLocked() {
         for (int i = mPendingAnimations.size() - 1; i >= 0; i--) {
             startAnimationLocked(mPendingAnimations.valueAt(i));
@@ -158,6 +159,7 @@
         mPendingAnimations.clear();
     }
 
+    @GuardedBy("mLock")
     private void startAnimationLocked(RunningAnimation a) {
         final ValueAnimator anim = mAnimatorFactory.makeAnimator();
 
@@ -167,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/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java
index a7a2b53..3d7b32c 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotController.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java
@@ -92,6 +92,7 @@
     private final TaskSnapshotPersister mPersister = new TaskSnapshotPersister(
             Environment::getDataSystemCeDirectory);
     private final TaskSnapshotLoader mLoader = new TaskSnapshotLoader(mPersister);
+    private final ArraySet<Task> mSkipClosingAppSnapshotTasks = new ArraySet<>();
     private final ArraySet<Task> mTmpTasks = new ArraySet<>();
     private final Handler mHandler = new Handler();
 
@@ -149,10 +150,20 @@
         // either closing or hidden.
         getClosingTasks(closingApps, mTmpTasks);
         snapshotTasks(mTmpTasks);
-
+        mSkipClosingAppSnapshotTasks.clear();
     }
 
-    private void snapshotTasks(ArraySet<Task> tasks) {
+    /**
+     * Adds the given {@param tasks} to the list of tasks which should not have their snapshots
+     * taken upon the next processing of the set of closing apps. The caller is responsible for
+     * calling {@link #snapshotTasks} to ensure that the task has an up-to-date snapshot.
+     */
+    @VisibleForTesting
+    void addSkipClosingAppSnapshotTasks(ArraySet<Task> tasks) {
+        mSkipClosingAppSnapshotTasks.addAll(tasks);
+    }
+
+    void snapshotTasks(ArraySet<Task> tasks) {
         for (int i = tasks.size() - 1; i >= 0; i--) {
             final Task task = tasks.valueAt(i);
             final int mode = getSnapshotMode(task);
@@ -295,7 +306,7 @@
 
             // If the task of the app is not visible anymore, it means no other app in that task
             // is opening. Thus, the task is closing.
-            if (task != null && !task.isVisible()) {
+            if (task != null && !task.isVisible() && !mSkipClosingAppSnapshotTasks.contains(task)) {
                 outClosingTasks.add(task);
             }
         }
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotPersister.java b/services/core/java/com/android/server/wm/TaskSnapshotPersister.java
index 7b047a8..621bee7 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotPersister.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotPersister.java
@@ -281,11 +281,13 @@
             mSnapshot = snapshot;
         }
 
+        @GuardedBy("mLock")
         @Override
         void onQueuedLocked() {
             mStoreQueueItems.offer(this);
         }
 
+        @GuardedBy("mLock")
         @Override
         void onDequeuedLocked() {
             mStoreQueueItems.remove(this);
diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java
index cec13ab..20349b9 100644
--- a/services/core/java/com/android/server/wm/WindowAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowAnimator.java
@@ -92,6 +92,7 @@
      * executed and the corresponding transaction is closed and applied.
      */
     private final ArrayList<Runnable> mAfterPrepareSurfacesRunnables = new ArrayList<>();
+    private boolean mInExecuteAfterPrepareSurfacesRunnables;
 
     WindowAnimator(final WindowManagerService service) {
         mService = service;
@@ -161,7 +162,7 @@
                 final int numDisplays = mDisplayContentsAnimators.size();
                 for (int i = 0; i < numDisplays; i++) {
                     final int displayId = mDisplayContentsAnimators.keyAt(i);
-                    final DisplayContent dc = mService.mRoot.getDisplayContentOrCreate(displayId);
+                    final DisplayContent dc = mService.mRoot.getDisplayContent(displayId);
                     DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.valueAt(i);
 
                     final ScreenRotationAnimation screenRotationAnimation =
@@ -195,7 +196,7 @@
 
                 for (int i = 0; i < numDisplays; i++) {
                     final int displayId = mDisplayContentsAnimators.keyAt(i);
-                    final DisplayContent dc = mService.mRoot.getDisplayContentOrCreate(displayId);
+                    final DisplayContent dc = mService.mRoot.getDisplayContent(displayId);
 
                     dc.checkAppWindowsReadyToShow();
 
@@ -228,7 +229,7 @@
             final int numDisplays = mDisplayContentsAnimators.size();
             for (int i = 0; i < numDisplays; i++) {
                 final int displayId = mDisplayContentsAnimators.keyAt(i);
-                final DisplayContent dc = mService.mRoot.getDisplayContentOrCreate(displayId);
+                final DisplayContent dc = mService.mRoot.getDisplayContent(displayId);
                 dc.onPendingTransactionApplied();
             }
 
@@ -305,7 +306,7 @@
                     pw.println(":");
             final DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.valueAt(i);
             final DisplayContent dc =
-                    mService.mRoot.getDisplayContentOrCreate(mDisplayContentsAnimators.keyAt(i));
+                    mService.mRoot.getDisplayContent(mDisplayContentsAnimators.keyAt(i));
             dc.dumpWindowAnimators(pw, subPrefix);
             if (displayAnimator.mScreenRotationAnimation != null) {
                 pw.print(subPrefix); pw.println("mScreenRotationAnimation:");
@@ -339,7 +340,7 @@
         if (displayId < 0) {
             return 0;
         }
-        final DisplayContent displayContent = mService.mRoot.getDisplayContentOrCreate(displayId);
+        final DisplayContent displayContent = mService.mRoot.getDisplayContent(displayId);
         return (displayContent != null) ? displayContent.pendingLayoutChanges : 0;
     }
 
@@ -347,7 +348,7 @@
         if (displayId < 0) {
             return;
         }
-        final DisplayContent displayContent = mService.mRoot.getDisplayContentOrCreate(displayId);
+        final DisplayContent displayContent = mService.mRoot.getDisplayContent(displayId);
         if (displayContent != null) {
             displayContent.pendingLayoutChanges |= changes;
         }
@@ -434,11 +435,24 @@
      * the corresponding transaction is closed and applied.
      */
     void addAfterPrepareSurfacesRunnable(Runnable r) {
+        // If runnables are already being handled in executeAfterPrepareSurfacesRunnable, then just
+        // immediately execute the runnable passed in.
+        if (mInExecuteAfterPrepareSurfacesRunnables) {
+            r.run();
+            return;
+        }
+
         mAfterPrepareSurfacesRunnables.add(r);
         scheduleAnimation();
     }
 
-    private void executeAfterPrepareSurfacesRunnables() {
+    void executeAfterPrepareSurfacesRunnables() {
+
+        // Don't even think about to start recursing!
+        if (mInExecuteAfterPrepareSurfacesRunnables) {
+            return;
+        }
+        mInExecuteAfterPrepareSurfacesRunnables = true;
 
         // Traverse in order they were added.
         final int size = mAfterPrepareSurfacesRunnables.size();
@@ -446,5 +460,6 @@
             mAfterPrepareSurfacesRunnables.get(i).run();
         }
         mAfterPrepareSurfacesRunnables.clear();
+        mInExecuteAfterPrepareSurfacesRunnables = false;
     }
 }
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index 6bd7f22..1f7caff 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -1142,7 +1142,7 @@
         scheduleAnimation();
     }
 
-    private void reassignLayer(Transaction t) {
+    void reassignLayer(Transaction t) {
         final WindowContainer parent = getParent();
         if (parent != null) {
             parent.assignChildLayers(t);
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index e2cfc99..b5df57a 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -744,7 +744,6 @@
     final InputManagerService mInputManager;
     final DisplayManagerInternal mDisplayManagerInternal;
     final DisplayManager mDisplayManager;
-    private final Display[] mDisplays;
 
     // Indicates whether this device supports wide color gamut rendering
     private boolean mHasWideColorGamutSupport;
@@ -753,8 +752,6 @@
     private Session mHoldingScreenOn;
     private PowerManager.WakeLock mHoldingScreenWakeLock;
 
-    boolean mTurnOnScreen;
-
     // Whether or not a layout can cause a wake up when theater mode is enabled.
     boolean mAllowTheaterModeWakeFromLayout;
 
@@ -922,7 +919,6 @@
             @Override
             public void run() {
                 WindowManagerPolicyThread.set(Thread.currentThread(), Looper.myLooper());
-
                 mPolicy.init(mContext, WindowManagerService.this, WindowManagerService.this);
             }
         }, 0);
@@ -981,10 +977,6 @@
         }
 
         mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
-        mDisplays = mDisplayManager.getDisplays();
-        for (Display display : mDisplays) {
-            createDisplayContentLocked(display);
-        }
 
         mKeyguardDisableHandler = new KeyguardDisableHandler(mContext, mPolicy);
 
@@ -1073,6 +1065,13 @@
         mDragDropController = new DragDropController(this, mH.getLooper());
 
         LocalServices.addService(WindowManagerInternal.class, new LocalService());
+    }
+
+    /**
+     * Called after all entities (such as the {@link ActivityManagerService}) have been set up and
+     * associated with the {@link WindowManagerService}.
+     */
+    public void onInitReady() {
         initPolicy();
 
         // Add ourself to the Watchdog monitors.
@@ -1088,6 +1087,7 @@
         showEmulatorDisplayOverlayIfNeeded();
     }
 
+
     public InputMonitor getInputMonitor() {
         return mInputMonitor;
     }
@@ -1140,7 +1140,7 @@
                 throw new IllegalStateException("Display has not been initialialized");
             }
 
-            final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
+            final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
             if (displayContent == null) {
                 Slog.w(TAG_WM, "Attempted to add window to a display that does not exist: "
                         + displayId + ".  Aborting.");
@@ -2286,7 +2286,7 @@
         }
 
         synchronized(mWindowMap) {
-            final DisplayContent dc = mRoot.getDisplayContentOrCreate(displayId);
+            final DisplayContent dc = mRoot.getDisplayContent(displayId);
             WindowToken token = dc.getWindowToken(binder);
             if (token != null) {
                 Slog.w(TAG_WM, "addWindowToken: Attempted to add binder token: " + binder
@@ -2689,6 +2689,7 @@
             cancelRecentsAnimation();
             mRecentsAnimationController = new RecentsAnimationController(this,
                     recentsAnimationRunner, callbacks, displayId);
+            mRecentsAnimationController.initialize();
         }
     }
 
@@ -2696,6 +2697,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) {
@@ -3000,7 +3014,9 @@
 
     @Override
     public void dismissKeyguard(IKeyguardDismissCallback callback, CharSequence message) {
-        checkCallingPermission(permission.CONTROL_KEYGUARD, "dismissKeyguard");
+        if (!checkCallingPermission(permission.CONTROL_KEYGUARD, "dismissKeyguard")) {
+            throw new SecurityException("Requires CONTROL_KEYGUARD permission");
+        }
         synchronized(mWindowMap) {
             mPolicy.dismissKeyguardLw(callback, message);
         }
@@ -3701,7 +3717,7 @@
             boolean wallpaperOnly) {
         final DisplayContent displayContent;
         synchronized(mWindowMap) {
-            displayContent = mRoot.getDisplayContentOrCreate(displayId);
+            displayContent = mRoot.getDisplayContent(displayId);
             if (displayContent == null) {
                 if (DEBUG_SCREENSHOT) Slog.i(TAG_WM, "Screenshot returning null. No Display for "
                         + "displayId=" + displayId);
@@ -3920,7 +3936,7 @@
     public boolean registerWallpaperVisibilityListener(IWallpaperVisibilityListener listener,
             int displayId) {
         synchronized (mWindowMap) {
-            final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
+            final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
             if (displayContent == null) {
                 throw new IllegalArgumentException("Trying to register visibility event "
                         + "for invalid display: " + displayId);
@@ -4477,10 +4493,13 @@
     }
 
     public void displayReady() {
-        for (Display display : mDisplays) {
+        final int displayCount = mRoot.mChildren.size();
+        for (int i = 0; i < displayCount; ++i) {
+            final DisplayContent display = mRoot.mChildren.get(i);
             displayReady(display.getDisplayId());
         }
 
+
         synchronized(mWindowMap) {
             final DisplayContent displayContent = getDefaultDisplayContentLocked();
             if (mMaxUiWidth > 0) {
@@ -4511,7 +4530,7 @@
 
     private void displayReady(int displayId) {
         synchronized(mWindowMap) {
-            final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
+            final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
             if (displayContent != null) {
                 mAnimator.addDisplayLocked(displayId);
                 displayContent.initializeDisplayBaseInfo();
@@ -5060,7 +5079,7 @@
     @Override
     public void getInitialDisplaySize(int displayId, Point size) {
         synchronized (mWindowMap) {
-            final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
+            final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
             if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
                 size.x = displayContent.mInitialDisplayWidth;
                 size.y = displayContent.mInitialDisplayHeight;
@@ -5071,7 +5090,7 @@
     @Override
     public void getBaseDisplaySize(int displayId, Point size) {
         synchronized (mWindowMap) {
-            final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
+            final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
             if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
                 size.x = displayContent.mBaseDisplayWidth;
                 size.y = displayContent.mBaseDisplayHeight;
@@ -5098,7 +5117,7 @@
                 final int MIN_WIDTH = 200;
                 final int MIN_HEIGHT = 200;
                 final int MAX_SCALE = 2;
-                final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
+                final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
                 if (displayContent != null) {
                     width = Math.min(Math.max(width, MIN_WIDTH),
                             displayContent.mInitialDisplayWidth * MAX_SCALE);
@@ -5128,7 +5147,7 @@
         final long ident = Binder.clearCallingIdentity();
         try {
             synchronized(mWindowMap) {
-                final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
+                final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
                 if (displayContent != null) {
                     if (mode < 0 || mode > 1) {
                         mode = 0;
@@ -5210,7 +5229,7 @@
         final long ident = Binder.clearCallingIdentity();
         try {
             synchronized(mWindowMap) {
-                final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
+                final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
                 if (displayContent != null) {
                     setForcedDisplaySizeLocked(displayContent, displayContent.mInitialDisplayWidth,
                             displayContent.mInitialDisplayHeight);
@@ -5226,7 +5245,7 @@
     @Override
     public int getInitialDisplayDensity(int displayId) {
         synchronized (mWindowMap) {
-            final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
+            final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
             if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
                 return displayContent.mInitialDisplayDensity;
             }
@@ -5237,7 +5256,7 @@
     @Override
     public int getBaseDisplayDensity(int displayId) {
         synchronized (mWindowMap) {
-            final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
+            final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
             if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
                 return displayContent.mBaseDisplayDensity;
             }
@@ -5263,7 +5282,7 @@
         final long ident = Binder.clearCallingIdentity();
         try {
             synchronized(mWindowMap) {
-                final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
+                final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
                 if (displayContent != null && mCurrentUserId == targetUserId) {
                     setForcedDisplayDensityLocked(displayContent, density);
                 }
@@ -5294,7 +5313,7 @@
         final long ident = Binder.clearCallingIdentity();
         try {
             synchronized(mWindowMap) {
-                final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
+                final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
                 if (displayContent != null && mCurrentUserId == callingUserId) {
                     setForcedDisplayDensityLocked(displayContent,
                             displayContent.mInitialDisplayDensity);
@@ -5386,7 +5405,7 @@
         final long ident = Binder.clearCallingIdentity();
         try {
             synchronized(mWindowMap) {
-                DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
+                DisplayContent displayContent = mRoot.getDisplayContent(displayId);
                 if (displayContent != null) {
                     setOverscanLocked(displayContent, left, top, right, bottom);
                 }
@@ -6649,19 +6668,11 @@
         synchronized (mWindowMap) { }
     }
 
-    // TODO: All the display method below should probably be moved into the RootWindowContainer...
-    private void createDisplayContentLocked(final Display display) {
-        if (display == null) {
-            throw new IllegalArgumentException("getDisplayContent: display must not be null");
-        }
-        mRoot.getDisplayContentOrCreate(display.getDisplayId());
-    }
-
     // There is an inherent assumption that this will never return null.
     // TODO(multi-display): Inspect all the call-points of this method to see if they make sense to
     // support non-default display.
     DisplayContent getDefaultDisplayContentLocked() {
-        return mRoot.getDisplayContentOrCreate(DEFAULT_DISPLAY);
+        return mRoot.getDisplayContent(DEFAULT_DISPLAY);
     }
 
     public void onDisplayAdded(int displayId) {
@@ -6676,10 +6687,6 @@
 
     public void onDisplayRemoved(int displayId) {
         synchronized (mWindowMap) {
-            final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
-            if (displayContent != null) {
-                displayContent.removeIfPossible();
-            }
             mAnimator.removeDisplayLocked(displayId);
             mWindowPlacerLocked.requestTraversal();
         }
@@ -6695,7 +6702,7 @@
 
     public void onDisplayChanged(int displayId) {
         synchronized (mWindowMap) {
-            final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
+            final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
             if (displayContent != null) {
                 displayContent.updateDisplayInfo();
             }
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 240e7fd..21b4361 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -17,6 +17,7 @@
 package com.android.server.wm;
 
 import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
+import static android.os.PowerManager.DRAW_WAKE_LOCK;
 import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.SurfaceControl.Transaction;
@@ -167,6 +168,7 @@
 import android.os.Trace;
 import android.os.UserHandle;
 import android.os.WorkSource;
+import android.provider.Settings;
 import android.text.TextUtils;
 import android.util.DisplayMetrics;
 import android.util.MergedConfiguration;
@@ -265,7 +267,7 @@
     // This is a non-system overlay window that is currently force hidden.
     private boolean mForceHideNonSystemOverlayWindow;
     boolean mAppFreezing;
-    boolean mHidden;    // Used to determine if to show child windows.
+    boolean mHidden = true;    // Used to determine if to show child windows.
     boolean mWallpaperVisible;  // for wallpaper, what was last vis report?
     private boolean mDragResizing;
     private boolean mDragResizingChangeReported = true;
@@ -285,7 +287,6 @@
     int mLayer;
     boolean mHaveFrame;
     boolean mObscured;
-    boolean mTurnOnScreen;
 
     int mLayoutSeq = -1;
 
@@ -635,6 +636,11 @@
     private TapExcludeRegionHolder mTapExcludeRegionHolder;
 
     /**
+     * Used for testing because the real PowerManager is final.
+     */
+    private PowerManagerWrapper mPowerManagerWrapper;
+
+    /**
      * Compares two window sub-layers and returns -1 if the first is lesser than the second in terms
      * of z-order and 1 otherwise.
      */
@@ -663,9 +669,34 @@
 
     private static final float DEFAULT_DIM_AMOUNT_DEAD_WINDOW = 0.5f;
 
+    interface PowerManagerWrapper {
+        void wakeUp(long time, String reason);
+
+        boolean isInteractive();
+
+    }
+
     WindowState(WindowManagerService service, Session s, IWindow c, WindowToken token,
-           WindowState parentWindow, int appOp, int seq, WindowManager.LayoutParams a,
-           int viewVisibility, int ownerId, boolean ownerCanAddInternalSystemWindow) {
+            WindowState parentWindow, int appOp, int seq, WindowManager.LayoutParams a,
+            int viewVisibility, int ownerId, boolean ownerCanAddInternalSystemWindow) {
+        this(service, s, c, token, parentWindow, appOp, seq, a, viewVisibility, ownerId,
+                ownerCanAddInternalSystemWindow, new PowerManagerWrapper() {
+                    @Override
+                    public void wakeUp(long time, String reason) {
+                        service.mPowerManager.wakeUp(time, reason);
+                    }
+
+                    @Override
+                    public boolean isInteractive() {
+                        return service.mPowerManager.isInteractive();
+                    }
+                });
+    }
+
+    WindowState(WindowManagerService service, Session s, IWindow c, WindowToken token,
+            WindowState parentWindow, int appOp, int seq, WindowManager.LayoutParams a,
+            int viewVisibility, int ownerId, boolean ownerCanAddInternalSystemWindow,
+            PowerManagerWrapper powerManagerWrapper) {
         super(service);
         mSession = s;
         mClient = c;
@@ -682,6 +713,7 @@
         DeathRecipient deathRecipient = new DeathRecipient();
         mSeq = seq;
         mEnforceSizeCompat = (mAttrs.privateFlags & PRIVATE_FLAG_COMPATIBLE_WINDOW) != 0;
+        mPowerManagerWrapper = powerManagerWrapper;
         if (localLOGV) Slog.v(
             TAG, "Window " + this + " client=" + c.asBinder()
             + " token=" + token + " (" + mAttrs.token + ")" + " params=" + a);
@@ -2275,9 +2307,34 @@
 
     void prepareWindowToDisplayDuringRelayout(boolean wasVisible) {
         // We need to turn on screen regardless of visibility.
-        if ((mAttrs.flags & FLAG_TURN_SCREEN_ON) != 0) {
-            if (DEBUG_VISIBILITY) Slog.v(TAG, "Relayout window turning screen on: " + this);
-            mTurnOnScreen = true;
+        boolean hasTurnScreenOnFlag = (mAttrs.flags & FLAG_TURN_SCREEN_ON) != 0;
+        boolean allowTheaterMode =
+                mService.mAllowTheaterModeWakeFromLayout || Settings.Global.getInt(
+                        mService.mContext.getContentResolver(), Settings.Global.THEATER_MODE_ON, 0)
+                        == 0;
+        boolean canTurnScreenOn = mAppToken == null || mAppToken.canTurnScreenOn();
+
+        // The screen will turn on if the following conditions are met
+        // 1. The window has the flag FLAG_TURN_SCREEN_ON
+        // 2. The WMS allows theater mode.
+        // 3. No AWT or the AWT allows the screen to be turned on. This should only be true once
+        // per resume to prevent the screen getting getting turned on for each relayout. Set
+        // canTurnScreenOn will be set to false so the window doesn't turn the screen on again
+        // during this resume.
+        // 4. When the screen is not interactive. This is because when the screen is already
+        // interactive, the value may persist until the next animation, which could potentially
+        // be occurring while turning off the screen. This would lead to the screen incorrectly
+        // turning back on.
+        if (hasTurnScreenOnFlag && allowTheaterMode && canTurnScreenOn
+                && !mPowerManagerWrapper.isInteractive()) {
+            if (DEBUG_VISIBILITY || DEBUG_POWER) {
+                Slog.v(TAG, "Relayout window turning screen on: " + this);
+            }
+            mPowerManagerWrapper.wakeUp(SystemClock.uptimeMillis(),
+                    "android.server.wm:TURN_ON");
+        }
+        if (mAppToken != null) {
+            mAppToken.setCanTurnScreenOn(false);
         }
 
         // If we were already visible, skip rest of preparation.
@@ -2571,8 +2628,7 @@
                 // in wake lock statistics.  So in particular, we don't want to include the
                 // window's hash code as in toString().
                 final CharSequence tag = getWindowTag();
-                mDrawLock = mService.mPowerManager.newWakeLock(
-                        PowerManager.DRAW_WAKE_LOCK, "Window:" + tag);
+                mDrawLock = mService.mPowerManager.newWakeLock(DRAW_WAKE_LOCK, "Window:" + tag);
                 mDrawLock.setReferenceCounted(false);
                 mDrawLock.setWorkSource(new WorkSource(mOwnerUid, mAttrs.packageName));
             }
@@ -3327,15 +3383,13 @@
                     pw.print(" mDestroying="); pw.print(mDestroying);
                     pw.print(" mRemoved="); pw.println(mRemoved);
         }
-        if (getOrientationChanging() || mAppFreezing || mTurnOnScreen
-                || mReportOrientationChanged) {
+        if (getOrientationChanging() || mAppFreezing || mReportOrientationChanged) {
             pw.print(prefix); pw.print("mOrientationChanging=");
                     pw.print(mOrientationChanging);
                     pw.print(" configOrientationChanging=");
                     pw.print(getLastReportedConfiguration().orientation
                             != getConfiguration().orientation);
                     pw.print(" mAppFreezing="); pw.print(mAppFreezing);
-                    pw.print(" mTurnOnScreen="); pw.print(mTurnOnScreen);
                     pw.print(" mReportOrientationChanged="); pw.println(mReportOrientationChanged);
         }
         if (mLastFreezeDuration != 0) {
@@ -4505,13 +4559,12 @@
         if (!mAnimatingExit && mAppDied) {
             mIsDimming = true;
             dimmer.dimAbove(getPendingTransaction(), this, DEFAULT_DIM_AMOUNT_DEAD_WINDOW);
-        } else if ((mAttrs.flags & FLAG_DIM_BEHIND) != 0 && isVisibleNow()
-                && !mWinAnimator.mLastHidden) {
+        } else if ((mAttrs.flags & FLAG_DIM_BEHIND) != 0 && isVisibleNow() && !mHidden) {
             // Only show a dim behind when the following is satisfied:
             // 1. The window has the flag FLAG_DIM_BEHIND
             // 2. The WindowToken is not hidden so dims aren't shown when the window is exiting.
             // 3. The WS is considered visible according to the isVisible() method
-            // 4. The WSA is not hidden.
+            // 4. The WS is not hidden.
             mIsDimming = true;
             dimmer.dimBelow(getPendingTransaction(), this, mAttrs.dimAmount);
         }
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 5c9cfbb..9621ee5 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -211,6 +211,8 @@
 
     private final Rect mTmpSize = new Rect();
 
+    private final SurfaceControl.Transaction mReparentTransaction = new SurfaceControl.Transaction();
+
     WindowStateAnimator(final WindowState win) {
         final WindowManagerService service = win.mService;
 
@@ -371,9 +373,9 @@
                 // child layers need to be reparented to the new surface to make this
                 // transparent to the app.
                 if (mWin.mAppToken == null || mWin.mAppToken.isRelaunching() == false) {
-                    SurfaceControl.openTransaction();
-                    mPendingDestroySurface.reparentChildrenInTransaction(mSurfaceController);
-                    SurfaceControl.closeTransaction();
+                    mReparentTransaction.reparentChildren(mPendingDestroySurface.mSurfaceControl,
+                            mSurfaceController.mSurfaceControl.getHandle())
+                            .apply();
                 }
             }
         }
@@ -587,7 +589,7 @@
                         if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) {
                             WindowManagerService.logSurface(mWin, "DESTROY PENDING", true);
                         }
-                        mPendingDestroySurface.destroyInTransaction();
+                        mPendingDestroySurface.destroyNotInTransaction();
                     }
                     mPendingDestroySurface = mSurfaceController;
                 }
@@ -624,7 +626,7 @@
                 if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) {
                     WindowManagerService.logSurface(mWin, "DESTROY PENDING", true);
                 }
-                mPendingDestroySurface.destroyInTransaction();
+                mPendingDestroySurface.destroyNotInTransaction();
                 // Don't hide wallpaper if we're destroying a deferred surface
                 // after a surface mode change.
                 if (!mDestroyPreservedSurfaceUponRedraw) {
@@ -1106,31 +1108,6 @@
                         w.setOrientationChanging(false);
                     }
                 }
-                // We process mTurnOnScreen even for windows which have already
-                // been shown, to handle cases where windows are not necessarily
-                // hidden while the screen is turning off.
-                // TODO(b/63773439): These cases should be eliminated, though we probably still
-                // want to process mTurnOnScreen in this way for clarity.
-                if (mWin.mTurnOnScreen &&
-                        (mWin.mAppToken == null || mWin.mAppToken.canTurnScreenOn())) {
-                    if (DEBUG_VISIBILITY) Slog.v(TAG, "Show surface turning screen on: " + mWin);
-                    mWin.mTurnOnScreen = false;
-
-                    // The window should only turn the screen on once per resume, but
-                    // prepareSurfaceLocked can be called multiple times. Set canTurnScreenOn to
-                    // false so the window doesn't turn the screen on again during this resume.
-                    if (mWin.mAppToken != null) {
-                        mWin.mAppToken.setCanTurnScreenOn(false);
-                    }
-
-                    // We do not add {@code SET_TURN_ON_SCREEN} when the screen is already
-                    // interactive as the value may persist until the next animation, which could
-                    // potentially occurring while turning off the screen. This would lead to the
-                    // screen incorrectly turning back on.
-                    if (!mService.mPowerManager.isInteractive()) {
-                        mService.mTurnOnScreen = true;
-                    }
-                }
             }
             if (hasSurface()) {
                 w.mToken.hasVisible = true;
@@ -1419,7 +1396,7 @@
     void destroySurface() {
         try {
             if (mSurfaceController != null) {
-                mSurfaceController.destroyInTransaction();
+                mSurfaceController.destroyNotInTransaction();
             }
         } catch (RuntimeException e) {
             Slog.w(TAG, "Exception thrown when destroying surface " + this
diff --git a/services/core/java/com/android/server/wm/WindowSurfaceController.java b/services/core/java/com/android/server/wm/WindowSurfaceController.java
index 2f38556..554a600 100644
--- a/services/core/java/com/android/server/wm/WindowSurfaceController.java
+++ b/services/core/java/com/android/server/wm/WindowSurfaceController.java
@@ -168,7 +168,7 @@
         }
     }
 
-    void destroyInTransaction() {
+    void destroyNotInTransaction() {
         if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) {
             Slog.i(TAG, "Destroying surface " + this + " called by " + Debug.getCallers(8));
         }
diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp
index 7540e26..0b03281 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -24,6 +24,7 @@
         "com_android_server_connectivity_Vpn.cpp",
         "com_android_server_connectivity_tethering_OffloadHardwareInterface.cpp",
         "com_android_server_ConsumerIrService.cpp",
+        "com_android_server_devicepolicy_CryptoTestHelper.cpp",
         "com_android_server_HardwarePropertiesManagerService.cpp",
         "com_android_server_hdmi_HdmiCecController.cpp",
         "com_android_server_input_InputApplicationHandle.cpp",
@@ -40,6 +41,7 @@
         "com_android_server_tv_TvUinputBridge.cpp",
         "com_android_server_tv_TvInputHal.cpp",
         "com_android_server_vr_VrManagerService.cpp",
+        "com_android_server_UsbAlsaJackDetector.cpp",
         "com_android_server_UsbDeviceManager.cpp",
         "com_android_server_UsbDescriptorParser.cpp",
         "com_android_server_UsbMidiDevice.cpp",
@@ -96,6 +98,7 @@
         "libgui",
         "libusbhost",
         "libsuspend",
+        "libtinyalsa",
         "libEGL",
         "libGLESv2",
         "libnetutils",
@@ -109,7 +112,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",
@@ -123,6 +125,7 @@
         "android.hardware.tv.input@1.0",
         "android.hardware.vibrator@1.0",
         "android.hardware.vibrator@1.1",
+        "android.hardware.vibrator@1.2",
         "android.hardware.vr@1.0",
         "android.frameworks.schedulerservice@1.0",
         "android.frameworks.sensorservice@1.0",
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/core/jni/com_android_server_AlarmManagerService.cpp b/services/core/jni/com_android_server_AlarmManagerService.cpp
index bcb0b4f..47350c1 100644
--- a/services/core/jni/com_android_server_AlarmManagerService.cpp
+++ b/services/core/jni/com_android_server_AlarmManagerService.cpp
@@ -385,20 +385,21 @@
     delete impl;
 }
 
-static void android_server_AlarmManagerService_set(JNIEnv*, jobject, jlong nativeData, jint type, jlong seconds, jlong nanoseconds)
+static jint android_server_AlarmManagerService_set(JNIEnv*, jobject, jlong nativeData, jint type, jlong seconds, jlong nanoseconds)
 {
     AlarmImpl *impl = reinterpret_cast<AlarmImpl *>(nativeData);
     struct timespec ts;
     ts.tv_sec = seconds;
     ts.tv_nsec = nanoseconds;
 
-    int result = impl->set(type, &ts);
+    const int result = impl->set(type, &ts);
     if (result < 0)
     {
         ALOGE("Unable to set alarm to %lld.%09lld: %s\n",
               static_cast<long long>(seconds),
               static_cast<long long>(nanoseconds), strerror(errno));
     }
+    return result >= 0 ? 0 : errno;
 }
 
 static jint android_server_AlarmManagerService_waitForAlarm(JNIEnv*, jobject, jlong nativeData)
@@ -424,7 +425,7 @@
      /* name, signature, funcPtr */
     {"init", "()J", (void*)android_server_AlarmManagerService_init},
     {"close", "(J)V", (void*)android_server_AlarmManagerService_close},
-    {"set", "(JIJJ)V", (void*)android_server_AlarmManagerService_set},
+    {"set", "(JIJJ)I", (void*)android_server_AlarmManagerService_set},
     {"waitForAlarm", "(J)I", (void*)android_server_AlarmManagerService_waitForAlarm},
     {"setKernelTime", "(JJ)I", (void*)android_server_AlarmManagerService_setKernelTime},
     {"setKernelTimezone", "(JI)I", (void*)android_server_AlarmManagerService_setKernelTimezone},
diff --git a/services/core/jni/com_android_server_ArcVideoService.cpp b/services/core/jni/com_android_server_ArcVideoService.cpp
index 7df8276..f93cd90 100644
--- a/services/core/jni/com_android_server_ArcVideoService.cpp
+++ b/services/core/jni/com_android_server_ArcVideoService.cpp
@@ -32,7 +32,7 @@
 #include <arc/Future.h>
 #include <arc/IArcBridgeService.h>
 #include <arc/MojoProcessSupport.h>
-#include <video.mojom.h>
+#include <components/arc/common/video.mojom.h>
 
 namespace {
 
diff --git a/services/core/jni/com_android_server_UsbAlsaJackDetector.cpp b/services/core/jni/com_android_server_UsbAlsaJackDetector.cpp
new file mode 100644
index 0000000..e9d4482
--- /dev/null
+++ b/services/core/jni/com_android_server_UsbAlsaJackDetector.cpp
@@ -0,0 +1,152 @@
+/*
+ * 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 LOG_TAG "UsbAlsaJackDetectorJNI"
+#include "utils/Log.h"
+
+#include "jni.h"
+#include <nativehelper/JNIHelp.h>
+#include "android_runtime/AndroidRuntime.h"
+#include "android_runtime/Log.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <asm/byteorder.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <tinyalsa/asoundlib.h>
+
+#define DRIVER_NAME "/dev/usb_accessory"
+
+#define USB_IN_JACK_NAME "USB in Jack"
+#define USB_OUT_JACK_NAME "USB out Jack"
+
+namespace android
+{
+
+static jboolean is_jack_connected(jint card, const char* control) {
+  struct mixer* card_mixer = mixer_open(card);
+  if (card_mixer == NULL) {
+    return true;
+  }
+  struct mixer_ctl* ctl = mixer_get_ctl_by_name(card_mixer, control);
+  if (!ctl) {
+    return true;
+  }
+  mixer_ctl_update(ctl);
+  int val = mixer_ctl_get_value(ctl, 0);
+  ALOGI("JACK %s - value %d\n", control, val);
+  mixer_close(card_mixer);
+
+  return val != 0;
+}
+
+static jboolean android_server_UsbAlsaJackDetector_hasJackDetect(JNIEnv* /* env */,
+                                                                 jobject /* thiz */,
+                                                                 jint card)
+{
+    struct mixer* card_mixer = mixer_open(card);
+    if (card_mixer == NULL) {
+        return false;
+    }
+
+    jboolean has_jack = false;
+    if ((mixer_get_ctl_by_name(card_mixer, USB_IN_JACK_NAME) != NULL) ||
+            (mixer_get_ctl_by_name(card_mixer, USB_OUT_JACK_NAME) != NULL)) {
+        has_jack = true;
+    }
+    mixer_close(card_mixer);
+    return has_jack;
+}
+
+
+static jboolean android_server_UsbAlsaJackDetector_inputJackConnected(JNIEnv* /* env */,
+                                                                      jobject /* thiz */,
+                                                                      jint card)
+{
+    return is_jack_connected(card, USB_IN_JACK_NAME);
+}
+
+
+static jboolean android_server_UsbAlsaJackDetector_outputJackConnected(JNIEnv* /* env */,
+                                                                       jobject /* thiz */,
+                                                                       jint card)
+{
+    return is_jack_connected(card, USB_OUT_JACK_NAME);
+}
+
+static void android_server_UsbAlsaJackDetector_jackDetect(JNIEnv* env,
+                                                                                                        jobject thiz,
+                                                                                                        jint card) {
+    jclass jdclass = env->GetObjectClass(thiz);
+    jmethodID method_jackDetectCallback = env->GetMethodID(jdclass, "jackDetectCallback", "()Z");
+    if (method_jackDetectCallback == NULL) {
+        ALOGE("Can't find jackDetectCallback");
+        return;
+    }
+
+    struct mixer* m = mixer_open(card);
+    if (!m) {
+        ALOGE("Jack detect unable to open mixer\n");
+        return;
+    }
+    mixer_subscribe_events(m, 1);
+    do {
+
+        // Wait for a mixer event.  Retry if interrupted, exit on error.
+        int retval;
+        do {
+            retval = mixer_wait_event(m, -1);
+        } while (retval == -EINTR);
+        if (retval < 0) {
+            break;
+        }
+        mixer_consume_event(m);
+    } while (env->CallBooleanMethod(thiz, method_jackDetectCallback));
+
+    mixer_close(m);
+    return;
+}
+
+static const JNINativeMethod method_table[] = {
+    { "nativeHasJackDetect", "(I)Z", (void*)android_server_UsbAlsaJackDetector_hasJackDetect },
+    { "nativeInputJackConnected",     "(I)Z",
+            (void*)android_server_UsbAlsaJackDetector_inputJackConnected },
+    { "nativeOutputJackConnected",    "(I)Z",
+            (void*)android_server_UsbAlsaJackDetector_outputJackConnected },
+    { "nativeJackDetect", "(I)Z", (void*)android_server_UsbAlsaJackDetector_jackDetect },
+};
+
+int register_android_server_UsbAlsaJackDetector(JNIEnv *env)
+{
+    jclass clazz = env->FindClass("com/android/server/usb/UsbAlsaJackDetector");
+    if (clazz == NULL) {
+        ALOGE("Can't find com/android/server/usb/UsbAlsaJackDetector");
+        return -1;
+    }
+
+    if (!jniRegisterNativeMethods(env, "com/android/server/usb/UsbAlsaJackDetector",
+            method_table, NELEM(method_table))) {
+      ALOGE("Can't register UsbAlsaJackDetector native methods");
+      return -1;
+    }
+
+    return 0;
+}
+
+}
diff --git a/services/core/jni/com_android_server_VibratorService.cpp b/services/core/jni/com_android_server_VibratorService.cpp
index d2f374d..016de14 100644
--- a/services/core/jni/com_android_server_VibratorService.cpp
+++ b/services/core/jni/com_android_server_VibratorService.cpp
@@ -18,7 +18,10 @@
 
 #include <android/hardware/vibrator/1.0/IVibrator.h>
 #include <android/hardware/vibrator/1.0/types.h>
-#include <android/hardware/vibrator/1.1/IVibrator.h>
+#include <android/hardware/vibrator/1.0/IVibrator.h>
+#include <android/hardware/vibrator/1.1/types.h>
+#include <android/hardware/vibrator/1.2/IVibrator.h>
+#include <android/hardware/vibrator/1.2/types.h>
 
 #include "jni.h"
 #include <nativehelper/JNIHelp.h>
@@ -32,15 +35,15 @@
 #include <stdio.h>
 
 using android::hardware::Return;
-using android::hardware::vibrator::V1_0::Effect;
 using android::hardware::vibrator::V1_0::EffectStrength;
-using android::hardware::vibrator::V1_0::IVibrator;
 using android::hardware::vibrator::V1_0::Status;
 using android::hardware::vibrator::V1_1::Effect_1_1;
-using IVibrator_1_1 = android::hardware::vibrator::V1_1::IVibrator;
 
-namespace android
-{
+namespace V1_0 = android::hardware::vibrator::V1_0;
+namespace V1_1 = android::hardware::vibrator::V1_1;
+namespace V1_2 = android::hardware::vibrator::V1_2;
+
+namespace android {
 
 static constexpr int NUM_TRIES = 2;
 
@@ -84,19 +87,29 @@
     return ret;
 }
 
+template<class R>
+bool isValidEffect(jlong effect) {
+    if (effect < 0) {
+        return false;
+    }
+    R val = static_cast<R>(effect);
+    auto iter = hardware::hidl_enum_iterator<R>();
+    return val >= *iter.begin() && val < *std::prev(iter.end());
+}
+
 static void vibratorInit(JNIEnv /* env */, jobject /* clazz */)
 {
-    halCall(&IVibrator::ping).isOk();
+    halCall(&V1_0::IVibrator::ping).isOk();
 }
 
 static jboolean vibratorExists(JNIEnv* /* env */, jobject /* clazz */)
 {
-    return halCall(&IVibrator::ping).isOk() ? JNI_TRUE : JNI_FALSE;
+    return halCall(&V1_0::IVibrator::ping).isOk() ? JNI_TRUE : JNI_FALSE;
 }
 
 static void vibratorOn(JNIEnv* /* env */, jobject /* clazz */, jlong timeout_ms)
 {
-    Status retStatus = halCall(&IVibrator::on, timeout_ms).withDefault(Status::UNKNOWN_ERROR);
+    Status retStatus = halCall(&V1_0::IVibrator::on, timeout_ms).withDefault(Status::UNKNOWN_ERROR);
     if (retStatus != Status::OK) {
         ALOGE("vibratorOn command failed (%" PRIu32 ").", static_cast<uint32_t>(retStatus));
     }
@@ -104,18 +117,18 @@
 
 static void vibratorOff(JNIEnv* /* env */, jobject /* clazz */)
 {
-    Status retStatus = halCall(&IVibrator::off).withDefault(Status::UNKNOWN_ERROR);
+    Status retStatus = halCall(&V1_0::IVibrator::off).withDefault(Status::UNKNOWN_ERROR);
     if (retStatus != Status::OK) {
         ALOGE("vibratorOff command failed (%" PRIu32 ").", static_cast<uint32_t>(retStatus));
     }
 }
 
 static jlong vibratorSupportsAmplitudeControl(JNIEnv*, jobject) {
-    return halCall(&IVibrator::supportsAmplitudeControl).withDefault(false);
+    return halCall(&V1_0::IVibrator::supportsAmplitudeControl).withDefault(false);
 }
 
 static void vibratorSetAmplitude(JNIEnv*, jobject, jint amplitude) {
-    Status status = halCall(&IVibrator::setAmplitude, static_cast<uint32_t>(amplitude))
+    Status status = halCall(&V1_0::IVibrator::setAmplitude, static_cast<uint32_t>(amplitude))
         .withDefault(Status::UNKNOWN_ERROR);
     if (status != Status::OK) {
       ALOGE("Failed to set vibrator amplitude (%" PRIu32 ").",
@@ -132,22 +145,25 @@
     };
     EffectStrength effectStrength(static_cast<EffectStrength>(strength));
 
-    if (effect < 0  || effect > static_cast<uint32_t>(Effect_1_1::TICK)) {
+    Return<void> ret;
+    if (isValidEffect<V1_0::Effect>(effect)) {
+        ret = halCall(&V1_0::IVibrator::perform, static_cast<V1_0::Effect>(effect),
+                effectStrength, callback);
+    } else if (isValidEffect<Effect_1_1>(effect)) {
+        ret = halCall(&V1_1::IVibrator::perform_1_1, static_cast<Effect_1_1>(effect),
+                           effectStrength, callback);
+    } else if (isValidEffect<V1_2::Effect>(effect)) {
+        ret = halCall(&V1_2::IVibrator::perform_1_2, static_cast<V1_2::Effect>(effect),
+                           effectStrength, callback);
+    } else {
         ALOGW("Unable to perform haptic effect, invalid effect ID (%" PRId32 ")",
                 static_cast<int32_t>(effect));
-    } else if (effect == static_cast<uint32_t>(Effect_1_1::TICK)) {
-        auto ret = halCall(&IVibrator_1_1::perform_1_1, static_cast<Effect_1_1>(effect),
-                           effectStrength, callback);
-        if (!ret.isOk()) {
-            ALOGW("Failed to perform effect (%" PRId32 "), insufficient HAL version",
-                    static_cast<int32_t>(effect));
-        }
-    } else {
-        auto ret = halCall(&IVibrator::perform, static_cast<Effect>(effect), effectStrength,
-                           callback);
-        if (!ret.isOk()) {
-            ALOGW("Failed to perform effect (%" PRId32 ")", static_cast<int32_t>(effect));
-        }
+        return -1;
+    }
+
+    if (!ret.isOk()) {
+        ALOGW("Failed to perform effect (%" PRId32 ")", static_cast<int32_t>(effect));
+        return -1;
     }
 
     if (status == Status::OK) {
@@ -160,6 +176,7 @@
                 ", error=%" PRIu32 ").", static_cast<int64_t>(effect),
                 static_cast<int32_t>(strength), static_cast<uint32_t>(status));
     }
+
     return -1;
 }
 
diff --git a/services/core/jni/com_android_server_devicepolicy_CryptoTestHelper.cpp b/services/core/jni/com_android_server_devicepolicy_CryptoTestHelper.cpp
new file mode 100644
index 0000000..b53ea92
--- /dev/null
+++ b/services/core/jni/com_android_server_devicepolicy_CryptoTestHelper.cpp
@@ -0,0 +1,42 @@
+/*
+ * 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 "jni.h"
+#include "core_jni_helpers.h"
+
+#include <openssl/crypto.h>
+
+namespace {
+
+static jint runSelfTest(JNIEnv* env, jobject /* clazz */) {
+    return BORINGSSL_self_test();
+}
+
+static const JNINativeMethod methods[] = {
+    /* name, signature, funcPtr */
+    {"runSelfTest", "()I", (void*) runSelfTest}
+};
+
+} // anonymous namespace
+
+namespace android {
+
+int register_android_server_devicepolicy_CryptoTestHelper(JNIEnv *env) {
+    return jniRegisterNativeMethods(
+            env, "com/android/server/devicepolicy/CryptoTestHelper", methods, NELEM(methods));
+}
+
+} // namespace android
\ No newline at end of file
diff --git a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
index 8fd5be2..c2771e4 100644
--- a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
+++ b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
@@ -51,6 +51,7 @@
 static jmethodID method_setGnssHardwareModelName;
 static jmethodID method_xtraDownloadRequest;
 static jmethodID method_reportNiNotification;
+static jmethodID method_requestLocation;
 static jmethodID method_requestRefLocation;
 static jmethodID method_requestSetID;
 static jmethodID method_requestUtcTime;
@@ -346,6 +347,34 @@
     return object.get();
 }
 
+static GnssLocation createGnssLocation(
+        jint gnssLocationFlags,
+        jdouble latitudeDegrees,
+        jdouble longitudeDegrees,
+        jdouble altitudeMeters,
+        jfloat speedMetersPerSec,
+        jfloat bearingDegrees,
+        jfloat horizontalAccuracyMeters,
+        jfloat verticalAccuracyMeters,
+        jfloat speedAccuracyMetersPerSecond,
+        jfloat bearingAccuracyDegrees,
+        jlong timestamp) {
+    GnssLocation location;
+    location.gnssLocationFlags = static_cast<uint16_t>(gnssLocationFlags);
+    location.latitudeDegrees = static_cast<double>(latitudeDegrees);
+    location.longitudeDegrees = static_cast<double>(longitudeDegrees);
+    location.altitudeMeters = static_cast<double>(altitudeMeters);
+    location.speedMetersPerSec = static_cast<float>(speedMetersPerSec);
+    location.bearingDegrees = static_cast<float>(bearingDegrees);
+    location.horizontalAccuracyMeters = static_cast<float>(horizontalAccuracyMeters);
+    location.verticalAccuracyMeters = static_cast<float>(verticalAccuracyMeters);
+    location.speedAccuracyMetersPerSecond = static_cast<float>(speedAccuracyMetersPerSecond);
+    location.bearingAccuracyDegrees = static_cast<float>(bearingAccuracyDegrees);
+    location.timestamp = static_cast<uint64_t>(timestamp);
+
+    return location;
+}
+
 /*
  * GnssCallback class implements the callback methods for IGnss interface.
  */
@@ -474,7 +503,9 @@
 }
 
 Return<void> GnssCallback::gnssRequestLocationCb(const bool independentFromGnss) {
-    // TODO(b/72405645): call into java implementation
+    JNIEnv* env = getJniEnv();
+    env->CallVoidMethod(mCallbacksObj, method_requestLocation, boolToJbool(independentFromGnss));
+    checkAndClearExceptionFromCallback(env, __FUNCTION__);
     return Void();
 }
 
@@ -1042,6 +1073,7 @@
     method_xtraDownloadRequest = env->GetMethodID(clazz, "xtraDownloadRequest", "()V");
     method_reportNiNotification = env->GetMethodID(clazz, "reportNiNotification",
             "(IIIIILjava/lang/String;Ljava/lang/String;II)V");
+    method_requestLocation = env->GetMethodID(clazz, "requestLocation", "(Z)V");
     method_requestRefLocation = env->GetMethodID(clazz, "requestRefLocation", "()V");
     method_requestSetID = env->GetMethodID(clazz, "requestSetID", "(I)V");
     method_requestUtcTime = env->GetMethodID(clazz, "requestUtcTime", "()V");
@@ -1441,6 +1473,42 @@
     }
 }
 
+static void android_location_GnssLocationProvider_inject_best_location(
+        JNIEnv*,
+        jobject,
+        jint gnssLocationFlags,
+        jdouble latitudeDegrees,
+        jdouble longitudeDegrees,
+        jdouble altitudeMeters,
+        jfloat speedMetersPerSec,
+        jfloat bearingDegrees,
+        jfloat horizontalAccuracyMeters,
+        jfloat verticalAccuracyMeters,
+        jfloat speedAccuracyMetersPerSecond,
+        jfloat bearingAccuracyDegrees,
+        jlong timestamp) {
+    if (gnssHal_V1_1 != nullptr) {
+        GnssLocation location = createGnssLocation(
+                gnssLocationFlags,
+                latitudeDegrees,
+                longitudeDegrees,
+                altitudeMeters,
+                speedMetersPerSec,
+                bearingDegrees,
+                horizontalAccuracyMeters,
+                verticalAccuracyMeters,
+                speedAccuracyMetersPerSecond,
+                bearingAccuracyDegrees,
+                timestamp);
+        auto result = gnssHal_V1_1->injectBestLocation(location);
+        if (!result.isOk() || !result) {
+            ALOGE("%s: Gnss injectBestLocation() failed.", __func__);
+        }
+    } else {
+        ALOGE("%s: injectBestLocation() is called but gnssHal_V1_1 is not available.", __func__);
+    }
+}
+
 static void android_location_GnssLocationProvider_inject_location(JNIEnv* /* env */,
         jobject /* obj */, jdouble latitude, jdouble longitude, jfloat accuracy) {
     if (gnssHal != nullptr) {
@@ -1996,6 +2064,9 @@
             android_location_GnssLocationProvider_read_nmea)},
     {"native_inject_time", "(JJI)V", reinterpret_cast<void *>(
             android_location_GnssLocationProvider_inject_time)},
+    {"native_inject_best_location",
+            "(IDDDFFFFFFJ)V",
+            reinterpret_cast<void *>(android_location_GnssLocationProvider_inject_best_location)},
     {"native_inject_location",
             "(DDF)V",
             reinterpret_cast<void *>(android_location_GnssLocationProvider_inject_location)},
diff --git a/services/core/jni/onload.cpp b/services/core/jni/onload.cpp
index 07ddb05..0ebef37 100644
--- a/services/core/jni/onload.cpp
+++ b/services/core/jni/onload.cpp
@@ -34,6 +34,7 @@
 int register_android_server_storage_AppFuse(JNIEnv* env);
 int register_android_server_SerialService(JNIEnv* env);
 int register_android_server_SystemServer(JNIEnv* env);
+int register_android_server_UsbAlsaJackDetector(JNIEnv* env);
 int register_android_server_UsbDeviceManager(JNIEnv* env);
 int register_android_server_UsbMidiDevice(JNIEnv* env);
 int register_android_server_UsbHostManager(JNIEnv* env);
@@ -42,6 +43,7 @@
 int register_android_server_location_GnssLocationProvider(JNIEnv* env);
 int register_android_server_connectivity_Vpn(JNIEnv* env);
 int register_android_server_connectivity_tethering_OffloadHardwareInterface(JNIEnv*);
+int register_android_server_devicepolicy_CryptoTestHelper(JNIEnv*);
 int register_android_server_hdmi_HdmiCecController(JNIEnv* env);
 int register_android_server_tv_TvUinputBridge(JNIEnv* env);
 int register_android_server_tv_TvInputHal(JNIEnv* env);
@@ -81,6 +83,7 @@
     register_android_server_AlarmManagerService(env);
     register_android_server_UsbDeviceManager(env);
     register_android_server_UsbMidiDevice(env);
+    register_android_server_UsbAlsaJackDetector(env);
     register_android_server_UsbHostManager(env);
     register_android_server_vr_VrManagerService(env);
     register_android_server_VibratorService(env);
@@ -88,6 +91,7 @@
     register_android_server_location_GnssLocationProvider(env);
     register_android_server_connectivity_Vpn(env);
     register_android_server_connectivity_tethering_OffloadHardwareInterface(env);
+    register_android_server_devicepolicy_CryptoTestHelper(env);
     register_android_server_ConsumerIrService(env);
     register_android_server_BatteryStatsService(env);
     register_android_server_hdmi_HdmiCecController(env);
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java b/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java
index c4e485c..3557dc9 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java
@@ -122,16 +122,6 @@
     }
 
     @Override
-    public void setPrintingEnabled(ComponentName admin, boolean enabled) {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public boolean isPrintingEnabled() {
-        return true;
-    }
-
-    @Override
     public List<String> setMeteredDataDisabled(ComponentName admin, List<String> packageNames) {
         return packageNames;
     }
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/CryptoTestHelper.java b/services/devicepolicy/java/com/android/server/devicepolicy/CryptoTestHelper.java
new file mode 100644
index 0000000..a20758e
--- /dev/null
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/CryptoTestHelper.java
@@ -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.
+ */
+
+package com.android.server.devicepolicy;
+
+import android.app.admin.SecurityLog;
+
+/**
+ * Helper to call native BoringSSL self test.
+ */
+public class CryptoTestHelper {
+    public static void runAndLogSelfTest() {
+        final int result = runSelfTest();
+        SecurityLog.writeEvent(SecurityLog.TAG_CRYPTO_SELF_TEST_COMPLETED, result);
+    }
+    private static native int runSelfTest();
+}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DeviceAdminServiceController.java b/services/devicepolicy/java/com/android/server/devicepolicy/DeviceAdminServiceController.java
index 60f204d..0c0ce8d 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DeviceAdminServiceController.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DeviceAdminServiceController.java
@@ -193,6 +193,7 @@
         }
     }
 
+    @GuardedBy("mLock")
     private void disconnectServiceOnUserLocked(int userId, @NonNull String actionForLog) {
         final DevicePolicyServiceConnection conn = mConnections.get(userId);
         if (conn != null) {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 4afe1c7..8753344 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -305,8 +305,6 @@
 
     private static final String TAG_PASSWORD_VALIDITY = "password-validity";
 
-    private static final String TAG_PRINTING_ENABLED = "printing-enabled";
-
     private static final String TAG_TRANSFER_OWNERSHIP_BUNDLE = "transfer-ownership-bundle";
 
     private static final int REQUEST_EXPIRE_PASSWORD = 5571;
@@ -615,8 +613,6 @@
 
         long mPasswordTokenHandle = 0;
 
-        boolean mPrintingEnabled = true;
-
         public DevicePolicyData(int userHandle) {
             mUserHandle = userHandle;
         }
@@ -2048,6 +2044,10 @@
         public TransferOwnershipMetadataManager newTransferOwnershipMetadataManager() {
             return new TransferOwnershipMetadataManager();
         }
+
+        public void runCryptoSelfTest() {
+            CryptoTestHelper.runAndLogSelfTest();
+        }
     }
 
     /**
@@ -2300,6 +2300,7 @@
 
             if (hasDeviceOwner && mInjector.securityLogGetLoggingEnabledProperty()) {
                 mSecurityLogMonitor.start();
+                mInjector.runCryptoSelfTest();
                 maybePauseDeviceWideLoggingLocked();
             }
         }
@@ -2948,12 +2949,6 @@
                 out.endTag(null, TAG_CURRENT_INPUT_METHOD_SET);
             }
 
-            if (!policy.mPrintingEnabled) {
-                out.startTag(null, TAG_PRINTING_ENABLED);
-                out.attribute(null, ATTR_VALUE, Boolean.toString(policy.mPrintingEnabled));
-                out.endTag(null, TAG_PRINTING_ENABLED);
-            }
-
             for (final String cert : policy.mOwnerInstalledCaCerts) {
                 out.startTag(null, TAG_OWNER_INSTALLED_CA_CERT);
                 out.attribute(null, ATTR_ALIAS, cert);
@@ -3172,9 +3167,6 @@
                     policy.mCurrentInputMethodSet = true;
                 } else if (TAG_OWNER_INSTALLED_CA_CERT.equals(tag)) {
                     policy.mOwnerInstalledCaCerts.add(parser.getAttributeValue(null, ATTR_ALIAS));
-                } else if (TAG_PRINTING_ENABLED.equals(tag)) {
-                    String enabled = parser.getAttributeValue(null, ATTR_VALUE);
-                    policy.mPrintingEnabled = Boolean.toString(true).equals(enabled);
                 } else {
                     Slog.w(LOG_TAG, "Unknown tag: " + tag);
                     XmlUtils.skipCurrentTag(parser);
@@ -10234,6 +10226,7 @@
             mInjector.registerContentObserver(mDefaultImeChanged, false, this, UserHandle.USER_ALL);
         }
 
+        @GuardedBy("DevicePolicyManagerService.this")
         private void addPendingChangeByOwnerLocked(int userId) {
             mUserIdsWithPendingChangesByOwner.add(userId);
         }
@@ -10417,7 +10410,7 @@
         public CharSequence getPrintingDisabledReasonForUser(@UserIdInt int userId) {
             synchronized (DevicePolicyManagerService.this) {
                 DevicePolicyData policy = getUserData(userId);
-                if (policy.mPrintingEnabled) {
+                if (!mUserManager.hasUserRestriction(UserManager.DISALLOW_PRINTING)) {
                     Log.e(LOG_TAG, "printing is enabled");
                     return null;
                 }
@@ -12789,27 +12782,6 @@
         }
     }
 
-    private boolean hasPrinting() {
-        return mInjector.getPackageManager().hasSystemFeature(PackageManager.FEATURE_PRINTING);
-    }
-
-    @Override
-    public void setPrintingEnabled(ComponentName admin, boolean enabled) {
-        if (!mHasFeature || !hasPrinting()) {
-            return;
-        }
-        Preconditions.checkNotNull(admin, "Admin cannot be null.");
-        enforceProfileOrDeviceOwner(admin);
-        synchronized (this) {
-            final int userHandle = mInjector.userHandleGetCallingUserId();
-            DevicePolicyData policy = getUserData(userHandle);
-            if (policy.mPrintingEnabled != enabled) {
-                policy.mPrintingEnabled = enabled;
-                saveSettingsLocked(userHandle);
-            }
-        }
-    }
-
     private void deleteTransferOwnershipMetadataFileLocked() {
         mTransferOwnershipMetadataManager.deleteMetadataFile();
     }
@@ -12839,25 +12811,6 @@
         }
     }
 
-    /**
-     * Returns whether printing is enabled for current user.
-     * @hide
-     */
-    @Override
-    public boolean isPrintingEnabled() {
-        if (!hasPrinting()) {
-            return false;
-        }
-        if (!mHasFeature) {
-            return true;
-        }
-        synchronized (this) {
-            final int userHandle = mInjector.userHandleGetCallingUserId();
-            DevicePolicyData policy = getUserData(userHandle);
-            return policy.mPrintingEnabled;
-        }
-    }
-
     @Override
     public int addOverrideApn(@NonNull ComponentName who, @NonNull ApnSetting apnSetting) {
         if (!mHasFeature) {
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 626850d..68da5f5 100755
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -67,7 +67,6 @@
 import com.android.server.audio.AudioService;
 import com.android.server.broadcastradio.BroadcastRadioService;
 import com.android.server.camera.CameraServiceProxy;
-import com.android.server.car.CarServiceHelperService;
 import com.android.server.clipboard.ClipboardService;
 import com.android.server.connectivity.IpConnectivityMetrics;
 import com.android.server.coverage.CoverageService;
@@ -203,7 +202,7 @@
     private static final String THERMAL_OBSERVER_CLASS =
             "com.google.android.clockwork.ThermalObserver";
     private static final String WEAR_CONNECTIVITY_SERVICE_CLASS =
-            "com.google.android.clockwork.connectivity.WearConnectivityService";
+            "com.android.clockwork.connectivity.WearConnectivityService";
     private static final String WEAR_SIDEKICK_SERVICE_CLASS =
             "com.google.android.clockwork.sidekick.SidekickService";
     private static final String WEAR_DISPLAY_SERVICE_CLASS =
@@ -226,6 +225,8 @@
             "com.google.android.things.services.IoTSystemService";
     private static final String SLICE_MANAGER_SERVICE_CLASS =
             "com.android.server.slice.SliceManagerService$Lifecycle";
+    private static final String CAR_SERVICE_HELPER_SERVICE_CLASS =
+            "com.android.internal.car.CarServiceHelperService";
 
     private static final String PERSISTENT_DATA_BLOCK_PROP = "ro.frp.pst";
 
@@ -738,7 +739,6 @@
         Object wigigP2pService = null;
         Object wigigService = null;
 
-        boolean disableRtt = SystemProperties.getBoolean("config.disable_rtt", false);
         boolean disableSystemTextClassifier = SystemProperties.getBoolean(
                 "config.disable_systemtextclassifier", false);
         boolean disableCameraService = SystemProperties.getBoolean("config.disable_cameraservice",
@@ -858,6 +858,14 @@
             ServiceManager.addService(Context.INPUT_SERVICE, inputManager);
             traceEnd();
 
+            traceBeginAndSlog("SetWindowManagerService");
+            mActivityManagerService.setWindowManager(wm);
+            traceEnd();
+
+            traceBeginAndSlog("WindowManagerServiceOnInitReady");
+            wm.onInitReady();
+            traceEnd();
+
             // Start receiving calls from HIDL services. Start in in a separate thread
             // because it need to connect to SensorManager. This have to start
             // after START_SENSOR_SERVICE is done.
@@ -875,10 +883,6 @@
                 traceEnd();
             }
 
-            traceBeginAndSlog("SetWindowManagerService");
-            mActivityManagerService.setWindowManager(wm);
-            traceEnd();
-
             traceBeginAndSlog("StartInputManager");
             inputManager.setWindowManagerCallbacks(wm.getInputMonitor());
             inputManager.start();
@@ -1120,18 +1124,12 @@
                 traceEnd();
             }
 
-            if (!disableRtt) {
-                traceBeginAndSlog("StartWifiRtt");
-                mSystemServiceManager.startService("com.android.server.wifi.RttService");
+            if (context.getPackageManager().hasSystemFeature(
+                PackageManager.FEATURE_WIFI_RTT)) {
+                traceBeginAndSlog("StartRttService");
+                mSystemServiceManager.startService(
+                    "com.android.server.wifi.rtt.RttService");
                 traceEnd();
-
-                if (context.getPackageManager().hasSystemFeature(
-                    PackageManager.FEATURE_WIFI_RTT)) {
-                    traceBeginAndSlog("StartRttService");
-                    mSystemServiceManager.startService(
-                        "com.android.server.wifi.rtt.RttService");
-                    traceEnd();
-                }
             }
 
             if (context.getPackageManager().hasSystemFeature(
@@ -1813,7 +1811,7 @@
 
             if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
                 traceBeginAndSlog("StartCarServiceHelperService");
-                mSystemServiceManager.startService(CarServiceHelperService.class);
+                mSystemServiceManager.startService(CAR_SERVICE_HELPER_SERVICE_CLASS);
                 traceEnd();
             }
 
diff --git a/services/net/java/android/net/apf/ApfFilter.java b/services/net/java/android/net/apf/ApfFilter.java
index 7d9736e..d190432 100644
--- a/services/net/java/android/net/apf/ApfFilter.java
+++ b/services/net/java/android/net/apf/ApfFilter.java
@@ -1068,6 +1068,7 @@
         mLastInstallEvent.flags = ApfProgramEvent.flagsFor(mIPv4Address != null, mMulticastFilter);
     }
 
+    @GuardedBy("this")
     private void logApfProgramEventLocked(long now) {
         if (mLastInstallEvent == null) {
             return;
diff --git a/services/net/java/android/net/ip/RouterAdvertisementDaemon.java b/services/net/java/android/net/ip/RouterAdvertisementDaemon.java
index 49a1e79..8fbc01e 100644
--- a/services/net/java/android/net/ip/RouterAdvertisementDaemon.java
+++ b/services/net/java/android/net/ip/RouterAdvertisementDaemon.java
@@ -268,6 +268,7 @@
         mUnicastResponder = null;
     }
 
+    @GuardedBy("mLock")
     private void assembleRaLocked() {
         final ByteBuffer ra = ByteBuffer.wrap(mRA);
         ra.order(ByteOrder.BIG_ENDIAN);
diff --git a/services/print/java/com/android/server/print/PrintManagerService.java b/services/print/java/com/android/server/print/PrintManagerService.java
index e1c1eb2..e8620ed 100644
--- a/services/print/java/com/android/server/print/PrintManagerService.java
+++ b/services/print/java/com/android/server/print/PrintManagerService.java
@@ -21,7 +21,6 @@
 
 import android.annotation.NonNull;
 import android.app.ActivityManager;
-import android.app.admin.DevicePolicyManager;
 import android.app.admin.DevicePolicyManagerInternal;
 import android.content.ComponentName;
 import android.content.Context;
@@ -115,12 +114,9 @@
 
         private final SparseArray<UserState> mUserStates = new SparseArray<>();
 
-        private final DevicePolicyManager mDpm;
-
         PrintManagerImpl(Context context) {
             mContext = context;
             mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
-            mDpm = (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);
             registerContentObservers();
             registerBroadcastReceivers();
         }
@@ -722,7 +718,7 @@
         }
 
         private boolean isPrintingEnabled() {
-            return mDpm == null || mDpm.isPrintingEnabled();
+            return !mUserManager.hasUserRestriction(UserManager.DISALLOW_PRINTING);
         }
 
         private void dump(@NonNull DualDumpOutputStream dumpStream,
diff --git a/services/print/java/com/android/server/print/RemotePrintSpooler.java b/services/print/java/com/android/server/print/RemotePrintSpooler.java
index ba5dde0..c1c32c2 100644
--- a/services/print/java/com/android/server/print/RemotePrintSpooler.java
+++ b/services/print/java/com/android/server/print/RemotePrintSpooler.java
@@ -596,6 +596,7 @@
         }
     }
 
+    @GuardedBy("mLock")
     private void bindLocked() throws TimeoutException, InterruptedException {
         while (mIsBinding) {
             mLock.wait();
diff --git a/services/robotests/src/com/android/server/backup/BackupManagerServiceTest.java b/services/robotests/src/com/android/server/backup/BackupManagerServiceTest.java
index df09780..53d734b 100644
--- a/services/robotests/src/com/android/server/backup/BackupManagerServiceTest.java
+++ b/services/robotests/src/com/android/server/backup/BackupManagerServiceTest.java
@@ -16,6 +16,7 @@
 
 package com.android.server.backup;
 
+import static com.android.server.backup.testing.BackupManagerServiceTestUtils.startBackupThread;
 import static com.android.server.backup.testing.TransportData.backupTransport;
 import static com.android.server.backup.testing.TransportData.d2dTransport;
 import static com.android.server.backup.testing.TransportData.localTransport;
@@ -41,9 +42,9 @@
 import android.os.HandlerThread;
 import android.platform.test.annotations.Presubmit;
 import android.provider.Settings;
-import com.android.server.backup.PackageManagerBackupAgent;
-import com.android.server.backup.testing.ShadowAppBackupUtils;
-import com.android.server.backup.testing.ShadowBackupPolicyEnforcer;
+
+import com.android.server.testing.shadows.ShadowAppBackupUtils;
+import com.android.server.testing.shadows.ShadowBackupPolicyEnforcer;
 import com.android.server.backup.testing.TransportData;
 import com.android.server.backup.testing.TransportTestUtils.TransportMock;
 import com.android.server.backup.transport.TransportNotRegisteredException;
@@ -97,10 +98,7 @@
         mTransport = backupTransport();
         mTransportName = mTransport.transportName;
 
-        mBackupThread = new HandlerThread("backup-test");
-        mBackupThread.setUncaughtExceptionHandler(
-                (t, e) -> ShadowLog.e(TAG, "Uncaught exception in test thread " + t.getName(), e));
-        mBackupThread.start();
+        mBackupThread = startBackupThread(this::uncaughtException);
         mShadowBackupLooper = shadowOf(mBackupThread.getLooper());
 
         ContextWrapper context = RuntimeEnvironment.application;
@@ -121,6 +119,13 @@
         ShadowBackupPolicyEnforcer.setMandatoryBackupTransport(null);
     }
 
+    private void uncaughtException(Thread thread, Throwable e) {
+        // Unrelated exceptions are thrown in the backup thread. Until we mock everything properly
+        // we should not fail tests because of this. This is not flakiness, the exceptions thrown
+        // don't interfere with the tests.
+        ShadowLog.e(TAG, "Uncaught exception in test thread " + thread.getName(), e);
+    }
+
     /* Tests for destination string */
 
     @Test
diff --git a/services/robotests/src/com/android/server/backup/PerformBackupTaskTest.java b/services/robotests/src/com/android/server/backup/PerformBackupTaskTest.java
index e103464..d0e6658 100644
--- a/services/robotests/src/com/android/server/backup/PerformBackupTaskTest.java
+++ b/services/robotests/src/com/android/server/backup/PerformBackupTaskTest.java
@@ -16,18 +16,23 @@
 
 package com.android.server.backup;
 
+import static com.android.server.backup.testing.BackupManagerServiceTestUtils.createBackupWakeLock;
+import static com.android.server.backup.testing.BackupManagerServiceTestUtils.setUpBackupManagerServiceBasics;
+import static com.android.server.backup.testing.BackupManagerServiceTestUtils.startBackupThreadAndGetLooper;
 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.mock;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doNothing;
+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;
@@ -37,27 +42,27 @@
 import static java.util.stream.Collectors.toList;
 
 import android.app.Application;
-import android.app.IActivityManager;
 import android.app.IBackupAgent;
 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;
 import android.app.backup.IBackupManagerMonitor;
 import android.app.backup.IBackupObserver;
-import android.content.Context;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.os.Handler;
-import android.os.HandlerThread;
 import android.os.Looper;
 import android.os.Message;
+import android.os.ParcelFileDescriptor;
 import android.os.PowerManager;
 import android.os.RemoteException;
 import android.platform.test.annotations.Presubmit;
 import android.util.Pair;
-import android.util.SparseArray;
 
 import com.android.internal.backup.IBackupTransport;
 import com.android.server.backup.internal.BackupHandler;
@@ -65,6 +70,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;
@@ -80,6 +86,8 @@
 import org.mockito.ArgumentMatcher;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
 import org.robolectric.RuntimeEnvironment;
 import org.robolectric.annotation.Config;
 import org.robolectric.shadow.api.Shadow;
@@ -88,6 +96,7 @@
 import org.robolectric.shadows.ShadowQueuedWork;
 
 import java.io.File;
+import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.stream.Stream;
@@ -124,96 +133,100 @@
     @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);
 
-        PowerManager powerManager =
-                (PowerManager) application.getSystemService(Context.POWER_SERVICE);
-        mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "*backup*");
+        mWakeLock = createBackupWakeLock(application);
 
-        // Robolectric simulates multi-thread in a single-thread to avoid flakiness
-        HandlerThread backupThread = new HandlerThread("backup");
-        backupThread.setUncaughtExceptionHandler(
-                (t, e) -> fail("Uncaught exception " + e.getMessage()));
-        backupThread.start();
-        Looper backupLooper = backupThread.getLooper();
+        Looper backupLooper = startBackupThreadAndGetLooper();
         mShadowBackupLooper = shadowOf(backupLooper);
         mBackupHandler = new BackupHandler(mBackupManagerService, backupLooper);
 
         mBackupManager = spy(FakeIBackupManager.class);
 
-        when(mBackupManagerService.getTransportManager()).thenReturn(mTransportManager);
-        when(mBackupManagerService.getContext()).thenReturn(application);
-        when(mBackupManagerService.getPackageManager()).thenReturn(packageManager);
-        when(mBackupManagerService.getWakelock()).thenReturn(mWakeLock);
-        when(mBackupManagerService.getCurrentOpLock()).thenReturn(new Object());
-        when(mBackupManagerService.getQueueLock()).thenReturn(new Object());
-        when(mBackupManagerService.getBaseStateDir()).thenReturn(baseStateDir);
+        setUpBackupManagerServiceBasics(
+                mBackupManagerService,
+                application,
+                mTransportManager,
+                packageManager,
+                mBackupHandler,
+                mWakeLock);
+        when(mBackupManagerService.getBaseStateDir()).thenReturn(mBaseStateDir);
         when(mBackupManagerService.getDataDir()).thenReturn(dataDir);
-        when(mBackupManagerService.getCurrentOperations()).thenReturn(new SparseArray<>());
-        when(mBackupManagerService.getBackupHandler()).thenReturn(mBackupHandler);
         when(mBackupManagerService.getBackupManagerBinder()).thenReturn(mBackupManager);
-        when(mBackupManagerService.getActivityManager()).thenReturn(mock(IActivityManager.class));
     }
 
     @Test
     public void testRunTask_whenTransportProvidesFlags_passesThemToTheAgent() throws Exception {
-        BackupAgent agent = setUpAgent(PACKAGE_1);
+        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);
 
-        verify(agent).onBackup(any(), argThat(dataOutputWithTransportFlags(flags)), any());
+        verify(agentMock.agent)
+                .onBackup(any(), argThat(dataOutputWithTransportFlags(flags)), any());
     }
 
     @Test
     public void testRunTask_whenTransportDoesNotProvidesFlags() throws Exception {
-        BackupAgent agent = setUpAgent(PACKAGE_1);
-        PerformBackupTask task = createPerformBackupTask(emptyList(), false, true, PACKAGE_1);
+        TransportMock transportMock = setUpTransport(mTransport);
+        AgentMock agentMock = setUpAgent(PACKAGE_1);
+        PerformBackupTask task =
+                createPerformBackupTask(
+                        transportMock.transportClient,
+                        mTransport.transportDirName,
+                        emptyList(),
+                        PACKAGE_1);
 
         runTask(task);
 
-        verify(agent).onBackup(any(), argThat(dataOutputWithTransportFlags(0)), any());
+        verify(agentMock.agent).onBackup(any(), argThat(dataOutputWithTransportFlags(0)), any());
     }
 
     @Test
     public void testRunTask_whenTransportProvidesFlagsAndMultipleAgents_passesToAll()
             throws Exception {
-        List<BackupAgent> agents = setUpAgents(PACKAGE_1, PACKAGE_2);
-        BackupAgent agent1 = agents.get(0);
-        BackupAgent agent2 = agents.get(1);
+        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);
 
@@ -223,14 +236,283 @@
 
     @Test
     public void testRunTask_whenTransportChangeFlagsAfterTaskCreation() throws Exception {
-        BackupAgent agent = setUpAgent(PACKAGE_1);
-        PerformBackupTask task = createPerformBackupTask(emptyList(), false, true, PACKAGE_1);
+        TransportMock transportMock = setUpTransport(mTransport);
+        AgentMock agentMock = setUpAgent(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);
 
-        verify(agent).onBackup(any(), argThat(dataOutputWithTransportFlags(flags)), any());
+        verify(agentMock.agent)
+                .onBackup(any(), argThat(dataOutputWithTransportFlags(flags)), any());
+    }
+
+    @Test
+    public void testRunTask_callsListenerAndObserver() throws Exception {
+        TransportMock transportMock = setUpTransport(mTransport);
+        setUpAgent(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_releasesWakeLock() throws Exception {
+        TransportMock transportMock = setUpTransport(mTransport);
+        setUpAgent(PACKAGE_1);
+        PerformBackupTask task =
+                createPerformBackupTask(
+                        transportMock.transportClient,
+                        mTransport.transportDirName,
+                        emptyList(),
+                        PACKAGE_1);
+
+        runTask(task);
+
+        assertThat(mWakeLock.isHeld()).isFalse();
+    }
+
+    @Test
+    public void testRunTask_callsTransportPerformBackupWithAgentData() throws Exception {
+        TransportMock transportMock = setUpTransport(mTransport);
+        IBackupTransport transportBinder = transportMock.transport;
+        AgentMock agentMock = setUpAgent(PACKAGE_1);
+        agentOnBackupDo(
+                agentMock.agent,
+                (oldState, dataOutput, newState) -> {
+                    writeData(dataOutput, "key1", "foo".getBytes());
+                    writeData(dataOutput, "key2", "bar".getBytes());
+                });
+        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(transportBinder.performBackup(argThat(packageInfo(PACKAGE_1)), any(), anyInt()))
+                .then(this::mockAndVerifyTransportPerformBackupData);
+
+        runTask(task);
+
+        // Already verified data in mockAndVerifyPerformBackupData
+        verify(transportBinder).performBackup(argThat(packageInfo(PACKAGE_1)), any(), anyInt());
+    }
+
+    private int mockAndVerifyTransportPerformBackupData(InvocationOnMock invocation)
+            throws IOException {
+        ParcelFileDescriptor data = invocation.getArgument(1);
+
+        // Verifying that what we passed to the transport is what the agent wrote
+        BackupDataInput dataInput = new BackupDataInput(data.getFileDescriptor());
+
+        // "key1" => "foo"
+        assertThat(dataInput.readNextHeader()).isTrue();
+        assertThat(dataInput.getKey()).isEqualTo("key1");
+        int size1 = dataInput.getDataSize();
+        byte[] data1 = new byte[size1];
+        dataInput.readEntityData(data1, 0, size1);
+        assertThat(data1).isEqualTo("foo".getBytes());
+
+        // "key2" => "bar"
+        assertThat(dataInput.readNextHeader()).isTrue();
+        assertThat(dataInput.getKey()).isEqualTo("key2");
+        int size2 = dataInput.getDataSize();
+        byte[] data2 = new byte[size2];
+        dataInput.readEntityData(data2, 0, size2);
+        assertThat(data2).isEqualTo("bar".getBytes());
+
+        // No more
+        assertThat(dataInput.readNextHeader()).isFalse();
+
+        return BackupTransport.TRANSPORT_OK;
+    }
+
+    @Test
+    public void testRunTask_whenPerformBackupSucceeds_callsTransportFinishBackup()
+            throws Exception {
+        TransportMock transportMock = setUpTransport(mTransport);
+        IBackupTransport transportBinder = transportMock.transport;
+        setUpAgent(PACKAGE_1);
+        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(transportBinder).finishBackup();
+    }
+
+    @Test
+    public void testRunTask_whenProhibitedKey_failsAgent() throws Exception {
+        TransportMock transportMock = setUpTransport(mTransport);
+        AgentMock agentMock = setUpAgent(PACKAGE_1);
+        agentOnBackupDo(
+                agentMock.agent,
+                (oldState, dataOutput, newState) -> {
+                    char prohibitedChar = 0xff00;
+                    writeData(dataOutput, prohibitedChar + "key", "foo".getBytes());
+                });
+        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) {
@@ -241,32 +523,48 @@
         }
     }
 
-    private List<BackupAgent> setUpAgents(String... packageNames) {
+    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());
     }
 
-    private BackupAgent setUpAgent(String packageName) {
-        PackageInfo packageInfo = new PackageInfo();
-        packageInfo.packageName = packageName;
-        packageInfo.applicationInfo = new ApplicationInfo();
-        packageInfo.applicationInfo.flags = ApplicationInfo.FLAG_ALLOW_BACKUP;
-        packageInfo.applicationInfo.backupAgentName = "BackupAgent" + packageName;
-        packageInfo.applicationInfo.packageName = packageName;
-        mShadowPackageManager.setApplicationEnabledSetting(
-                packageName, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 0);
-        mShadowPackageManager.addPackage(packageInfo);
-        BackupAgent backupAgent = spy(BackupAgent.class);
-        IBackupAgent backupAgentBinder = IBackupAgent.Stub.asInterface(backupAgent.onBind());
-        when(mBackupManagerService.bindToAgentSynchronous(
-                        eq(packageInfo.applicationInfo), anyInt()))
-                .thenReturn(backupAgentBinder);
-        return backupAgent;
+    private AgentMock setUpAgent(String packageName) {
+        try {
+            PackageInfo packageInfo = new PackageInfo();
+            packageInfo.packageName = packageName;
+            packageInfo.applicationInfo = new ApplicationInfo();
+            packageInfo.applicationInfo.flags = ApplicationInfo.FLAG_ALLOW_BACKUP;
+            packageInfo.applicationInfo.backupAgentName = "BackupAgent" + packageName;
+            packageInfo.applicationInfo.packageName = packageName;
+            mShadowPackageManager.setApplicationEnabledSetting(
+                    packageName, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 0);
+            mShadowPackageManager.addPackage(packageInfo);
+            BackupAgent backupAgent = spy(BackupAgent.class);
+            IBackupAgent backupAgentBinder =
+                    spy(IBackupAgent.Stub.asInterface(backupAgent.onBind()));
+            // Don't crash our only process (in production code this would crash the app, not us)
+            doNothing().when(backupAgentBinder).fail(any());
+            when(mBackupManagerService.bindToAgentSynchronous(
+                            eq(packageInfo.applicationInfo), anyInt()))
+                    .thenReturn(backupAgentBinder);
+            return new AgentMock(backupAgentBinder, backupAgent);
+        } catch (RemoteException e) {
+            // Never happens, compiler happy
+            throw new AssertionError(e);
+        }
     }
 
     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));
@@ -274,24 +572,75 @@
         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 ArgumentMatcher<BackupDataOutput> dataOutputWithTransportFlags(int flags) {
+    private static ArgumentMatcher<PackageInfo> packageInfo(String 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) {
         return dataOutput -> dataOutput.getTransportFlags() == flags;
     }
 
+    private static void writeData(BackupDataOutput dataOutput, String key, byte[] data)
+            throws IOException {
+        dataOutput.writeEntityHeader(key, data.length);
+        dataOutput.writeEntityData(data, data.length);
+    }
+
+    private static void agentOnBackupDo(BackupAgent agent, BackupAgentOnBackup function)
+            throws Exception {
+        doAnswer(function).when(agent).onBackup(any(), any(), any());
+    }
+
+    @FunctionalInterface
+    private interface BackupAgentOnBackup extends Answer<Void> {
+        void onBackup(
+                ParcelFileDescriptor oldState,
+                BackupDataOutput dataOutput,
+                ParcelFileDescriptor newState)
+                throws IOException;
+
+        @Override
+        default Void answer(InvocationOnMock invocation) throws Throwable {
+            onBackup(
+                    invocation.getArgument(0),
+                    invocation.getArgument(1),
+                    invocation.getArgument(2));
+            return null;
+        }
+    }
+
+    private static class AgentMock {
+        private final IBackupAgent agentBinder;
+        private final BackupAgent agent;
+
+        private AgentMock(IBackupAgent agentBinder, BackupAgent agent) {
+            this.agentBinder = agentBinder;
+            this.agent = agent;
+        }
+    }
+
     private abstract static class FakeIBackupManager extends IBackupManager.Stub {
         private Handler mBackupHandler;
         private BackupRestoreTask mTask;
diff --git a/services/robotests/src/com/android/server/backup/TransportManagerTest.java b/services/robotests/src/com/android/server/backup/TransportManagerTest.java
index 44ac803..32697bd 100644
--- a/services/robotests/src/com/android/server/backup/TransportManagerTest.java
+++ b/services/robotests/src/com/android/server/backup/TransportManagerTest.java
@@ -19,14 +19,12 @@
 import static com.android.server.backup.testing.TransportData.genericTransport;
 import static com.android.server.backup.testing.TransportTestUtils.mockTransport;
 import static com.android.server.backup.testing.TransportTestUtils.setUpTransportsForTransportManager;
+
 import static com.google.common.truth.Truth.assertThat;
-import static java.util.Arrays.asList;
-import static java.util.Collections.emptyList;
-import static java.util.Collections.singletonList;
-import static java.util.stream.Collectors.toList;
-import static java.util.stream.Collectors.toSet;
-import static java.util.stream.Stream.concat;
+
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.argThat;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.reset;
@@ -35,6 +33,13 @@
 import static org.robolectric.shadow.api.Shadow.extract;
 import static org.testng.Assert.expectThrows;
 
+import static java.util.Arrays.asList;
+import static java.util.Collections.emptyList;
+import static java.util.Collections.singletonList;
+import static java.util.stream.Collectors.toList;
+import static java.util.stream.Collectors.toSet;
+import static java.util.stream.Stream.concat;
+
 import android.annotation.Nullable;
 import android.app.backup.BackupManager;
 import android.content.ComponentName;
@@ -43,7 +48,7 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
 import android.platform.test.annotations.Presubmit;
-import com.android.server.backup.testing.ShadowContextImplForBackup;
+
 import com.android.server.backup.testing.TransportData;
 import com.android.server.backup.testing.TransportTestUtils.TransportMock;
 import com.android.server.backup.transport.OnTransportRegisteredListener;
@@ -54,12 +59,7 @@
 import com.android.server.testing.SystemLoaderPackages;
 import com.android.server.testing.shadows.FrameworkShadowContextImpl;
 import com.android.server.testing.shadows.FrameworkShadowPackageManager;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Objects;
-import java.util.Set;
-import java.util.stream.Stream;
-import org.junit.After;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -69,6 +69,12 @@
 import org.robolectric.annotation.Config;
 import org.robolectric.shadows.ShadowPackageManager;
 
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+import java.util.stream.Stream;
+
 @RunWith(FrameworkRobolectricTestRunner.class)
 @Config(
     manifest = Config.NONE,
@@ -81,6 +87,12 @@
     private static final String PACKAGE_A = "some.package.a";
     private static final String PACKAGE_B = "some.package.b";
 
+    /**
+     * GMSCore depends on this constant so we define it here on top of the definition in {@link
+     * TransportManager} to verify this extra is passed
+     */
+    private static final String EXTRA_TRANSPORT_REGISTRATION = "transport_registration";
+
     @Mock private OnTransportRegisteredListener mListener;
     @Mock private TransportClientManager mTransportClientManager;
     private TransportData mTransportA1;
@@ -94,21 +106,15 @@
     public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
 
+        mContext = RuntimeEnvironment.application;
         mShadowPackageManager =
-                (FrameworkShadowPackageManager)
-                        extract(RuntimeEnvironment.application.getPackageManager());
-        mContext = RuntimeEnvironment.application.getApplicationContext();
+                (FrameworkShadowPackageManager) extract(mContext.getPackageManager());
 
         mTransportA1 = genericTransport(PACKAGE_A, "TransportFoo");
         mTransportA2 = genericTransport(PACKAGE_A, "TransportBar");
         mTransportB1 = genericTransport(PACKAGE_B, "TransportBaz");
     }
 
-    @After
-    public void tearDown() throws Exception {
-        ShadowContextImplForBackup.resetBackupShadowState();
-    }
-
     @Test
     public void testRegisterTransports() throws Exception {
         setUpPackage(PACKAGE_A, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
@@ -195,6 +201,22 @@
     }
 
     @Test
+    public void testRegisterTransports_passesRegistrationExtraToGetTransportClient()
+            throws Exception {
+        setUpPackage(PACKAGE_A, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
+        setUpTransports(mTransportA1);
+        TransportManager transportManager = createTransportManager(mTransportA1);
+
+        transportManager.registerTransports();
+
+        verify(mTransportClientManager)
+                .getTransportClient(
+                        eq(mTransportA1.getTransportComponent()),
+                        argThat(bundle -> bundle.getBoolean(EXTRA_TRANSPORT_REGISTRATION)),
+                        anyString());
+    }
+
+    @Test
     public void testOnPackageAdded_registerTransports() throws Exception {
         setUpPackage(PACKAGE_A, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
         setUpTransports(mTransportA1);
@@ -580,6 +602,9 @@
             when(mTransportClientManager.getTransportClient(
                             eq(transport.getTransportComponent()), any()))
                     .thenReturn(transportMock.transportClient);
+            when(mTransportClientManager.getTransportClient(
+                            eq(transport.getTransportComponent()), any(), any()))
+                    .thenReturn(transportMock.transportClient);
             transportMocks.add(transportMock);
         }
         return transportMocks;
diff --git a/services/robotests/src/com/android/server/backup/restore/ActiveRestoreSessionTest.java b/services/robotests/src/com/android/server/backup/restore/ActiveRestoreSessionTest.java
new file mode 100644
index 0000000..4ac00f0
--- /dev/null
+++ b/services/robotests/src/com/android/server/backup/restore/ActiveRestoreSessionTest.java
@@ -0,0 +1,205 @@
+/*
+ * 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.backup.restore;
+
+import static com.android.server.backup.testing.BackupManagerServiceTestUtils.createBackupWakeLock;
+import static com.android.server.backup.testing.BackupManagerServiceTestUtils.setUpBackupManagerServiceBasics;
+import static com.android.server.backup.testing.BackupManagerServiceTestUtils.startBackupThreadAndGetLooper;
+import static com.android.server.backup.testing.TransportData.backupTransport;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.AdditionalMatchers.aryEq;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.isNull;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.robolectric.Shadows.shadowOf;
+import static org.testng.Assert.expectThrows;
+
+import android.app.Application;
+import android.app.backup.IBackupManagerMonitor;
+import android.app.backup.IRestoreObserver;
+import android.app.backup.IRestoreSession;
+import android.app.backup.RestoreSet;
+import android.os.Looper;
+import android.os.PowerManager;
+import android.platform.test.annotations.Presubmit;
+
+import com.android.server.EventLogTags;
+import com.android.server.backup.BackupManagerService;
+import com.android.server.backup.TransportManager;
+import com.android.server.backup.internal.BackupHandler;
+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.testing.FrameworkRobolectricTestRunner;
+import com.android.server.testing.SystemLoaderPackages;
+import com.android.server.testing.shadows.ShadowEventLog;
+
+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;
+import org.robolectric.shadows.ShadowApplication;
+import org.robolectric.shadows.ShadowLooper;
+
+@RunWith(FrameworkRobolectricTestRunner.class)
+@Config(manifest = Config.NONE, sdk = 26, shadows = ShadowEventLog.class)
+@SystemLoaderPackages({"com.android.server.backup"})
+@Presubmit
+public class ActiveRestoreSessionTest {
+    private static final String PACKAGE_1 = "com.example.package1";
+    private static final String PACKAGE_2 = "com.example.package2";
+
+    @Mock private BackupManagerService mBackupManagerService;
+    @Mock private TransportManager mTransportManager;
+    @Mock private IRestoreObserver mObserver;
+    @Mock private IBackupManagerMonitor mMonitor;
+    private ShadowLooper mShadowBackupLooper;
+    private ShadowApplication mShadowApplication;
+    private PowerManager.WakeLock mWakeLock;
+    private TransportData mTransport;
+    private RestoreSet mRestoreSet1;
+    private RestoreSet mRestoreSet2;
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+
+        mTransport = backupTransport();
+
+        mRestoreSet1 = new RestoreSet("name1", "device1", 1L);
+        mRestoreSet2 = new RestoreSet("name2", "device2", 2L);
+
+        Application application = RuntimeEnvironment.application;
+        mShadowApplication = shadowOf(application);
+
+        Looper backupLooper = startBackupThreadAndGetLooper();
+        mShadowBackupLooper = shadowOf(backupLooper);
+        BackupHandler backupHandler = new BackupHandler(mBackupManagerService, backupLooper);
+
+        mWakeLock = createBackupWakeLock(application);
+
+        setUpBackupManagerServiceBasics(
+                mBackupManagerService,
+                application,
+                mTransportManager,
+                application.getPackageManager(),
+                backupHandler,
+                mWakeLock);
+    }
+
+    @Test
+    public void testGetAvailableRestoreSets_withoutPermission() throws Exception {
+        mShadowApplication.denyPermissions(android.Manifest.permission.BACKUP);
+        setUpTransport(mTransport);
+        IRestoreSession restoreSession = createActiveRestoreSession(PACKAGE_1, mTransport);
+
+        expectThrows(
+                SecurityException.class,
+                () -> restoreSession.getAvailableRestoreSets(mObserver, mMonitor));
+    }
+
+    @Test
+    public void testGetAvailableRestoreSets_forNullObserver() throws Exception {
+        mShadowApplication.grantPermissions(android.Manifest.permission.BACKUP);
+        setUpTransport(mTransport);
+        IRestoreSession restoreSession = createActiveRestoreSession(PACKAGE_1, mTransport);
+
+        expectThrows(
+                RuntimeException.class,
+                () -> restoreSession.getAvailableRestoreSets(null, mMonitor));
+    }
+
+    @Test
+    public void testGetAvailableRestoreSets_whenTransportNotRegistered() throws Exception {
+        mShadowApplication.grantPermissions(android.Manifest.permission.BACKUP);
+        setUpTransport(mTransport.unregistered());
+        IRestoreSession restoreSession = createActiveRestoreSession(PACKAGE_1, mTransport);
+
+        int result = restoreSession.getAvailableRestoreSets(mObserver, mMonitor);
+
+        assertThat(result).isEqualTo(-1);
+    }
+
+    @Test
+    public void testGetAvailableRestoreSets() throws Exception {
+        mShadowApplication.grantPermissions(android.Manifest.permission.BACKUP);
+        TransportMock transportMock = setUpTransport(mTransport);
+        when(transportMock.transport.getAvailableRestoreSets())
+                .thenReturn(new RestoreSet[] {mRestoreSet1, mRestoreSet2});
+        IRestoreSession restoreSession = createActiveRestoreSession(PACKAGE_1, mTransport);
+
+        int result = restoreSession.getAvailableRestoreSets(mObserver, mMonitor);
+
+        mShadowBackupLooper.runToEndOfTasks();
+        assertThat(result).isEqualTo(0);
+        verify(mObserver)
+                .restoreSetsAvailable(aryEq(new RestoreSet[] {mRestoreSet1, mRestoreSet2}));
+        verify(mTransportManager)
+                .disposeOfTransportClient(eq(transportMock.transportClient), any());
+        assertThat(mWakeLock.isHeld()).isFalse();
+    }
+
+    @Test
+    public void testGetAvailableRestoreSets_forEmptyRestoreSets() throws Exception {
+        mShadowApplication.grantPermissions(android.Manifest.permission.BACKUP);
+        TransportMock transportMock = setUpTransport(mTransport);
+        when(transportMock.transport.getAvailableRestoreSets()).thenReturn(new RestoreSet[0]);
+        IRestoreSession restoreSession = createActiveRestoreSession(PACKAGE_1, mTransport);
+
+        int result = restoreSession.getAvailableRestoreSets(mObserver, mMonitor);
+
+        mShadowBackupLooper.runToEndOfTasks();
+        assertThat(result).isEqualTo(0);
+        verify(mObserver).restoreSetsAvailable(aryEq(new RestoreSet[0]));
+        assertThat(ShadowEventLog.hasEvent(EventLogTags.RESTORE_TRANSPORT_FAILURE)).isFalse();
+    }
+
+    @Test
+    public void testGetAvailableRestoreSets_forNullRestoreSets() throws Exception {
+        mShadowApplication.grantPermissions(android.Manifest.permission.BACKUP);
+        TransportMock transportMock = setUpTransport(mTransport);
+        when(transportMock.transport.getAvailableRestoreSets()).thenReturn(null);
+        IRestoreSession restoreSession = createActiveRestoreSession(PACKAGE_1, mTransport);
+
+        int result = restoreSession.getAvailableRestoreSets(mObserver, mMonitor);
+
+        mShadowBackupLooper.runToEndOfTasks();
+        assertThat(result).isEqualTo(0);
+        verify(mObserver).restoreSetsAvailable(isNull());
+        assertThat(ShadowEventLog.hasEvent(EventLogTags.RESTORE_TRANSPORT_FAILURE)).isTrue();
+        verify(mTransportManager)
+                .disposeOfTransportClient(eq(transportMock.transportClient), any());
+        assertThat(mWakeLock.isHeld()).isFalse();
+    }
+
+    private IRestoreSession createActiveRestoreSession(
+            String packageName, TransportData transport) {
+        return new ActiveRestoreSession(
+                mBackupManagerService, packageName, transport.transportName);
+    }
+
+    private TransportMock setUpTransport(TransportData transport) throws Exception {
+        return TransportTestUtils.setUpTransport(mTransportManager, transport);
+    }
+}
diff --git a/services/robotests/src/com/android/server/backup/testing/BackupManagerServiceTestUtils.java b/services/robotests/src/com/android/server/backup/testing/BackupManagerServiceTestUtils.java
new file mode 100644
index 0000000..3c0234b
--- /dev/null
+++ b/services/robotests/src/com/android/server/backup/testing/BackupManagerServiceTestUtils.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.backup.testing;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import android.app.Application;
+import android.app.IActivityManager;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.os.HandlerThread;
+import android.os.Looper;
+import android.os.PowerManager;
+import android.util.SparseArray;
+
+import com.android.server.backup.BackupManagerService;
+import com.android.server.backup.TransportManager;
+import com.android.server.backup.internal.BackupHandler;
+
+import java.lang.Thread.UncaughtExceptionHandler;
+
+public class BackupManagerServiceTestUtils {
+    /** Sets up a basic mocks for {@link BackupManagerService} */
+    public static void setUpBackupManagerServiceBasics(
+            BackupManagerService backupManagerService,
+            Context context,
+            TransportManager transportManager,
+            PackageManager packageManager,
+            BackupHandler backupHandler,
+            PowerManager.WakeLock wakeLock) {
+        when(backupManagerService.getContext()).thenReturn(context);
+        when(backupManagerService.getTransportManager()).thenReturn(transportManager);
+        when(backupManagerService.getPackageManager()).thenReturn(packageManager);
+        when(backupManagerService.getBackupHandler()).thenReturn(backupHandler);
+        when(backupManagerService.getCurrentOpLock()).thenReturn(new Object());
+        when(backupManagerService.getQueueLock()).thenReturn(new Object());
+        when(backupManagerService.getCurrentOperations()).thenReturn(new SparseArray<>());
+        when(backupManagerService.getActivityManager()).thenReturn(mock(IActivityManager.class));
+        when(backupManagerService.getWakelock()).thenReturn(wakeLock);
+    }
+
+    public static PowerManager.WakeLock createBackupWakeLock(Application application) {
+        PowerManager powerManager =
+                (PowerManager) application.getSystemService(Context.POWER_SERVICE);
+        return powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "*backup*");
+    }
+
+    /**
+     * Creates a backup thread associated with a looper, starts it and returns its looper for
+     * shadowing and creation of the backup handler.
+     *
+     * <p>Note that Robolectric simulates multi-thread in a single-thread to avoid flakiness, so
+     * even though we started the thread, you should control its execution via the shadow of the
+     * looper returned.
+     *
+     * @return The {@link Looper} for the backup thread.
+     */
+    public static Looper startBackupThreadAndGetLooper() {
+        HandlerThread backupThread = new HandlerThread("backup");
+        backupThread.start();
+        return backupThread.getLooper();
+    }
+
+    /**
+     * Similar to {@link #startBackupThreadAndGetLooper()} but with a custom exception handler and
+     * returning the thread instead of the looper associated with it.
+     *
+     * @param exceptionHandler Uncaught exception handler for backup thread.
+     * @return The backup thread.
+     * @see #startBackupThreadAndGetLooper()
+     */
+    public static HandlerThread startBackupThread(UncaughtExceptionHandler exceptionHandler) {
+        HandlerThread backupThread = new HandlerThread("backup");
+        backupThread.setUncaughtExceptionHandler(exceptionHandler);
+        backupThread.start();
+        return backupThread;
+    }
+
+    private BackupManagerServiceTestUtils() {}
+}
diff --git a/services/robotests/src/com/android/server/backup/testing/ShadowBackupTransportStub.java b/services/robotests/src/com/android/server/backup/testing/ShadowBackupTransportStub.java
deleted file mode 100644
index 48a12f0..0000000
--- a/services/robotests/src/com/android/server/backup/testing/ShadowBackupTransportStub.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.server.backup.testing;
-
-import android.os.IBinder;
-
-import com.android.internal.backup.IBackupTransport;
-
-import org.robolectric.annotation.Implementation;
-import org.robolectric.annotation.Implements;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * Shadow IBackupTransport.Stub, returns a transport corresponding to the binder.
- */
-@Implements(IBackupTransport.Stub.class)
-public class ShadowBackupTransportStub {
-    public static Map<IBinder, IBackupTransport> sBinderTransportMap = new HashMap<>();
-
-    @Implementation
-    public static IBackupTransport asInterface(IBinder obj) {
-        return sBinderTransportMap.get(obj);
-    }
-}
diff --git a/services/robotests/src/com/android/server/backup/testing/ShadowContextImplForBackup.java b/services/robotests/src/com/android/server/backup/testing/ShadowContextImplForBackup.java
deleted file mode 100644
index c3975db..0000000
--- a/services/robotests/src/com/android/server/backup/testing/ShadowContextImplForBackup.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.server.backup.testing;
-
-import android.annotation.RequiresPermission;
-import android.content.ComponentName;
-import android.content.Intent;
-import android.content.ServiceConnection;
-import android.os.IBinder;
-import android.os.UserHandle;
-
-import org.robolectric.annotation.Implementation;
-import org.robolectric.annotation.Implements;
-import org.robolectric.shadows.ShadowApplication;
-import org.robolectric.shadows.ShadowContextImpl;
-
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * Implementation of ContextImpl shadow, handling bindServiceAsUser().
- */
-@Implements(className = ShadowContextImpl.CLASS_NAME)
-public class ShadowContextImplForBackup extends ShadowContextImpl {
-    public static Map<ComponentName, IBinder> sComponentBinderMap = new HashMap<>();
-    public static Set<ComponentName> sUnbindableComponents = new HashSet<>();
-
-    @Implementation
-    public boolean bindServiceAsUser(@RequiresPermission Intent service, ServiceConnection conn,
-            int flags, UserHandle user) {
-        if (sUnbindableComponents.contains(service.getComponent())) {
-            return false;
-        }
-
-        ShadowApplication.getInstance().setComponentNameAndServiceForBindService(
-                service.getComponent(), sComponentBinderMap.get(service.getComponent()));
-        return bindService(service, conn, flags);
-    }
-
-
-    /**
-     * Resets backup-related shadow state.
-     */
-    public static void resetBackupShadowState() {
-        sComponentBinderMap.clear();
-        sUnbindableComponents.clear();
-    }
-}
diff --git a/services/robotests/src/com/android/server/backup/transport/TransportClientManagerTest.java b/services/robotests/src/com/android/server/backup/transport/TransportClientManagerTest.java
new file mode 100644
index 0000000..5e3c974
--- /dev/null
+++ b/services/robotests/src/com/android/server/backup/transport/TransportClientManagerTest.java
@@ -0,0 +1,122 @@
+/*
+ * 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.backup.transport;
+
+import static com.android.server.backup.TransportManager.SERVICE_ACTION_TRANSPORT_HOST;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.argThat;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.Bundle;
+import android.os.UserHandle;
+import android.platform.test.annotations.Presubmit;
+import com.android.server.testing.FrameworkRobolectricTestRunner;
+import com.android.server.testing.SystemLoaderPackages;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentMatcher;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.annotation.Config;
+
+@RunWith(FrameworkRobolectricTestRunner.class)
+@Config(manifest = Config.NONE, sdk = 26)
+@SystemLoaderPackages({"com.android.server.backup"})
+@Presubmit
+public class TransportClientManagerTest {
+
+    private static final String PACKAGE_NAME = "random.package.name";
+    private static final String CLASS_NAME = "random.package.name.transport.Transport";
+
+    @Mock private Context mContext;
+    @Mock private TransportConnectionListener mTransportConnectionListener;
+    private TransportClientManager mTransportClientManager;
+    private ComponentName mTransportComponent;
+    private Intent mBindIntent;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        mTransportClientManager = new TransportClientManager(mContext);
+        mTransportComponent = new ComponentName(PACKAGE_NAME, CLASS_NAME);
+        mBindIntent = new Intent(SERVICE_ACTION_TRANSPORT_HOST).setComponent(mTransportComponent);
+
+        when(mContext.bindServiceAsUser(
+                        any(Intent.class),
+                        any(ServiceConnection.class),
+                        anyInt(),
+                        any(UserHandle.class)))
+                .thenReturn(true);
+    }
+
+    @Test
+    public void testGetTransportClient_withExtras_createsTransportClientWithCorrectIntent() {
+        Bundle extras = new Bundle();
+        extras.putBoolean("random_extra", true);
+        mBindIntent.putExtras(extras);
+
+        TransportClient transportClient =
+                mTransportClientManager.getTransportClient(mTransportComponent, extras, "caller");
+
+        transportClient.connectAsync(mTransportConnectionListener, "caller");
+        verify(mContext)
+                .bindServiceAsUser(
+                        argThat(matchesIntentAndExtras(mBindIntent)),
+                        any(ServiceConnection.class),
+                        anyInt(),
+                        any(UserHandle.class));
+    }
+
+    private ArgumentMatcher<Intent> matchesIntentAndExtras(Intent expectedIntent) {
+        return (Intent actualIntent) -> {
+            if (!expectedIntent.filterEquals(actualIntent)) {
+                return false;
+            }
+
+            Bundle expectedExtras = expectedIntent.getExtras();
+            Bundle actualExtras = actualIntent.getExtras();
+
+            if (expectedExtras == null && actualExtras == null) {
+                return true;
+            }
+
+            if (expectedExtras == null || actualExtras == null) {
+                return false;
+            }
+
+            if (expectedExtras.size() != actualExtras.size()) {
+                return false;
+            }
+
+            for (String key : expectedExtras.keySet()) {
+                if (!expectedExtras.get(key).equals(actualExtras.get(key))) {
+                    return false;
+                }
+            }
+
+            return true;
+        };
+    }
+}
diff --git a/services/robotests/src/com/android/server/backup/testing/ShadowAppBackupUtils.java b/services/robotests/src/com/android/server/testing/shadows/ShadowAppBackupUtils.java
similarity index 96%
rename from services/robotests/src/com/android/server/backup/testing/ShadowAppBackupUtils.java
rename to services/robotests/src/com/android/server/testing/shadows/ShadowAppBackupUtils.java
index 73cb4c0..c3b2f0d 100644
--- a/services/robotests/src/com/android/server/backup/testing/ShadowAppBackupUtils.java
+++ b/services/robotests/src/com/android/server/testing/shadows/ShadowAppBackupUtils.java
@@ -14,7 +14,7 @@
  * limitations under the License
  */
 
-package com.android.server.backup.testing;
+package com.android.server.testing.shadows;
 
 import android.annotation.Nullable;
 import android.content.pm.PackageManager;
diff --git a/services/robotests/src/com/android/server/testing/shadows/ShadowBackupDataInput.java b/services/robotests/src/com/android/server/testing/shadows/ShadowBackupDataInput.java
index 28489af..8016a8b 100644
--- a/services/robotests/src/com/android/server/testing/shadows/ShadowBackupDataInput.java
+++ b/services/robotests/src/com/android/server/testing/shadows/ShadowBackupDataInput.java
@@ -21,41 +21,76 @@
 import org.robolectric.annotation.Implementation;
 import org.robolectric.annotation.Implements;
 
+import java.io.EOFException;
 import java.io.FileDescriptor;
+import java.io.FileInputStream;
 import java.io.IOException;
+import java.io.ObjectInputStream;
 
+/**
+ * Shadow for {@link BackupDataInput}. Format read does NOT match implementation. To write data to
+ * be read by this shadow, you should also declare shadow {@link ShadowBackupDataOutput}.
+ */
 @Implements(BackupDataInput.class)
 public class ShadowBackupDataInput {
-    @Implementation
-    public void __constructor__(FileDescriptor fd) {
-    }
+    private ObjectInputStream mInput;
+    private int mSize;
+    private String mKey;
+    private boolean mHeaderReady;
 
     @Implementation
-    protected void finalize() throws Throwable {
+    public void __constructor__(FileDescriptor fd) {
+        try {
+            mInput = new ObjectInputStream(new FileInputStream(fd));
+        } catch (IOException e) {
+            throw new AssertionError(e);
+        }
     }
 
     @Implementation
     public boolean readNextHeader() throws IOException {
-        return false;
+        mHeaderReady = false;
+        try {
+            mSize = mInput.readInt();
+        } catch (EOFException e) {
+            return false;
+        }
+        mKey = mInput.readUTF();
+        mHeaderReady = true;
+        return true;
     }
 
     @Implementation
     public String getKey() {
-        throw new AssertionError("Can't call because readNextHeader() returned false");
+        checkHeaderReady();
+        return mKey;
     }
 
     @Implementation
     public int getDataSize() {
-        throw new AssertionError("Can't call because readNextHeader() returned false");
+        checkHeaderReady();
+        return mSize;
     }
 
     @Implementation
     public int readEntityData(byte[] data, int offset, int size) throws IOException {
-        throw new AssertionError("Can't call because readNextHeader() returned false");
+        checkHeaderReady();
+        int result = mInput.read(data, offset, size);
+        if (result < 0) {
+            throw new IOException("result=0x" + Integer.toHexString(result));
+        }
+        return result;
     }
 
     @Implementation
     public void skipEntityData() throws IOException {
-        throw new AssertionError("Can't call because readNextHeader() returned false");
+        checkHeaderReady();
+        mInput.read(new byte[mSize], 0, mSize);
+    }
+
+    private void checkHeaderReady() {
+        if (!mHeaderReady) {
+            throw new IllegalStateException("Entity header not read");
+        }
     }
 }
diff --git a/services/robotests/src/com/android/server/testing/shadows/ShadowBackupDataOutput.java b/services/robotests/src/com/android/server/testing/shadows/ShadowBackupDataOutput.java
index c7deada..e78a4b3 100644
--- a/services/robotests/src/com/android/server/testing/shadows/ShadowBackupDataOutput.java
+++ b/services/robotests/src/com/android/server/testing/shadows/ShadowBackupDataOutput.java
@@ -21,16 +21,29 @@
 import org.robolectric.annotation.Implementation;
 import org.robolectric.annotation.Implements;
 
+import java.io.ByteArrayOutputStream;
 import java.io.FileDescriptor;
+import java.io.FileOutputStream;
 import java.io.IOException;
+import java.io.ObjectOutputStream;
 
+/**
+ * Shadow for {@link BackupDataOutput}. Format written does NOT match implementation. To read data
+ * written with this shadow you should also declare shadow {@link ShadowBackupDataInput}.
+ */
 @Implements(BackupDataOutput.class)
 public class ShadowBackupDataOutput {
     private long mQuota;
     private int mTransportFlags;
+    private ObjectOutputStream mOutput;
 
     @Implementation
     public void __constructor__(FileDescriptor fd, long quota, int transportFlags) {
+        try {
+            mOutput = new ObjectOutputStream(new FileOutputStream(fd));
+        } catch (IOException e) {
+            throw new AssertionError(e);
+        }
         mQuota = quota;
         mTransportFlags = transportFlags;
     }
@@ -47,11 +60,27 @@
 
     @Implementation
     public int writeEntityHeader(String key, int dataSize) throws IOException {
-        return 0;
+        final int size;
+        try (ByteArrayOutputStream byteStream = new ByteArrayOutputStream()) {
+            writeEntityHeader(new ObjectOutputStream(byteStream), key, dataSize);
+            size = byteStream.size();
+        }
+        writeEntityHeader(mOutput, key, dataSize);
+        return size;
+    }
+
+    private void writeEntityHeader(ObjectOutputStream stream, String key, int dataSize)
+            throws IOException {
+        // Write the int first because readInt() throws EOFException, to know when stream ends
+        stream.writeInt(dataSize);
+        stream.writeUTF(key);
+        stream.flush();
     }
 
     @Implementation
     public int writeEntityData(byte[] data, int size) throws IOException {
-        return 0;
+        mOutput.write(data, 0, size);
+        mOutput.flush();
+        return size;
     }
 }
diff --git a/services/robotests/src/com/android/server/backup/testing/ShadowBackupPolicyEnforcer.java b/services/robotests/src/com/android/server/testing/shadows/ShadowBackupPolicyEnforcer.java
similarity index 62%
rename from services/robotests/src/com/android/server/backup/testing/ShadowBackupPolicyEnforcer.java
rename to services/robotests/src/com/android/server/testing/shadows/ShadowBackupPolicyEnforcer.java
index ef4764d..e76b9d1 100644
--- a/services/robotests/src/com/android/server/backup/testing/ShadowBackupPolicyEnforcer.java
+++ b/services/robotests/src/com/android/server/testing/shadows/ShadowBackupPolicyEnforcer.java
@@ -1,5 +1,6 @@
-package com.android.server.backup.testing;
+package com.android.server.testing.shadows;
 
+import android.annotation.Nullable;
 import android.content.ComponentName;
 
 import com.android.server.backup.BackupPolicyEnforcer;
@@ -9,14 +10,15 @@
 
 @Implements(BackupPolicyEnforcer.class)
 public class ShadowBackupPolicyEnforcer {
+    @Nullable private static ComponentName sMandatoryBackupTransport;
 
-    private static ComponentName sMandatoryBackupTransport;
-
-    public static void setMandatoryBackupTransport(ComponentName backupTransportComponent) {
+    public static void setMandatoryBackupTransport(
+            @Nullable ComponentName backupTransportComponent) {
         sMandatoryBackupTransport = backupTransportComponent;
     }
 
     @Implementation
+    @Nullable
     public ComponentName getMandatoryBackupTransport() {
         return sMandatoryBackupTransport;
     }
diff --git a/services/tests/servicestests/src/com/android/server/ForceAppStandbyTrackerTest.java b/services/tests/servicestests/src/com/android/server/AppStateTrackerTest.java
similarity index 92%
rename from services/tests/servicestests/src/com/android/server/ForceAppStandbyTrackerTest.java
rename to services/tests/servicestests/src/com/android/server/AppStateTrackerTest.java
index 2c50f22..90db2a3 100644
--- a/services/tests/servicestests/src/com/android/server/ForceAppStandbyTrackerTest.java
+++ b/services/tests/servicestests/src/com/android/server/AppStateTrackerTest.java
@@ -15,7 +15,7 @@
  */
 package com.android.server;
 
-import static com.android.server.ForceAppStandbyTracker.TARGET_OP;
+import static com.android.server.AppStateTracker.TARGET_OP;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -33,6 +33,7 @@
 import static org.mockito.Mockito.when;
 
 import android.app.ActivityManager;
+import android.app.ActivityManagerInternal;
 import android.app.AppOpsManager;
 import android.app.AppOpsManager.OpEntry;
 import android.app.AppOpsManager.PackageOps;
@@ -63,7 +64,7 @@
 
 import com.android.internal.app.IAppOpsCallback;
 import com.android.internal.app.IAppOpsService;
-import com.android.server.ForceAppStandbyTracker.Listener;
+import com.android.server.AppStateTracker.Listener;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -82,17 +83,17 @@
 import java.util.function.Consumer;
 
 /**
- * Tests for {@link ForceAppStandbyTracker}
+ * Tests for {@link AppStateTracker}
  *
  * Run with:
- atest $ANDROID_BUILD_TOP/frameworks/base/services/tests/servicestests/src/com/android/server/ForceAppStandbyTrackerTest.java
+ atest $ANDROID_BUILD_TOP/frameworks/base/services/tests/servicestests/src/com/android/server/AppStateTrackerTest.java
  */
 @SmallTest
 @RunWith(AndroidJUnit4.class)
-public class ForceAppStandbyTrackerTest {
+public class AppStateTrackerTest {
 
-    private class ForceAppStandbyTrackerTestable extends ForceAppStandbyTracker {
-        ForceAppStandbyTrackerTestable() {
+    private class AppStateTrackerTestable extends AppStateTracker {
+        AppStateTrackerTestable() {
             super(mMockContext, Looper.getMainLooper());
         }
 
@@ -112,6 +113,11 @@
         }
 
         @Override
+        ActivityManagerInternal injectActivityManagerInternal() {
+            return mMockIActivityManagerInternal;
+        }
+
+        @Override
         PowerManagerInternal injectPowerManagerInternal() {
             return mMockPowerManagerInternal;
         }
@@ -152,6 +158,9 @@
     private IActivityManager mMockIActivityManager;
 
     @Mock
+    private ActivityManagerInternal mMockIActivityManagerInternal;
+
+    @Mock
     private AppOpsManager mMockAppOpsManager;
 
     @Mock
@@ -195,7 +204,7 @@
         return new PowerSaveState.Builder().setBatterySaverEnabled(mPowerSaveMode).build();
     }
 
-    private ForceAppStandbyTrackerTestable newInstance() throws Exception {
+    private AppStateTrackerTestable newInstance() throws Exception {
         MockitoAnnotations.initMocks(this);
 
         when(mMockIAppOpsService.checkOperation(eq(TARGET_OP), anyInt(), anyString()))
@@ -205,12 +214,12 @@
                             AppOpsManager.MODE_IGNORED : AppOpsManager.MODE_ALLOWED;
                 });
 
-        final ForceAppStandbyTrackerTestable instance = new ForceAppStandbyTrackerTestable();
+        final AppStateTrackerTestable instance = new AppStateTrackerTestable();
 
         return instance;
     }
 
-    private void callStart(ForceAppStandbyTrackerTestable instance) throws RemoteException {
+    private void callStart(AppStateTrackerTestable instance) throws RemoteException {
 
         // Set up functions that start() calls.
         when(mMockPowerManagerInternal.getLowPowerState(eq(ServiceType.FORCE_ALL_APPS_STANDBY)))
@@ -223,7 +232,7 @@
         when(mMockContext.getContentResolver()).thenReturn(mMockContentResolver);
 
         // Call start.
-        instance.start();
+        instance.onSystemServicesReady();
 
         // Capture the listeners.
         ArgumentCaptor<IUidObserver> uidObserverArgumentCaptor =
@@ -287,7 +296,7 @@
     private static final int JOBS_ONLY = 1 << 1;
     private static final int JOBS_AND_ALARMS = ALARMS_ONLY | JOBS_ONLY;
 
-    private void areRestricted(ForceAppStandbyTrackerTestable instance, int uid, String packageName,
+    private void areRestricted(AppStateTrackerTestable instance, int uid, String packageName,
             int restrictionTypes, boolean exemptFromBatterySaver) {
         assertEquals(((restrictionTypes & JOBS_ONLY) != 0),
                 instance.areJobsRestricted(uid, packageName, exemptFromBatterySaver));
@@ -295,13 +304,13 @@
                 instance.areAlarmsRestricted(uid, packageName, exemptFromBatterySaver));
     }
 
-    private void areRestricted(ForceAppStandbyTrackerTestable instance, int uid, String packageName,
+    private void areRestricted(AppStateTrackerTestable instance, int uid, String packageName,
             int restrictionTypes) {
         areRestricted(instance, uid, packageName, restrictionTypes,
                 /*exemptFromBatterySaver=*/ false);
     }
 
-    private void areRestrictedWithExemption(ForceAppStandbyTrackerTestable instance,
+    private void areRestrictedWithExemption(AppStateTrackerTestable instance,
             int uid, String packageName, int restrictionTypes) {
         areRestricted(instance, uid, packageName, restrictionTypes,
                 /*exemptFromBatterySaver=*/ true);
@@ -309,7 +318,7 @@
 
     @Test
     public void testAll() throws Exception {
-        final ForceAppStandbyTrackerTestable instance = newInstance();
+        final AppStateTrackerTestable instance = newInstance();
         callStart(instance);
 
         assertFalse(instance.isForceAllAppsStandbyEnabled());
@@ -343,6 +352,7 @@
         assertTrue(instance.isUidActive(Process.SYSTEM_UID));
 
         mIUidObserver.onUidActive(UID_1);
+        waitUntilMainHandlerDrain();
         areRestricted(instance, UID_1, PACKAGE_1, NONE);
         areRestricted(instance, UID_2, PACKAGE_2, JOBS_AND_ALARMS);
         areRestricted(instance, Process.SYSTEM_UID, PACKAGE_SYSTEM, NONE);
@@ -350,6 +360,7 @@
         assertFalse(instance.isUidActive(UID_2));
 
         mIUidObserver.onUidGone(UID_1, /*disable=*/ false);
+        waitUntilMainHandlerDrain();
         areRestricted(instance, UID_1, PACKAGE_1, JOBS_AND_ALARMS);
         areRestricted(instance, UID_2, PACKAGE_2, JOBS_AND_ALARMS);
         areRestricted(instance, Process.SYSTEM_UID, PACKAGE_SYSTEM, NONE);
@@ -357,11 +368,13 @@
         assertFalse(instance.isUidActive(UID_2));
 
         mIUidObserver.onUidActive(UID_1);
+        waitUntilMainHandlerDrain();
         areRestricted(instance, UID_1, PACKAGE_1, NONE);
         areRestricted(instance, UID_2, PACKAGE_2, JOBS_AND_ALARMS);
         areRestricted(instance, Process.SYSTEM_UID, PACKAGE_SYSTEM, NONE);
 
         mIUidObserver.onUidIdle(UID_1, /*disable=*/ false);
+        waitUntilMainHandlerDrain();
         areRestricted(instance, UID_1, PACKAGE_1, JOBS_AND_ALARMS);
         areRestricted(instance, UID_2, PACKAGE_2, JOBS_AND_ALARMS);
         areRestricted(instance, Process.SYSTEM_UID, PACKAGE_SYSTEM, NONE);
@@ -462,15 +475,20 @@
 
     @Test
     public void testUidStateForeground() throws Exception {
-        final ForceAppStandbyTrackerTestable instance = newInstance();
+        final AppStateTrackerTestable instance = newInstance();
         callStart(instance);
 
         mIUidObserver.onUidActive(UID_1);
 
+        waitUntilMainHandlerDrain();
         assertTrue(instance.isUidActive(UID_1));
         assertFalse(instance.isUidActive(UID_2));
         assertTrue(instance.isUidActive(Process.SYSTEM_UID));
 
+        assertTrue(instance.isUidActiveSynced(UID_1));
+        assertFalse(instance.isUidActiveSynced(UID_2));
+        assertTrue(instance.isUidActiveSynced(Process.SYSTEM_UID));
+
         assertFalse(instance.isUidInForeground(UID_1));
         assertFalse(instance.isUidInForeground(UID_2));
         assertTrue(instance.isUidInForeground(Process.SYSTEM_UID));
@@ -479,10 +497,15 @@
         mIUidObserver.onUidStateChanged(UID_2,
                 ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE, 0);
 
+        waitUntilMainHandlerDrain();
         assertTrue(instance.isUidActive(UID_1));
         assertFalse(instance.isUidActive(UID_2));
         assertTrue(instance.isUidActive(Process.SYSTEM_UID));
 
+        assertTrue(instance.isUidActiveSynced(UID_1));
+        assertFalse(instance.isUidActiveSynced(UID_2));
+        assertTrue(instance.isUidActiveSynced(Process.SYSTEM_UID));
+
         assertFalse(instance.isUidInForeground(UID_1));
         assertTrue(instance.isUidInForeground(UID_2));
         assertTrue(instance.isUidInForeground(Process.SYSTEM_UID));
@@ -491,6 +514,7 @@
         mIUidObserver.onUidStateChanged(UID_1,
                 ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE, 0);
 
+        waitUntilMainHandlerDrain();
         assertTrue(instance.isUidActive(UID_1));
         assertFalse(instance.isUidActive(UID_2));
         assertTrue(instance.isUidActive(Process.SYSTEM_UID));
@@ -501,6 +525,7 @@
 
         mIUidObserver.onUidGone(UID_1, true);
 
+        waitUntilMainHandlerDrain();
         assertFalse(instance.isUidActive(UID_1));
         assertFalse(instance.isUidActive(UID_2));
         assertTrue(instance.isUidActive(Process.SYSTEM_UID));
@@ -511,6 +536,7 @@
 
         mIUidObserver.onUidIdle(UID_2, true);
 
+        waitUntilMainHandlerDrain();
         assertFalse(instance.isUidActive(UID_1));
         assertFalse(instance.isUidActive(UID_2));
         assertTrue(instance.isUidActive(Process.SYSTEM_UID));
@@ -522,6 +548,7 @@
         mIUidObserver.onUidStateChanged(UID_1,
                 ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND, 0);
 
+        waitUntilMainHandlerDrain();
         assertFalse(instance.isUidActive(UID_1));
         assertFalse(instance.isUidActive(UID_2));
         assertTrue(instance.isUidActive(Process.SYSTEM_UID));
@@ -533,18 +560,39 @@
         mIUidObserver.onUidStateChanged(UID_1,
                 ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND, 0);
 
+        waitUntilMainHandlerDrain();
         assertFalse(instance.isUidActive(UID_1));
         assertFalse(instance.isUidActive(UID_2));
         assertTrue(instance.isUidActive(Process.SYSTEM_UID));
 
+        assertFalse(instance.isUidActiveSynced(UID_1));
+        assertFalse(instance.isUidActiveSynced(UID_2));
+        assertTrue(instance.isUidActiveSynced(Process.SYSTEM_UID));
+
         assertFalse(instance.isUidInForeground(UID_1));
         assertFalse(instance.isUidInForeground(UID_2));
         assertTrue(instance.isUidInForeground(Process.SYSTEM_UID));
+
+        // The result from AMI.isUidActive() only affects isUidActiveSynced().
+        when(mMockIActivityManagerInternal.isUidActive(anyInt())).thenReturn(true);
+
+        assertFalse(instance.isUidActive(UID_1));
+        assertFalse(instance.isUidActive(UID_2));
+        assertTrue(instance.isUidActive(Process.SYSTEM_UID));
+
+        assertTrue(instance.isUidActiveSynced(UID_1));
+        assertTrue(instance.isUidActiveSynced(UID_2));
+        assertTrue(instance.isUidActiveSynced(Process.SYSTEM_UID));
+
+        assertFalse(instance.isUidInForeground(UID_1));
+        assertFalse(instance.isUidInForeground(UID_2));
+        assertTrue(instance.isUidInForeground(Process.SYSTEM_UID));
+
     }
 
     @Test
     public void testExempt() throws Exception {
-        final ForceAppStandbyTrackerTestable instance = newInstance();
+        final AppStateTrackerTestable instance = newInstance();
         callStart(instance);
 
         assertFalse(instance.isForceAllAppsStandbyEnabled());
@@ -610,7 +658,7 @@
     }
 
     public void loadPersistedAppOps() throws Exception {
-        final ForceAppStandbyTrackerTestable instance = newInstance();
+        final AppStateTrackerTestable instance = newInstance();
 
         final List<PackageOps> ops = new ArrayList<>();
 
@@ -620,7 +668,7 @@
                 AppOpsManager.OP_ACCESS_NOTIFICATIONS,
                 AppOpsManager.MODE_IGNORED, 0, 0, 0, 0, null));
         entries.add(new AppOpsManager.OpEntry(
-                ForceAppStandbyTracker.TARGET_OP,
+                AppStateTracker.TARGET_OP,
                 AppOpsManager.MODE_IGNORED, 0, 0, 0, 0, null));
 
         ops.add(new PackageOps(PACKAGE_1, UID_1, entries));
@@ -628,7 +676,7 @@
         //--------------------------------------------------
         entries = new ArrayList<>();
         entries.add(new AppOpsManager.OpEntry(
-                ForceAppStandbyTracker.TARGET_OP,
+                AppStateTracker.TARGET_OP,
                 AppOpsManager.MODE_IGNORED, 0, 0, 0, 0, null));
 
         ops.add(new PackageOps(PACKAGE_2, UID_2, entries));
@@ -636,7 +684,7 @@
         //--------------------------------------------------
         entries = new ArrayList<>();
         entries.add(new AppOpsManager.OpEntry(
-                ForceAppStandbyTracker.TARGET_OP,
+                AppStateTracker.TARGET_OP,
                 AppOpsManager.MODE_ALLOWED, 0, 0, 0, 0, null));
 
         ops.add(new PackageOps(PACKAGE_1, UID_10_1, entries));
@@ -644,7 +692,7 @@
         //--------------------------------------------------
         entries = new ArrayList<>();
         entries.add(new AppOpsManager.OpEntry(
-                ForceAppStandbyTracker.TARGET_OP,
+                AppStateTracker.TARGET_OP,
                 AppOpsManager.MODE_IGNORED, 0, 0, 0, 0, null));
         entries.add(new AppOpsManager.OpEntry(
                 AppOpsManager.OP_ACCESS_NOTIFICATIONS,
@@ -677,10 +725,10 @@
 
     @Test
     public void testPowerSaveListener() throws Exception {
-        final ForceAppStandbyTrackerTestable instance = newInstance();
+        final AppStateTrackerTestable instance = newInstance();
         callStart(instance);
 
-        ForceAppStandbyTracker.Listener l = mock(ForceAppStandbyTracker.Listener.class);
+        AppStateTracker.Listener l = mock(AppStateTracker.Listener.class);
         instance.addListener(l);
 
         // Power save on.
@@ -720,10 +768,10 @@
 
     @Test
     public void testAllListeners() throws Exception {
-        final ForceAppStandbyTrackerTestable instance = newInstance();
+        final AppStateTrackerTestable instance = newInstance();
         callStart(instance);
 
-        ForceAppStandbyTracker.Listener l = mock(ForceAppStandbyTracker.Listener.class);
+        AppStateTracker.Listener l = mock(AppStateTracker.Listener.class);
         instance.addListener(l);
 
         // -------------------------------------------------------------------------
@@ -1031,12 +1079,14 @@
 
     @Test
     public void testUserRemoved() throws Exception {
-        final ForceAppStandbyTrackerTestable instance = newInstance();
+        final AppStateTrackerTestable instance = newInstance();
         callStart(instance);
 
         mIUidObserver.onUidActive(UID_1);
         mIUidObserver.onUidActive(UID_10_1);
 
+        waitUntilMainHandlerDrain();
+
         setAppOps(UID_2, PACKAGE_2, true);
         setAppOps(UID_10_2, PACKAGE_2, true);
 
@@ -1064,7 +1114,7 @@
         // This is a small battery device
         mIsSmallBatteryDevice = true;
 
-        final ForceAppStandbyTrackerTestable instance = newInstance();
+        final AppStateTrackerTestable instance = newInstance();
         callStart(instance);
         assertFalse(instance.isForceAllAppsStandbyEnabled());
 
@@ -1090,7 +1140,7 @@
         // Not a small battery device, so plugged in status should not affect forced app standby
         mIsSmallBatteryDevice = false;
 
-        final ForceAppStandbyTrackerTestable instance = newInstance();
+        final AppStateTrackerTestable instance = newInstance();
         callStart(instance);
         assertFalse(instance.isForceAllAppsStandbyEnabled());
 
@@ -1139,7 +1189,7 @@
 
     private void checkAnyAppIdUnwhitelisted(int[] prevArray, int[] newArray, boolean expected) {
         assertEquals("Input: " + Arrays.toString(prevArray) + " " + Arrays.toString(newArray),
-                expected, ForceAppStandbyTracker.isAnyAppIdUnwhitelisted(prevArray, newArray));
+                expected, AppStateTracker.isAnyAppIdUnwhitelisted(prevArray, newArray));
 
         // Also test isAnyAppIdUnwhitelistedSlow.
         assertEquals("Input: " + Arrays.toString(prevArray) + " " + Arrays.toString(newArray),
@@ -1171,7 +1221,7 @@
             final int[] array2 = makeRandomArray();
 
             final boolean expected = isAnyAppIdUnwhitelistedSlow(array1, array2);
-            final boolean actual = ForceAppStandbyTracker.isAnyAppIdUnwhitelisted(array1, array2);
+            final boolean actual = AppStateTracker.isAnyAppIdUnwhitelisted(array1, array2);
 
             assertEquals("Input: " + Arrays.toString(array1) + " " + Arrays.toString(array2),
                     expected, actual);
diff --git a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
index 184e8de..e1b4422 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
@@ -104,6 +104,7 @@
 import android.os.PowerManagerInternal;
 import android.os.PowerSaveState;
 import android.os.RemoteException;
+import android.os.SimpleClock;
 import android.os.UserHandle;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.runner.AndroidJUnit4;
@@ -118,7 +119,6 @@
 import android.util.Log;
 import android.util.Pair;
 import android.util.RecurrenceRule;
-import android.util.TrustedTime;
 
 import com.android.internal.telephony.PhoneConstants;
 import com.android.internal.util.test.BroadcastInterceptingContext;
@@ -158,6 +158,7 @@
 import java.time.Instant;
 import java.time.Period;
 import java.time.ZoneId;
+import java.time.ZoneOffset;
 import java.time.ZonedDateTime;
 import java.util.Arrays;
 import java.util.Calendar;
@@ -215,7 +216,6 @@
     private @Mock IActivityManager mActivityManager;
     private @Mock INetworkStatsService mStatsService;
     private @Mock INetworkManagementService mNetworkManager;
-    private @Mock TrustedTime mTime;
     private @Mock IConnectivityManager mConnManager;
     private @Mock NotificationManager mNotifManager;
     private @Mock PackageManager mPackageManager;
@@ -267,6 +267,13 @@
 
     public final @Rule NetPolicyMethodRule mNetPolicyXmlRule = new NetPolicyMethodRule();
 
+    private final Clock mClock = new SimpleClock(ZoneOffset.UTC) {
+        @Override
+        public long millis() {
+            return currentTimeMillis();
+        }
+    };
+
     private void registerLocalServices() {
         addLocalServiceMock(DeviceIdleController.LocalService.class);
 
@@ -341,7 +348,7 @@
 
         mFutureIntent = newRestrictBackgroundChangedFuture();
         mService = new NetworkPolicyManagerService(mServiceContext, mActivityManager, mStatsService,
-                mNetworkManager, mIpm, mTime, mPolicyDir, true);
+                mNetworkManager, mIpm, mClock, mPolicyDir, true);
         mService.bindConnectivityManager(mConnManager);
         mPolicyListener = new NetworkPolicyListenerAnswer(mService);
 
@@ -370,7 +377,6 @@
         when(mPackageManager.getPackagesForUid(UID_A)).thenReturn(new String[] {PKG_NAME_A});
         when(mNetworkManager.isBandwidthControlEnabled()).thenReturn(true);
         when(mNetworkManager.setDataSaverModeEnabled(anyBoolean())).thenReturn(true);
-        expectCurrentTime();
 
         // Prepare NPMS.
         mService.systemReady(mService.networkScoreAndNetworkManagementServiceReady());
@@ -940,7 +946,6 @@
         // which means we shouldn't push limit to interface.
         state = new NetworkState[] { buildWifi() };
         when(mConnManager.getAllNetworkState()).thenReturn(state);
-        expectCurrentTime();
 
         mPolicyListener.expect().onMeteredIfacesChanged(any());
         mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION));
@@ -949,7 +954,6 @@
         // now change cycle to be on 15th, and test in early march, to verify we
         // pick cycle day in previous month.
         when(mConnManager.getAllNetworkState()).thenReturn(state);
-        expectCurrentTime();
 
         // pretend that 512 bytes total have happened
         stats = new NetworkStats(getElapsedRealtime(), 1)
@@ -996,7 +1000,6 @@
         final long start = parseTime("2015-11-01T00:00Z");
         final long end = parseTime("2015-11-07T00:00Z");
         setCurrentTimeMillis(end);
-        expectCurrentTime();
 
         // Normal usage means no notification
         {
@@ -1096,7 +1099,6 @@
         final long start = parseTime("2015-11-01T00:00Z");
         final long end = parseTime("2015-11-07T00:00Z");
         setCurrentTimeMillis(end);
-        expectCurrentTime();
 
         // Using 20% data in 20% time is normal
         {
@@ -1139,7 +1141,6 @@
                 .addIfaceValues(TEST_IFACE, 0L, 0L, 0L, 0L);
 
         {
-            expectCurrentTime();
             when(mConnManager.getAllNetworkState()).thenReturn(state);
             when(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15,
                     currentTimeMillis())).thenReturn(stats.getTotalBytes());
@@ -1474,14 +1475,6 @@
         return new NetworkState(info, prop, networkCapabilities, null, null, TEST_SSID);
     }
 
-    private void expectCurrentTime() throws Exception {
-        when(mTime.forceRefresh()).thenReturn(false);
-        when(mTime.hasCache()).thenReturn(true);
-        when(mTime.currentTimeMillis()).thenReturn(currentTimeMillis());
-        when(mTime.getCacheAge()).thenReturn(0L);
-        when(mTime.getCacheCertainty()).thenReturn(0L);
-    }
-
     private void expectHasInternetPermission(int uid, boolean hasIt) throws Exception {
         when(mIpm.checkUidPermission(Manifest.permission.INTERNET, uid)).thenReturn(
                 hasIt ? PackageManager.PERMISSION_GRANTED : PackageManager.PERMISSION_DENIED);
diff --git a/services/tests/servicestests/src/com/android/server/WatchdogDiagnosticsTest.java b/services/tests/servicestests/src/com/android/server/WatchdogDiagnosticsTest.java
new file mode 100644
index 0000000..6e76b67
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/WatchdogDiagnosticsTest.java
@@ -0,0 +1,189 @@
+/*
+ * 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;
+
+import static org.junit.Assert.assertEquals;
+
+import android.support.test.runner.AndroidJUnit4;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Unit tests for {@link WatchdogDiagnostics}
+ */
+@RunWith(AndroidJUnit4.class)
+public class WatchdogDiagnosticsTest {
+
+    private static class TestThread1 extends Thread {
+        Object lock1;
+        Object lock2;
+        volatile boolean inB = false;
+
+        public TestThread1(Object lock1, Object lock2) {
+            super("TestThread1");
+            this.lock1 = lock1;
+            this.lock2 = lock2;
+        }
+
+        @Override
+        public void run() {
+            a();
+        }
+
+        private void a() {
+            synchronized(lock1) {
+                b();
+            }
+        }
+
+        private void b() {
+            inB = true;
+            synchronized(lock2) {
+                // Nothing.
+            }
+        }
+    }
+
+    private static class TestThread2 extends Thread {
+        Object lock1;
+        Object lock2;
+        volatile boolean inY = false;
+
+        public TestThread2(Object lock1, Object lock2) {
+            super("TestThread2");
+            this.lock1 = lock1;
+            this.lock2 = lock2;
+        }
+
+        @Override
+        public void run() {
+            x();
+        }
+
+        private void x() {
+            synchronized(lock1) {
+                y();
+            }
+        }
+
+        private void y() {
+            synchronized(lock2) {
+                inY = true;
+                try {
+                    lock2.wait();
+                } catch (Exception exc) {
+                    throw new RuntimeException(exc);
+                }
+            }
+        }
+    }
+
+    @Test
+    public void printAnnotatedStack() throws Exception {
+        // Preparation.
+
+        Object heldLock1 = new Object();
+        Object heldLock2 = 0;
+        Object waitLock = "123";
+
+        TestThread1 thread1 = new TestThread1(heldLock1, heldLock2);
+        TestThread2 thread2 = new TestThread2(heldLock2, waitLock);
+
+        // Start the second thread, ensure it grabs heldLock2.
+        thread2.start();
+        while(!thread2.inY) {
+            Thread.yield();
+        }
+
+        // Start the first thread, ensure it made progress.
+        thread1.start();
+        while(!thread1.inB) {
+            Thread.yield();
+        }
+
+        // Now wait till both are no longer in runnable state.
+        while (thread1.getState() == Thread.State.RUNNABLE) {
+            Thread.yield();
+        }
+        while (thread2.getState() == Thread.State.RUNNABLE) {
+            Thread.yield();
+        }
+
+        // Now do the test.
+        StringWriter stringBuffer = new StringWriter();
+        PrintWriter print = new PrintWriter(stringBuffer, true);
+
+        {
+            WatchdogDiagnostics.printAnnotatedStack(thread1, print);
+
+            String output = stringBuffer.toString();
+            String expected =
+                    "TestThread1 annotated stack trace:\n" +
+                    "    at com.android.server.WatchdogDiagnosticsTest$TestThread1.b(" +
+                            "WatchdogDiagnosticsTest.java:59)\n" +
+                    "    - waiting to lock <HASH> (a java.lang.Integer)\n" +
+                    "    at com.android.server.WatchdogDiagnosticsTest$TestThread1.a(" +
+                            "WatchdogDiagnosticsTest.java:53)\n" +
+                    "    - locked <HASH> (a java.lang.Object)\n" +
+                    "    at com.android.server.WatchdogDiagnosticsTest$TestThread1.run(" +
+                            "WatchdogDiagnosticsTest.java:48)\n";
+            assertEquals(expected, filterHashes(output));
+        }
+
+        stringBuffer.getBuffer().setLength(0);
+
+        {
+            WatchdogDiagnostics.printAnnotatedStack(thread2, print);
+
+            String output = stringBuffer.toString();
+            String expected =
+                    "TestThread2 annotated stack trace:\n" +
+                    "    at java.lang.Object.wait(Native Method)\n" +
+                    "    at com.android.server.WatchdogDiagnosticsTest$TestThread2.y(" +
+                            "WatchdogDiagnosticsTest.java:91)\n" +
+                    "    - locked <HASH> (a java.lang.String)\n" +
+                    "    at com.android.server.WatchdogDiagnosticsTest$TestThread2.x(" +
+                            "WatchdogDiagnosticsTest.java:83)\n" +
+                    "    - locked <HASH> (a java.lang.Integer)\n" +
+                    "    at com.android.server.WatchdogDiagnosticsTest$TestThread2.run(" +
+                            "WatchdogDiagnosticsTest.java:78)\n";
+            assertEquals(expected, filterHashes(output));
+        }
+
+        // Let the threads finish.
+        synchronized (waitLock) {
+            waitLock.notifyAll();
+        }
+
+        thread1.join();
+        thread2.join();
+    }
+
+    /**
+     * A filter function that removes hash codes (which will change between tests and cannot be
+     * controlled.)
+     * <p>
+     * Note: leaves "<HASH>" to indicate that something was replaced.
+     */
+    private static String filterHashes(String t) {
+        return t.replaceAll("<0x[0-9a-f]{8}>", "<HASH>");
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/MagnificationGestureHandlerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/MagnificationGestureHandlerTest.java
index 07262e1..23fe0ff 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/MagnificationGestureHandlerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/MagnificationGestureHandlerTest.java
@@ -34,7 +34,6 @@
 
 import android.annotation.NonNull;
 import android.content.Context;
-import android.os.Handler;
 import android.os.Message;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.runner.AndroidJUnit4;
@@ -49,9 +48,7 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
-import java.util.concurrent.CompletableFuture;
 import java.util.function.IntConsumer;
-import java.util.function.Supplier;
 
 
 /**
@@ -283,6 +280,19 @@
         verify(mMgh.getNext(), times(2)).onMotionEvent(any(), any(), anyInt());
     }
 
+    @Test
+    public void testTripleTapAndHold_zoomsImmediately() {
+        assertZoomsImmediatelyOnSwipeFrom(STATE_2TAPS);
+        assertZoomsImmediatelyOnSwipeFrom(STATE_SHORTCUT_TRIGGERED);
+    }
+
+    private void assertZoomsImmediatelyOnSwipeFrom(int state) {
+        goFromStateIdleTo(state);
+        swipeAndHold();
+        assertIn(STATE_DRAGGING_TMP);
+        returnToNormalFrom(STATE_DRAGGING_TMP);
+    }
+
     private void assertTransition(int fromState, Runnable transitionAction, int toState) {
         goFromStateIdleTo(fromState);
         transitionAction.run();
@@ -339,11 +349,13 @@
                 check(tapCount() == 2, state);
             } break;
             case STATE_DRAGGING: {
+                check(isZoomed(), state);
                 check(mMgh.mCurrentState == mMgh.mViewportDraggingState,
                         state);
                 check(mMgh.mViewportDraggingState.mZoomedInBeforeDrag, state);
             } break;
             case STATE_DRAGGING_TMP: {
+                check(isZoomed(), state);
                 check(mMgh.mCurrentState == mMgh.mViewportDraggingState,
                         state);
                 check(!mMgh.mViewportDraggingState.mZoomedInBeforeDrag, state);
@@ -353,11 +365,13 @@
                 check(!isZoomed(), state);
             } break;
             case STATE_PANNING: {
+                check(isZoomed(), state);
                 check(mMgh.mCurrentState == mMgh.mPanningScalingState,
                         state);
                 check(!mMgh.mPanningScalingState.mScaling, state);
             } break;
             case STATE_SCALING_AND_PANNING: {
+                check(isZoomed(), state);
                 check(mMgh.mCurrentState == mMgh.mPanningScalingState,
                         state);
                 check(mMgh.mPanningScalingState.mScaling, state);
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/am/PendingRemoteAnimationRegistryTest.java b/services/tests/servicestests/src/com/android/server/am/PendingRemoteAnimationRegistryTest.java
new file mode 100644
index 0000000..2baf995
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/am/PendingRemoteAnimationRegistryTest.java
@@ -0,0 +1,103 @@
+/*
+ * 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 org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import android.annotation.Nullable;
+import android.app.ActivityOptions;
+import android.os.Handler;
+import android.platform.test.annotations.Presubmit;
+import android.support.test.filters.FlakyTest;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.util.ArrayMap;
+import android.view.RemoteAnimationAdapter;
+
+import com.android.server.testutils.OffsettableClock;
+import com.android.server.testutils.TestHandler;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+/**
+ * atest PendingRemoteAnimationRegistryTest
+ */
+@SmallTest
+@Presubmit
+@FlakyTest
+@RunWith(AndroidJUnit4.class)
+public class PendingRemoteAnimationRegistryTest extends ActivityTestsBase {
+
+    @Mock RemoteAnimationAdapter mAdapter;
+    private PendingRemoteAnimationRegistry mRegistry;
+    private final OffsettableClock mClock = new OffsettableClock.Stopped();
+    private TestHandler mHandler;
+    private ActivityManagerService mService;
+
+    @Before
+    public void setUp() throws Exception {
+        super.setUp();
+        MockitoAnnotations.initMocks(this);
+        mService = createActivityManagerService();
+        mService.mHandlerThread.getThreadHandler().runWithScissors(() -> {
+            mHandler = new TestHandler(null, mClock);
+        }, 0);
+        mRegistry = new PendingRemoteAnimationRegistry(mService, mHandler);
+    }
+
+    @Test
+    public void testOverrideActivityOptions() {
+        mRegistry.addPendingAnimation("com.android.test", mAdapter);
+        ActivityOptions opts = ActivityOptions.makeBasic();
+        opts = mRegistry.overrideOptionsIfNeeded("com.android.test", opts);
+        assertEquals(mAdapter, opts.getRemoteAnimationAdapter());
+    }
+
+    @Test
+    public void testOverrideActivityOptions_null() {
+        mRegistry.addPendingAnimation("com.android.test", mAdapter);
+        final ActivityOptions opts = mRegistry.overrideOptionsIfNeeded("com.android.test", null);
+        assertNotNull(opts);
+        assertEquals(mAdapter, opts.getRemoteAnimationAdapter());
+    }
+
+    @Test
+    public void testTimeout() {
+        mRegistry.addPendingAnimation("com.android.test", mAdapter);
+        mClock.fastForward(5000);
+        mHandler.timeAdvance();
+        assertNull(mRegistry.overrideOptionsIfNeeded("com.android.test", null));
+    }
+
+    @Test
+    public void testTimeout_overridenEntry() {
+        mRegistry.addPendingAnimation("com.android.test", mAdapter);
+        mClock.fastForward(2500);
+        mHandler.timeAdvance();
+        mRegistry.addPendingAnimation("com.android.test", mAdapter);
+        mClock.fastForward(1000);
+        mHandler.timeAdvance();
+        final ActivityOptions opts = mRegistry.overrideOptionsIfNeeded("com.android.test", null);
+        assertEquals(mAdapter, opts.getRemoteAnimationAdapter());
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
index 00e27c9..ab0bfefb 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
@@ -447,5 +447,8 @@
             return new TransferOwnershipMetadataManager(
                     new TransferOwnershipMetadataManagerTest.MockInjector());
         }
+
+        @Override
+        public void runCryptoSelfTest() {}
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/SystemUpdatePolicyTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/SystemUpdatePolicyTest.java
index 98c428d..091d9bd 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/SystemUpdatePolicyTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/SystemUpdatePolicyTest.java
@@ -45,6 +45,7 @@
 import java.time.LocalDate;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.concurrent.TimeUnit;
 
 /**
  * Unit tests for {@link android.app.admin.SystemUpdatePolicy}.
@@ -253,6 +254,147 @@
 
     }
 
+    @Test
+    public void testInstallationOptionWithoutFreeze() {
+        // Also duplicated at com.google.android.gts.deviceowner.SystemUpdatePolicyTest
+        final long millis_2018_01_01 = TimeUnit.SECONDS.toMillis(1514764800);
+
+        SystemUpdatePolicy p = SystemUpdatePolicy.createAutomaticInstallPolicy();
+        assertInstallationOption(SystemUpdatePolicy.TYPE_INSTALL_AUTOMATIC, Long.MAX_VALUE,
+                millis_2018_01_01, p);
+
+        p = SystemUpdatePolicy.createPostponeInstallPolicy();
+        assertInstallationOption(SystemUpdatePolicy.TYPE_POSTPONE, Long.MAX_VALUE,
+                millis_2018_01_01, p);
+
+        p = SystemUpdatePolicy.createWindowedInstallPolicy(120, 180); // 2:00 - 3:00
+        // 00:00 is two hours before the next window
+        assertInstallationOption(SystemUpdatePolicy.TYPE_PAUSE, TimeUnit.HOURS.toMillis(2),
+                millis_2018_01_01, p);
+        // 02:00 is within the current maintenance window, and one hour until the window ends
+        assertInstallationOption(
+                SystemUpdatePolicy.TYPE_INSTALL_AUTOMATIC, TimeUnit.HOURS.toMillis(1),
+                millis_2018_01_01 + TimeUnit.HOURS.toMillis(2), p);
+        // 04:00 is 22 hours from the window next day
+        assertInstallationOption(SystemUpdatePolicy.TYPE_PAUSE, TimeUnit.HOURS.toMillis(22),
+                millis_2018_01_01 + TimeUnit.HOURS.toMillis(4), p);
+
+        p = SystemUpdatePolicy.createWindowedInstallPolicy(22 * 60, 2 * 60); // 22:00 - 2:00
+        // 21:00 is one hour from the next window
+        assertInstallationOption(SystemUpdatePolicy.TYPE_PAUSE, TimeUnit.HOURS.toMillis(1),
+                millis_2018_01_01 + TimeUnit.HOURS.toMillis(21), p);
+        // 00:00 is two hours from the end of current window
+        assertInstallationOption(
+                SystemUpdatePolicy.TYPE_INSTALL_AUTOMATIC, TimeUnit.HOURS.toMillis(2),
+                millis_2018_01_01, p);
+        // 03:00 is 22 hours from the window today
+        assertInstallationOption(SystemUpdatePolicy.TYPE_PAUSE, TimeUnit.HOURS.toMillis(19),
+                millis_2018_01_01 + TimeUnit.HOURS.toMillis(3), p);
+    }
+
+    @Test
+    public void testInstallationOptionWithFreeze() throws Exception {
+        final long millis_2016_02_29 = TimeUnit.SECONDS.toMillis(1456704000);
+        final long millis_2017_01_31 = TimeUnit.SECONDS.toMillis(1485820800);
+        final long millis_2017_02_28 = TimeUnit.SECONDS.toMillis(1488240000);
+        final long millis_2018_01_01 = TimeUnit.SECONDS.toMillis(1514764800);
+        final long millis_2018_08_01 = TimeUnit.SECONDS.toMillis(1533081600);
+
+        SystemUpdatePolicy p = SystemUpdatePolicy.createAutomaticInstallPolicy();
+        setFreezePeriods(p, "01-01", "01-31");
+        // Inside a freeze period
+        assertInstallationOption(
+                SystemUpdatePolicy.TYPE_PAUSE, TimeUnit.DAYS.toMillis(31),
+                millis_2018_01_01, p);
+        // Device is outside freeze between 2/28 to 12/31 inclusive
+        assertInstallationOption(
+                SystemUpdatePolicy.TYPE_INSTALL_AUTOMATIC, TimeUnit.DAYS.toMillis(307),
+                millis_2017_02_28, p);
+
+        // Freeze period contains leap day Feb 29
+        p = SystemUpdatePolicy.createPostponeInstallPolicy();
+        setFreezePeriods(p, "02-01", "03-15");
+        // Freezed until 3/31, note 2016 is a leap year
+        assertInstallationOption(SystemUpdatePolicy.TYPE_PAUSE, TimeUnit.DAYS.toMillis(16),
+                millis_2016_02_29, p);
+        // Freezed until 3/31, note 2017 is not a leap year
+        assertInstallationOption(SystemUpdatePolicy.TYPE_PAUSE, TimeUnit.DAYS.toMillis(16),
+                millis_2017_02_28, p);
+        // Next freeze is 2018/2/1
+        assertInstallationOption(SystemUpdatePolicy.TYPE_POSTPONE, TimeUnit.DAYS.toMillis(31),
+                millis_2018_01_01, p);
+
+        // Freeze period start on or right after leap day
+        p = SystemUpdatePolicy.createAutomaticInstallPolicy();
+        setFreezePeriods(p, "03-01", "03-31");
+        assertInstallationOption(
+                SystemUpdatePolicy.TYPE_INSTALL_AUTOMATIC, TimeUnit.DAYS.toMillis(1),
+                millis_2016_02_29, p);
+        assertInstallationOption(
+                SystemUpdatePolicy.TYPE_INSTALL_AUTOMATIC, TimeUnit.DAYS.toMillis(1),
+                millis_2017_02_28, p);
+        setFreezePeriods(p, "02-28", "03-15");
+        assertInstallationOption(
+                SystemUpdatePolicy.TYPE_PAUSE, TimeUnit.DAYS.toMillis(16),
+                millis_2016_02_29, p);
+        assertInstallationOption(
+                SystemUpdatePolicy.TYPE_PAUSE, TimeUnit.DAYS.toMillis(16),
+                millis_2017_02_28, p);
+
+        // Freeze period end on or right after leap day
+        p = SystemUpdatePolicy.createAutomaticInstallPolicy();
+        setFreezePeriods(p, "02-01", "02-28");
+        assertInstallationOption(
+                SystemUpdatePolicy.TYPE_PAUSE, TimeUnit.DAYS.toMillis(1),
+                millis_2016_02_29, p);
+        assertInstallationOption(
+                SystemUpdatePolicy.TYPE_PAUSE, TimeUnit.DAYS.toMillis(1),
+                millis_2017_02_28, p);
+        p = SystemUpdatePolicy.createAutomaticInstallPolicy();
+        setFreezePeriods(p, "02-01", "03-01");
+        assertInstallationOption(
+                SystemUpdatePolicy.TYPE_PAUSE, TimeUnit.DAYS.toMillis(2),
+                millis_2016_02_29, p);
+        assertInstallationOption(
+                SystemUpdatePolicy.TYPE_PAUSE, TimeUnit.DAYS.toMillis(2),
+                millis_2017_02_28, p);
+
+        // Freeze period with maintenance window
+        p = SystemUpdatePolicy.createWindowedInstallPolicy(23 * 60, 1 * 60); // 23:00 - 1:00
+        setFreezePeriods(p, "02-01", "02-28");
+        // 00:00 is within the current window, outside freeze period
+        assertInstallationOption(
+                SystemUpdatePolicy.TYPE_INSTALL_AUTOMATIC, TimeUnit.HOURS.toMillis(1),
+                millis_2018_01_01, p);
+        // Last day of feeze period, which ends in 22 hours
+        assertInstallationOption(
+                SystemUpdatePolicy.TYPE_PAUSE, TimeUnit.HOURS.toMillis(22),
+                millis_2017_02_28 + TimeUnit.HOURS.toMillis(2), p);
+        // Last day before the next freeze, and within window
+        assertInstallationOption(
+                SystemUpdatePolicy.TYPE_INSTALL_AUTOMATIC, TimeUnit.HOURS.toMillis(1),
+                millis_2017_01_31, p);
+        // Last day before the next freeze, and there is still a partial maintenance window before
+        // the freeze.
+        assertInstallationOption(
+                SystemUpdatePolicy.TYPE_PAUSE, TimeUnit.HOURS.toMillis(19),
+                millis_2017_01_31 + TimeUnit.HOURS.toMillis(4), p);
+
+        // Two freeze periods
+        p = SystemUpdatePolicy.createAutomaticInstallPolicy();
+        setFreezePeriods(p, "05-01", "06-01", "12-01", "01-31");
+        // automatic policy for August, September, November and December
+        assertInstallationOption(
+                SystemUpdatePolicy.TYPE_INSTALL_AUTOMATIC, TimeUnit.DAYS.toMillis(122),
+                millis_2018_08_01, p);
+    }
+
+    private void assertInstallationOption(int expectedType, long expectedTime, long now,
+            SystemUpdatePolicy p) {
+        assertEquals(expectedType, p.getInstallationOptionAt(now).getType());
+        assertEquals(expectedTime, p.getInstallationOptionAt(now).getEffectiveTime());
+    }
+
     private void testFreezePeriodsSucceeds(String...dates) throws Exception {
         SystemUpdatePolicy p = SystemUpdatePolicy.createPostponeInstallPolicy();
         setFreezePeriods(p, dates);
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java
index ce5ee13..e40e3a4 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java
@@ -275,7 +275,7 @@
     }
 
     @Test
-    public void run_sendsEncryptedKeysIfAvailableToSync() throws Exception {
+    public void run_sendsEncryptedKeysIfAvailableToSync_withRawPublicKey() throws Exception {
         mRecoverableKeyStoreDb.setRecoveryServicePublicKey(
                 TEST_USER_ID, TEST_RECOVERY_AGENT_UID, mKeyPair.getPublic());
 
@@ -323,6 +323,26 @@
     }
 
     @Test
+    public void run_sendsEncryptedKeysIfAvailableToSync_withCertPath() throws Exception {
+        mRecoverableKeyStoreDb.setRecoveryServiceCertPath(
+                TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TestData.CERT_PATH_1);
+        mRecoverableKeyStoreDb.setServerParams(
+                TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_VAULT_HANDLE);
+        when(mSnapshotListenersStorage.hasListener(TEST_RECOVERY_AGENT_UID)).thenReturn(true);
+        addApplicationKey(TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_APP_KEY_ALIAS);
+
+        mKeySyncTask.run();
+
+        KeyChainSnapshot keyChainSnapshot = mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID);
+        verify(mSnapshotListenersStorage).recoverySnapshotAvailable(TEST_RECOVERY_AGENT_UID);
+        List<WrappedApplicationKey> applicationKeys = keyChainSnapshot.getWrappedApplicationKeys();
+        assertThat(applicationKeys).hasSize(1);
+        assertThat(keyChainSnapshot.getTrustedHardwarePublicKey())
+                .isEqualTo(SecureBox.encodePublicKey(
+                        TestData.CERT_PATH_1.getCertificates().get(0).getPublicKey()));
+    }
+
+    @Test
     public void run_setsCorrectSnapshotVersion() throws Exception {
         mRecoverableKeyStoreDb.setRecoveryServicePublicKey(
                 TEST_USER_ID, TEST_RECOVERY_AGENT_UID, mKeyPair.getPublic());
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/OWNERS b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/OWNERS
new file mode 100644
index 0000000..bb487fb
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/OWNERS
@@ -0,0 +1,4 @@
+aseemk@google.com
+bozhu@google.com
+dementyev@google.com
+robertberry@google.com
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/PlatformKeyManagerTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/PlatformKeyManagerTest.java
index f9ffccd..0f0e3f3 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/PlatformKeyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/PlatformKeyManagerTest.java
@@ -255,6 +255,9 @@
         when(mKeyStoreProxy
                 .containsAlias("com.android.server.locksettings.recoverablekeystore/"
                         + "platform/42/1/decrypt")).thenReturn(true);
+        when(mKeyStoreProxy
+                .containsAlias("com.android.server.locksettings.recoverablekeystore/"
+                        + "platform/42/1/encrypt")).thenReturn(true);
 
         mPlatformKeyManager.getDecryptKey(USER_ID_FIXTURE);
 
@@ -264,6 +267,56 @@
     }
 
     @Test
+    public void getDecryptKey_generatesNewKeyIfOldDecryptKeyWasRemoved() throws Exception {
+        when(mKeyStoreProxy
+                .containsAlias("com.android.server.locksettings.recoverablekeystore/"
+                        + "platform/42/1/encrypt")).thenReturn(true);
+        when(mKeyStoreProxy
+                .containsAlias("com.android.server.locksettings.recoverablekeystore/"
+                        + "platform/42/1/decrypt")).thenReturn(false); // was removed
+        when(mKeyStoreProxy
+                .containsAlias("com.android.server.locksettings.recoverablekeystore/"
+                        + "platform/42/2/encrypt")).thenReturn(true); // new version is available
+        when(mKeyStoreProxy
+                .containsAlias("com.android.server.locksettings.recoverablekeystore/"
+                        + "platform/42/2/decrypt")).thenReturn(true);
+
+        mPlatformKeyManager.getDecryptKey(USER_ID_FIXTURE);
+
+        verify(mKeyStoreProxy).containsAlias(
+                eq("com.android.server.locksettings.recoverablekeystore/platform/42/1/decrypt"));
+        // Attempt to get regenerated key.
+        verify(mKeyStoreProxy).getKey(
+                eq("com.android.server.locksettings.recoverablekeystore/platform/42/2/decrypt"),
+                any());
+    }
+
+    @Test
+    public void getDecryptKey_generatesNewKeyIfOldEncryptKeyWasRemoved() throws Exception {
+        when(mKeyStoreProxy
+                .containsAlias("com.android.server.locksettings.recoverablekeystore/"
+                        + "platform/42/1/encrypt")).thenReturn(false); // was removed
+        when(mKeyStoreProxy
+                .containsAlias("com.android.server.locksettings.recoverablekeystore/"
+                        + "platform/42/1/decrypt")).thenReturn(true);
+        when(mKeyStoreProxy
+                .containsAlias("com.android.server.locksettings.recoverablekeystore/"
+                        + "platform/42/2/encrypt")).thenReturn(true);
+        when(mKeyStoreProxy
+                .containsAlias("com.android.server.locksettings.recoverablekeystore/"
+                        + "platform/42/2/decrypt")).thenReturn(true);
+
+        mPlatformKeyManager.getDecryptKey(USER_ID_FIXTURE);
+
+        verify(mKeyStoreProxy).containsAlias(
+                eq("com.android.server.locksettings.recoverablekeystore/platform/42/1/encrypt"));
+        // Attempt to get regenerated key.
+        verify(mKeyStoreProxy).getKey(
+                eq("com.android.server.locksettings.recoverablekeystore/platform/42/2/decrypt"),
+                any());
+    }
+
+    @Test
     public void getEncryptKey_generatesNewKeyIfOldOneIsInvalid() throws Exception {
         doThrow(new UnrecoverableKeyException()).when(mKeyStoreProxy).getKey(
                 eq("com.android.server.locksettings.recoverablekeystore/platform/42/1/encrypt"),
@@ -274,7 +327,13 @@
                         + "platform/42/1/encrypt")).thenReturn(true);
         when(mKeyStoreProxy
                 .containsAlias("com.android.server.locksettings.recoverablekeystore/"
+                        + "platform/42/1/decrypt")).thenReturn(true);
+        when(mKeyStoreProxy
+                .containsAlias("com.android.server.locksettings.recoverablekeystore/"
                         + "platform/42/2/encrypt")).thenReturn(true);
+        when(mKeyStoreProxy
+                .containsAlias("com.android.server.locksettings.recoverablekeystore/"
+                        + "platform/42/2/decrypt")).thenReturn(true);
 
         mPlatformKeyManager.getEncryptKey(USER_ID_FIXTURE);
 
@@ -295,11 +354,16 @@
 
         when(mKeyStoreProxy
                 .containsAlias("com.android.server.locksettings.recoverablekeystore/"
-                        + "platform/42/1/decrypt")).thenReturn(false); // was removed.
-
+                        + "platform/42/1/encrypt")).thenReturn(true);
         when(mKeyStoreProxy
                 .containsAlias("com.android.server.locksettings.recoverablekeystore/"
-                        + "platform/42/2/decrypt")).thenReturn(true); // new version is available
+                        + "platform/42/1/decrypt")).thenReturn(true);
+        when(mKeyStoreProxy
+                .containsAlias("com.android.server.locksettings.recoverablekeystore/"
+                        + "platform/42/2/encrypt")).thenReturn(true);
+        when(mKeyStoreProxy
+                .containsAlias("com.android.server.locksettings.recoverablekeystore/"
+                        + "platform/42/2/decrypt")).thenReturn(true);
 
         mPlatformKeyManager.getDecryptKey(USER_ID_FIXTURE);
 
@@ -312,14 +376,45 @@
     }
 
     @Test
-    public void getEncryptKey_generatesNewKeyIfOldWasRemoved() throws Exception {
+    public void getEncryptKey_generatesNewKeyIfDecryptKeyIsUnrecoverable() throws Exception {
+        doThrow(new UnrecoverableKeyException()).when(mKeyStoreProxy).getKey(
+                eq("com.android.server.locksettings.recoverablekeystore/platform/42/1/decrypt"),
+                any());
         when(mKeyStoreProxy
                 .containsAlias("com.android.server.locksettings.recoverablekeystore/"
-                        + "platform/42/1/encrypt")).thenReturn(false); // was removed.
-
+                        + "platform/42/1/encrypt")).thenReturn(true);
+        when(mKeyStoreProxy
+                .containsAlias("com.android.server.locksettings.recoverablekeystore/"
+                        + "platform/42/1/decrypt")).thenReturn(false); // was removed
         when(mKeyStoreProxy
                 .containsAlias("com.android.server.locksettings.recoverablekeystore/"
                         + "platform/42/2/encrypt")).thenReturn(true); // new version is available
+        when(mKeyStoreProxy
+                .containsAlias("com.android.server.locksettings.recoverablekeystore/"
+                        + "platform/42/2/decrypt")).thenReturn(true);
+
+        mPlatformKeyManager.getEncryptKey(USER_ID_FIXTURE);
+
+        // Attempt to get regenerated key.
+        verify(mKeyStoreProxy).getKey(
+                eq("com.android.server.locksettings.recoverablekeystore/platform/42/2/encrypt"),
+                any());
+    }
+
+    @Test
+    public void getEncryptKey_generatesNewKeyIfOldDecryptKeyWasRemoved() throws Exception {
+        when(mKeyStoreProxy
+                .containsAlias("com.android.server.locksettings.recoverablekeystore/"
+                        + "platform/42/1/encrypt")).thenReturn(true);
+        when(mKeyStoreProxy
+                .containsAlias("com.android.server.locksettings.recoverablekeystore/"
+                        + "platform/42/1/decrypt")).thenReturn(false); // was removed
+        when(mKeyStoreProxy
+                .containsAlias("com.android.server.locksettings.recoverablekeystore/"
+                        + "platform/42/2/encrypt")).thenReturn(true); // new version is available
+        when(mKeyStoreProxy
+                .containsAlias("com.android.server.locksettings.recoverablekeystore/"
+                        + "platform/42/2/decrypt")).thenReturn(true);
 
         mPlatformKeyManager.getEncryptKey(USER_ID_FIXTURE);
 
@@ -332,10 +427,38 @@
     }
 
     @Test
-    public void getEncryptKey_getsEndryptKeyWithCorrectAlias() throws Exception {
+    public void getEncryptKey_generatesNewKeyIfOldEncryptKeyWasRemoved() throws Exception {
+        when(mKeyStoreProxy
+                .containsAlias("com.android.server.locksettings.recoverablekeystore/"
+                        + "platform/42/1/encrypt")).thenReturn(false); // was removed
+        when(mKeyStoreProxy
+                .containsAlias("com.android.server.locksettings.recoverablekeystore/"
+                        + "platform/42/1/decrypt")).thenReturn(true);
+        when(mKeyStoreProxy
+                .containsAlias("com.android.server.locksettings.recoverablekeystore/"
+                        + "platform/42/2/encrypt")).thenReturn(true);
+        when(mKeyStoreProxy
+                .containsAlias("com.android.server.locksettings.recoverablekeystore/"
+                        + "platform/42/2/decrypt")).thenReturn(true);
+
+        mPlatformKeyManager.getEncryptKey(USER_ID_FIXTURE);
+
+        verify(mKeyStoreProxy).containsAlias(
+                eq("com.android.server.locksettings.recoverablekeystore/platform/42/1/encrypt"));
+        // Attempt to get regenerated key.
+        verify(mKeyStoreProxy).getKey(
+                eq("com.android.server.locksettings.recoverablekeystore/platform/42/2/encrypt"),
+                any());
+    }
+
+    @Test
+    public void getEncryptKey_getsEncryptKeyWithCorrectAlias() throws Exception {
         when(mKeyStoreProxy
                 .containsAlias("com.android.server.locksettings.recoverablekeystore/"
                         + "platform/42/1/encrypt")).thenReturn(true);
+        when(mKeyStoreProxy
+                .containsAlias("com.android.server.locksettings.recoverablekeystore/"
+                        + "platform/42/1/decrypt")).thenReturn(true);
 
         mPlatformKeyManager.getEncryptKey(USER_ID_FIXTURE);
 
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 473a813..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
@@ -125,6 +125,7 @@
     private static final byte[] RECOVERY_RESPONSE_HEADER =
             "V1 reencrypted_recovery_key".getBytes(StandardCharsets.UTF_8);
     private static final String TEST_ALIAS = "nick";
+    private static final String TEST_ALIAS2 = "bob";
     private static final int RECOVERABLE_KEY_SIZE_BYTES = 32;
     private static final int GENERATION_ID = 1;
     private static final byte[] NONCE = getUtf8Bytes("nonce");
@@ -237,15 +238,81 @@
     }
 
     @Test
-    public void initRecoveryService_updatesShouldCreateSnapshot() throws Exception {
+    public void initRecoveryService_succeeds() throws Exception {
         int uid = Binder.getCallingUid();
         int userId = UserHandle.getCallingUserId();
-        // Sync is not needed.
+        long certSerial = 1000L;
+        mRecoverableKeyStoreDb.setShouldCreateSnapshot(userId, uid, false);
+
+        mRecoverableKeyStoreManager.initRecoveryService(ROOT_CERTIFICATE_ALIAS,
+                TestData.getCertXmlWithSerial(certSerial));
+
+        assertThat(mRecoverableKeyStoreDb.getShouldCreateSnapshot(userId, uid)).isTrue();
+        assertThat(mRecoverableKeyStoreDb.getRecoveryServiceCertPath(userId, uid)).isEqualTo(
+                TestData.CERT_PATH_1);
+        assertThat(mRecoverableKeyStoreDb.getRecoveryServiceCertSerial(userId, uid)).isEqualTo(
+                certSerial);
+        assertThat(mRecoverableKeyStoreDb.getRecoveryServicePublicKey(userId, uid)).isNull();
+    }
+
+    @Test
+    public void initRecoveryService_updatesWithLargerSerial() throws Exception {
+        int uid = Binder.getCallingUid();
+        int userId = UserHandle.getCallingUserId();
+        long certSerial = 1000L;
+
+        mRecoverableKeyStoreManager.initRecoveryService(ROOT_CERTIFICATE_ALIAS,
+                TestData.getCertXmlWithSerial(certSerial));
+        mRecoverableKeyStoreManager.initRecoveryService(ROOT_CERTIFICATE_ALIAS,
+                TestData.getCertXmlWithSerial(certSerial + 1));
+
+        assertThat(mRecoverableKeyStoreDb.getRecoveryServiceCertSerial(userId, uid))
+                .isEqualTo(certSerial + 1);
+    }
+
+    @Test
+    public void initRecoveryService_ignoresSmallerSerial() throws Exception {
+        int uid = Binder.getCallingUid();
+        int userId = UserHandle.getCallingUserId();
+        long certSerial = 1000L;
+
+        mRecoverableKeyStoreManager.initRecoveryService(ROOT_CERTIFICATE_ALIAS,
+                TestData.getCertXmlWithSerial(certSerial));
+        mRecoverableKeyStoreManager.initRecoveryService(ROOT_CERTIFICATE_ALIAS,
+                TestData.getCertXmlWithSerial(certSerial - 1));
+
+        assertThat(mRecoverableKeyStoreDb.getRecoveryServiceCertSerial(userId, uid))
+                .isEqualTo(certSerial);
+    }
+
+    @Test
+    public void initRecoveryService_ignoresTheSameSerial() throws Exception {
+        int uid = Binder.getCallingUid();
+        int userId = UserHandle.getCallingUserId();
+        long certSerial = 1000L;
+
+        mRecoverableKeyStoreManager.initRecoveryService(ROOT_CERTIFICATE_ALIAS,
+                TestData.getCertXmlWithSerial(certSerial));
+        mRecoverableKeyStoreDb.setShouldCreateSnapshot(userId, uid, false);
+        mRecoverableKeyStoreManager.initRecoveryService(ROOT_CERTIFICATE_ALIAS,
+                TestData.getCertXmlWithSerial(certSerial));
+
+        // If the second update succeeds, getShouldCreateSnapshot() will return true.
+        assertThat(mRecoverableKeyStoreDb.getShouldCreateSnapshot(userId, uid)).isFalse();
+    }
+
+    @Test
+    public void initRecoveryService_succeedsWithRawPublicKey() throws Exception {
+        int uid = Binder.getCallingUid();
+        int userId = UserHandle.getCallingUserId();
         mRecoverableKeyStoreDb.setShouldCreateSnapshot(userId, uid, false);
 
         mRecoverableKeyStoreManager.initRecoveryService(ROOT_CERTIFICATE_ALIAS, TEST_PUBLIC_KEY);
 
         assertThat(mRecoverableKeyStoreDb.getShouldCreateSnapshot(userId, uid)).isTrue();
+        assertThat(mRecoverableKeyStoreDb.getRecoveryServiceCertPath(userId, uid)).isNull();
+        assertThat(mRecoverableKeyStoreDb.getRecoveryServiceCertSerial(userId, uid)).isNull();
+        assertThat(mRecoverableKeyStoreDb.getRecoveryServicePublicKey(userId, uid)).isNotNull();
     }
 
     @Test
@@ -343,26 +410,6 @@
     }
 
     @Test
-    public void startRecoverySession_throwsIfBadKey() throws Exception {
-        try {
-            mRecoverableKeyStoreManager.startRecoverySession(
-                    TEST_SESSION_ID,
-                    getUtf8Bytes("0"),
-                    TEST_VAULT_PARAMS,
-                    TEST_VAULT_CHALLENGE,
-                    ImmutableList.of(
-                            new KeyChainProtectionParams(
-                                    TYPE_LOCKSCREEN,
-                                    UI_FORMAT_PASSWORD,
-                                    KeyDerivationParams.createSha256Params(TEST_SALT),
-                                    TEST_SECRET)));
-            fail("should have thrown");
-        } catch (ServiceSpecificException e) {
-            assertEquals("Not a valid X509 key", e.getMessage());
-        }
-    }
-
-    @Test
     public void startRecoverySession_throwsIfPublicKeysMismatch() throws Exception {
         byte[] vaultParams = TEST_VAULT_PARAMS.clone();
         vaultParams[1] ^= (byte) 1;  // Flip 1 bit
@@ -424,7 +471,7 @@
     }
 
     @Test
-    public void recoverKeys_throwsIfFailedToDecryptAnApplicationKey() throws Exception {
+    public void recoverKeys_throwsIfFailedToDecryptAllApplicationKeys() throws Exception {
         mRecoverableKeyStoreManager.startRecoverySession(
                 TEST_SESSION_ID,
                 TEST_PUBLIC_KEY,
@@ -442,7 +489,7 @@
                 keyClaimant, TEST_SECRET, TEST_VAULT_PARAMS, recoveryKey);
         WrappedApplicationKey badApplicationKey = new WrappedApplicationKey(
                 TEST_ALIAS,
-                randomBytes(32));
+                encryptedApplicationKey(randomRecoveryKey(), randomBytes(32)));
 
         try {
             mRecoverableKeyStoreManager.recoverKeys(
@@ -451,11 +498,35 @@
                     /*applicationKeys=*/ ImmutableList.of(badApplicationKey));
             fail("should have thrown");
         } catch (ServiceSpecificException e) {
-            assertThat(e.getMessage()).startsWith("Failed to recover key with alias 'nick'");
+            assertThat(e.getMessage()).startsWith("Failed to recover any of the application keys");
         }
     }
 
     @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,
@@ -487,6 +558,44 @@
     }
 
     @Test
+    public void recoverKeys_worksOnOtherApplicationKeysIfOneDecryptionFails() 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);
+
+        byte[] applicationKeyBytes1 = randomBytes(32);
+        byte[] applicationKeyBytes2 = randomBytes(32);
+
+        WrappedApplicationKey applicationKey1 = new WrappedApplicationKey(
+                TEST_ALIAS,
+                // Use a different recovery key here, so the decryption will fail
+                encryptedApplicationKey(randomRecoveryKey(), applicationKeyBytes1));
+        WrappedApplicationKey applicationKey2 = new WrappedApplicationKey(
+                TEST_ALIAS2,
+                encryptedApplicationKey(recoveryKey, applicationKeyBytes2));
+
+        Map<String, byte[]> recoveredKeys = mRecoverableKeyStoreManager.recoverKeys(
+                TEST_SESSION_ID,
+                encryptedClaimResponse,
+                ImmutableList.of(applicationKey1, applicationKey2));
+
+        assertThat(recoveredKeys).hasSize(1);
+        assertThat(recoveredKeys.get(TEST_ALIAS2)).isEqualTo(applicationKeyBytes2);
+    }
+
+    @Test
     public void setSnapshotCreatedPendingIntent() throws Exception {
         int uid = Binder.getCallingUid();
         PendingIntent intent = PendingIntent.getBroadcast(
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/TestData.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/TestData.java
new file mode 100644
index 0000000..0e4f91b
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/TestData.java
@@ -0,0 +1,202 @@
+package com.android.server.locksettings.recoverablekeystore;
+
+import com.android.server.locksettings.recoverablekeystore.certificate.CertUtils;
+
+import java.io.ByteArrayInputStream;
+import java.nio.charset.StandardCharsets;
+import java.security.cert.CertPath;
+import java.security.cert.CertificateFactory;
+
+public final class TestData {
+
+    private static final String CERT_PATH_ENCODING = "PkiPath";
+
+    private static final String CERT_PATH_1_BASE64 = ""
+            + "MIIIPzCCBS8wggMXoAMCAQICAhAAMA0GCSqGSIb3DQEBCwUAMCAxHjAcBgNVBAMM"
+            + "FUdvb2dsZSBDcnlwdEF1dGhWYXVsdDAeFw0xODAyMDMwMDQyMDNaFw0yODAyMDEw"
+            + "MDQyMDNaMC0xKzApBgNVBAMMIkdvb2dsZSBDcnlwdEF1dGhWYXVsdCBJbnRlcm1l"
+            + "ZGlhdGUwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDckHib0X6rQyDq"
+            + "k4519b5du0OrCPk30XXKwz+Hz5y4cGZaWKGcHOHWS2X9YApRzO00/EbvFkWVUTVG"
+            + "27wJ54V+C3HHSOAUWHhEgfFWvvHwfn9HTDx1BEk79aQqJ7DuJ06Sn/WOiMtKVAT5"
+            + "6Mi8mekBxpMOrdZqwlcLrUVsZxEHsw5/ceZu4cSWzc7SzlnbNK1cCgyRDGqWf6Gp"
+            + "3hGE86kUOtM1i95RgUIpw+w/z0wxpF6kIyQTjK+KjiYH/RBOJIEcm6sSWZlMotKL"
+            + "Sn2lhf+XL8yUxExIHTosfeb077QWW4w2BB2NZM4wPAO3w4aw33FNigDQc2SQYmnU"
+            + "EYmIcD8kx77+JWCgCxBJc2zTHXtBxWuXAQ+iegt8RO+QD97pd6XKM9xPsAOkcWLp"
+            + "79o+AJol4P5fwvgYM69mM4lwH12v86RI4aptPQOag0KDIHXyKbjaQyAgv30l4KkD"
+            + "pf2uWODhOOTwNbVPYUm3sYUlhBcbyhTk8YqN9sPU4QAao5sKTAYZgB/mlheQypTU"
+            + "wyvqz6bRzGehVB3ltP9gCyKdI04VXEUuUBWk3STyV2REQen5/LKAns6v11Cz22Zr"
+            + "EdCvNLgetnyV7CJsOa/wD/GiUWL2Ta7pzshi9ahJqrrcNPRbAzOLcNKZkFexhzPp"
+            + "onuo/pNrcaRda1frepXxVkmbsgOULwIDAQABo2YwZDAdBgNVHQ4EFgQUd6md2hCP"
+            + "lmf3VkEX5FfDxKBLbaAwHwYDVR0jBBgwFoAUm2X66jmB+eBCaZHSjGYzHM/x6fgw"
+            + "EgYDVR0TAQH/BAgwBgEB/wIBATAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQEL"
+            + "BQADggIBAFgShhuW+WVTowN080PLf0TWPlHACHHUPghf7rFGxgUjJypCloE84Beg"
+            + "3ROpP5l19CDqZ9OyPzA1z6VAzeGXyFhZvby7G2tZDBRP/v0u8pnSAdC5F8l8Vh2Y"
+            + "GdgE3sZD25vpdBi7P0Ef6LYQetOJXn86PqgmgW1F6lzxDjKCsi9kpeU0AWwDdOVg"
+            + "748wku50o8UEzsVwxzFd9toGlge/nn3FH5J7EuGzAlFwToHqpwTVEegaAd0l9mr5"
+            + "+rS7Urd3X80BHDqCBcXE7Uqbtzw5Y+lmowMCnW0kFN02dC9dLt2c9IxC+9sPIA5e"
+            + "TkrZBkrkTVRGLj2r29j7nC9m5VaKcBqcLZDWy8pRna8yaZprgNdE8d/WTY9nVsic"
+            + "09N8zNF5Q0bhhWa3QonlB9XW5ZqDguiclvn+5TtREzSAtSOyxM+gfG3l0wjOywIk"
+            + "1aFa52RaqAWPL67KOM6G3vKNpMnW5hrmHrijuKxiarGIoZfkZMR5ijK0uFgv3/p6"
+            + "NHL/YQBaHJJhkKet5ThiPxwW9+1k/ZcXVeY26Xh+22Gp/8to7ZW8guPPiN1hfpD+"
+            + "7f1IdSmHDrsZQQ7bfzV0bppsyNNB7e2Ecyw+GQny27nytBLJDGdRBurbwQvzppQO"
+            + "6Qmlk0rfCszh7bGCoCQNxXmuDsQ5BC+pQUqJplTqds1smyi29xs3MIIDCDCB8aAD"
+            + "AgECAgYBYVkuU0cwDQYJKoZIhvcNAQELBQAwLTErMCkGA1UEAwwiR29vZ2xlIENy"
+            + "eXB0QXV0aFZhdWx0IEludGVybWVkaWF0ZTAeFw0xODAyMDIwMTAxMDNaFw0yMDAy"
+            + "MDMwMTAxMDNaMCkxJzAlBgNVBAMTHkdvb2dsZSBDcnlwdEF1dGhWYXVsdCBJbnN0"
+            + "YW5jZTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABLgAERiYHfButJT+htocB40B"
+            + "tDr2jdxh0EZJlQ8QhpMkZuA/0t/zeSAdkVWw5b16izJ9JVOi/KVl4b0hRH54Uvow"
+            + "DQYJKoZIhvcNAQELBQADggIBAJ3PM4GNTNYzMr8E/IGsWZkLx9ARAALqBXz7As59"
+            + "F8y5UcLMqkXD/ewOfBZgF5VzjlAePyE/wSw0wc3xzvrDVVDiZaMBW1DVtSlbn25q"
+            + "00m00mmcUeyyMc7vuRkPoDshIMQTc8+U3yyYsVScSV+B4TvSx6wPZ9FpwnSPjVPD"
+            + "2GkqeMTWszuxNVEWq0wmm0K5lMaX0hfiak+4/IZxOPPGIg2py1KLA/H2gdyeqyJR"
+            + "cAsyEkfwLlushR5T9abSiPsIRcYoX8Ck8Lt+gQ7RCMefnm8CoOBKIfcjuV4PGOoe"
+            + "Xrq57VR5SsOeT07bL+D7B+mohYFI1v2G3WClAE8XgM3q8NoFFvaYmoi0+UcTduil"
+            + "47qvozjdNmjRAgu5j6vMKXEdG5Rqsja8hy0LG1hwfnR0gNiwcZ5Le3GyFnwH1Igq"
+            + "vsGOUM0ohnDUAU0zJY7nG0QYrDYe5/QPRNhWDpYkwHDiqcG28wIQCOTPAZHU2EoS"
+            + "KjSqEG2l0S5JPcor2BEde9ikSkcmK8foxlOHIdFn+n7RNF3bSEfKn1IOuXoqPidm"
+            + "eBQLevqG8KTy/C9CHqlaCNlpbIA9h+WVfsjm2s6JXBu0YbcfoIbJAmSuZVeqB/+Z"
+            + "Vvpfiad/jQWzY49fRnsSmV7VveTFPGtJxC89EadbMAinMZo+72u59319RqN5wsP2"
+            + "Zus8";
+    private static String CERT_PATH_2_BASE64 = ""
+            + "MIIFMzCCBS8wggMXoAMCAQICAhAAMA0GCSqGSIb3DQEBCwUAMCAxHjAcBgNVBAMM"
+            + "FUdvb2dsZSBDcnlwdEF1dGhWYXVsdDAeFw0xODAyMDMwMDQyMDNaFw0yODAyMDEw"
+            + "MDQyMDNaMC0xKzApBgNVBAMMIkdvb2dsZSBDcnlwdEF1dGhWYXVsdCBJbnRlcm1l"
+            + "ZGlhdGUwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDckHib0X6rQyDq"
+            + "k4519b5du0OrCPk30XXKwz+Hz5y4cGZaWKGcHOHWS2X9YApRzO00/EbvFkWVUTVG"
+            + "27wJ54V+C3HHSOAUWHhEgfFWvvHwfn9HTDx1BEk79aQqJ7DuJ06Sn/WOiMtKVAT5"
+            + "6Mi8mekBxpMOrdZqwlcLrUVsZxEHsw5/ceZu4cSWzc7SzlnbNK1cCgyRDGqWf6Gp"
+            + "3hGE86kUOtM1i95RgUIpw+w/z0wxpF6kIyQTjK+KjiYH/RBOJIEcm6sSWZlMotKL"
+            + "Sn2lhf+XL8yUxExIHTosfeb077QWW4w2BB2NZM4wPAO3w4aw33FNigDQc2SQYmnU"
+            + "EYmIcD8kx77+JWCgCxBJc2zTHXtBxWuXAQ+iegt8RO+QD97pd6XKM9xPsAOkcWLp"
+            + "79o+AJol4P5fwvgYM69mM4lwH12v86RI4aptPQOag0KDIHXyKbjaQyAgv30l4KkD"
+            + "pf2uWODhOOTwNbVPYUm3sYUlhBcbyhTk8YqN9sPU4QAao5sKTAYZgB/mlheQypTU"
+            + "wyvqz6bRzGehVB3ltP9gCyKdI04VXEUuUBWk3STyV2REQen5/LKAns6v11Cz22Zr"
+            + "EdCvNLgetnyV7CJsOa/wD/GiUWL2Ta7pzshi9ahJqrrcNPRbAzOLcNKZkFexhzPp"
+            + "onuo/pNrcaRda1frepXxVkmbsgOULwIDAQABo2YwZDAdBgNVHQ4EFgQUd6md2hCP"
+            + "lmf3VkEX5FfDxKBLbaAwHwYDVR0jBBgwFoAUm2X66jmB+eBCaZHSjGYzHM/x6fgw"
+            + "EgYDVR0TAQH/BAgwBgEB/wIBATAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQEL"
+            + "BQADggIBAFgShhuW+WVTowN080PLf0TWPlHACHHUPghf7rFGxgUjJypCloE84Beg"
+            + "3ROpP5l19CDqZ9OyPzA1z6VAzeGXyFhZvby7G2tZDBRP/v0u8pnSAdC5F8l8Vh2Y"
+            + "GdgE3sZD25vpdBi7P0Ef6LYQetOJXn86PqgmgW1F6lzxDjKCsi9kpeU0AWwDdOVg"
+            + "748wku50o8UEzsVwxzFd9toGlge/nn3FH5J7EuGzAlFwToHqpwTVEegaAd0l9mr5"
+            + "+rS7Urd3X80BHDqCBcXE7Uqbtzw5Y+lmowMCnW0kFN02dC9dLt2c9IxC+9sPIA5e"
+            + "TkrZBkrkTVRGLj2r29j7nC9m5VaKcBqcLZDWy8pRna8yaZprgNdE8d/WTY9nVsic"
+            + "09N8zNF5Q0bhhWa3QonlB9XW5ZqDguiclvn+5TtREzSAtSOyxM+gfG3l0wjOywIk"
+            + "1aFa52RaqAWPL67KOM6G3vKNpMnW5hrmHrijuKxiarGIoZfkZMR5ijK0uFgv3/p6"
+            + "NHL/YQBaHJJhkKet5ThiPxwW9+1k/ZcXVeY26Xh+22Gp/8to7ZW8guPPiN1hfpD+"
+            + "7f1IdSmHDrsZQQ7bfzV0bppsyNNB7e2Ecyw+GQny27nytBLJDGdRBurbwQvzppQO"
+            + "6Qmlk0rfCszh7bGCoCQNxXmuDsQ5BC+pQUqJplTqds1smyi29xs3";
+
+    private static final String THM_CERT_XML_BEFORE_SERIAL = ""
+            + "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+            + "<certificates>\n"
+            + "  <metadata>\n"
+            + "    <serial>\n";
+    private static final String THM_CERT_XML_AFTER_SERIAL = ""
+            + "    </serial>\n"
+            + "    <creation-time>\n"
+            + "      1515697631\n"
+            + "    </creation-time>\n"
+            + "    <refresh-interval>\n"
+            + "      2592000\n"
+            + "    </refresh-interval>\n"
+            + "    <previous>\n"
+            + "      <serial>\n"
+            + "        0\n"
+            + "      </serial>\n"
+            + "      <hash>\n"
+            + "        47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=\n"
+            + "      </hash>\n"
+            + "    </previous>\n"
+            + "  </metadata>\n"
+            + "  <intermediates>\n"
+            + "    <cert>\n"
+            + "      MIIFLzCCAxegAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwIDEeMBwGA1UEAwwVR29v\n"
+            + "      Z2xlIENyeXB0QXV0aFZhdWx0MB4XDTE4MDIwMzAwNDIwM1oXDTI4MDIwMTAwNDIw\n"
+            + "      M1owLTErMCkGA1UEAwwiR29vZ2xlIENyeXB0QXV0aFZhdWx0IEludGVybWVkaWF0\n"
+            + "      ZTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANyQeJvRfqtDIOqTjnX1\n"
+            + "      vl27Q6sI+TfRdcrDP4fPnLhwZlpYoZwc4dZLZf1gClHM7TT8Ru8WRZVRNUbbvAnn\n"
+            + "      hX4LccdI4BRYeESB8Va+8fB+f0dMPHUESTv1pConsO4nTpKf9Y6Iy0pUBPnoyLyZ\n"
+            + "      6QHGkw6t1mrCVwutRWxnEQezDn9x5m7hxJbNztLOWds0rVwKDJEMapZ/oaneEYTz\n"
+            + "      qRQ60zWL3lGBQinD7D/PTDGkXqQjJBOMr4qOJgf9EE4kgRybqxJZmUyi0otKfaWF\n"
+            + "      /5cvzJTETEgdOix95vTvtBZbjDYEHY1kzjA8A7fDhrDfcU2KANBzZJBiadQRiYhw\n"
+            + "      PyTHvv4lYKALEElzbNMde0HFa5cBD6J6C3xE75AP3ul3pcoz3E+wA6RxYunv2j4A\n"
+            + "      miXg/l/C+Bgzr2YziXAfXa/zpEjhqm09A5qDQoMgdfIpuNpDICC/fSXgqQOl/a5Y\n"
+            + "      4OE45PA1tU9hSbexhSWEFxvKFOTxio32w9ThABqjmwpMBhmAH+aWF5DKlNTDK+rP\n"
+            + "      ptHMZ6FUHeW0/2ALIp0jThVcRS5QFaTdJPJXZERB6fn8soCezq/XULPbZmsR0K80\n"
+            + "      uB62fJXsImw5r/AP8aJRYvZNrunOyGL1qEmqutw09FsDM4tw0pmQV7GHM+mie6j+\n"
+            + "      k2txpF1rV+t6lfFWSZuyA5QvAgMBAAGjZjBkMB0GA1UdDgQWBBR3qZ3aEI+WZ/dW\n"
+            + "      QRfkV8PEoEttoDAfBgNVHSMEGDAWgBSbZfrqOYH54EJpkdKMZjMcz/Hp+DASBgNV\n"
+            + "      HRMBAf8ECDAGAQH/AgEBMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOC\n"
+            + "      AgEAWBKGG5b5ZVOjA3TzQ8t/RNY+UcAIcdQ+CF/usUbGBSMnKkKWgTzgF6DdE6k/\n"
+            + "      mXX0IOpn07I/MDXPpUDN4ZfIWFm9vLsba1kMFE/+/S7ymdIB0LkXyXxWHZgZ2ATe\n"
+            + "      xkPbm+l0GLs/QR/othB604lefzo+qCaBbUXqXPEOMoKyL2Sl5TQBbAN05WDvjzCS\n"
+            + "      7nSjxQTOxXDHMV322gaWB7+efcUfknsS4bMCUXBOgeqnBNUR6BoB3SX2avn6tLtS\n"
+            + "      t3dfzQEcOoIFxcTtSpu3PDlj6WajAwKdbSQU3TZ0L10u3Zz0jEL72w8gDl5OStkG\n"
+            + "      SuRNVEYuPavb2PucL2blVopwGpwtkNbLylGdrzJpmmuA10Tx39ZNj2dWyJzT03zM\n"
+            + "      0XlDRuGFZrdCieUH1dblmoOC6JyW+f7lO1ETNIC1I7LEz6B8beXTCM7LAiTVoVrn\n"
+            + "      ZFqoBY8vrso4zobe8o2kydbmGuYeuKO4rGJqsYihl+RkxHmKMrS4WC/f+no0cv9h\n"
+            + "      AFockmGQp63lOGI/HBb37WT9lxdV5jbpeH7bYan/y2jtlbyC48+I3WF+kP7t/Uh1\n"
+            + "      KYcOuxlBDtt/NXRummzI00Ht7YRzLD4ZCfLbufK0EskMZ1EG6tvBC/OmlA7pCaWT\n"
+            + "      St8KzOHtsYKgJA3Fea4OxDkEL6lBSommVOp2zWybKLb3Gzc=\n"
+            + "    </cert>\n"
+            + "  </intermediates>\n"
+            + "  <endpoints>\n"
+            + "    <cert>\n"
+            + "      MIIDCDCB8aADAgECAgYBYVkuU0cwDQYJKoZIhvcNAQELBQAwLTErMCkGA1UEAwwi\n"
+            + "      R29vZ2xlIENyeXB0QXV0aFZhdWx0IEludGVybWVkaWF0ZTAeFw0xODAyMDIwMTAx\n"
+            + "      MDNaFw0yMDAyMDMwMTAxMDNaMCkxJzAlBgNVBAMTHkdvb2dsZSBDcnlwdEF1dGhW\n"
+            + "      YXVsdCBJbnN0YW5jZTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABLgAERiYHfBu\n"
+            + "      tJT+htocB40BtDr2jdxh0EZJlQ8QhpMkZuA/0t/zeSAdkVWw5b16izJ9JVOi/KVl\n"
+            + "      4b0hRH54UvowDQYJKoZIhvcNAQELBQADggIBAJ3PM4GNTNYzMr8E/IGsWZkLx9AR\n"
+            + "      AALqBXz7As59F8y5UcLMqkXD/ewOfBZgF5VzjlAePyE/wSw0wc3xzvrDVVDiZaMB\n"
+            + "      W1DVtSlbn25q00m00mmcUeyyMc7vuRkPoDshIMQTc8+U3yyYsVScSV+B4TvSx6wP\n"
+            + "      Z9FpwnSPjVPD2GkqeMTWszuxNVEWq0wmm0K5lMaX0hfiak+4/IZxOPPGIg2py1KL\n"
+            + "      A/H2gdyeqyJRcAsyEkfwLlushR5T9abSiPsIRcYoX8Ck8Lt+gQ7RCMefnm8CoOBK\n"
+            + "      IfcjuV4PGOoeXrq57VR5SsOeT07bL+D7B+mohYFI1v2G3WClAE8XgM3q8NoFFvaY\n"
+            + "      moi0+UcTduil47qvozjdNmjRAgu5j6vMKXEdG5Rqsja8hy0LG1hwfnR0gNiwcZ5L\n"
+            + "      e3GyFnwH1IgqvsGOUM0ohnDUAU0zJY7nG0QYrDYe5/QPRNhWDpYkwHDiqcG28wIQ\n"
+            + "      COTPAZHU2EoSKjSqEG2l0S5JPcor2BEde9ikSkcmK8foxlOHIdFn+n7RNF3bSEfK\n"
+            + "      n1IOuXoqPidmeBQLevqG8KTy/C9CHqlaCNlpbIA9h+WVfsjm2s6JXBu0YbcfoIbJ\n"
+            + "      AmSuZVeqB/+ZVvpfiad/jQWzY49fRnsSmV7VveTFPGtJxC89EadbMAinMZo+72u5\n"
+            + "      9319RqN5wsP2Zus8\n"
+            + "    </cert>\n"
+            + "  </endpoints>\n"
+            + "</certificates>\n";
+
+    public static byte[] getCertPath1Bytes() {
+        try {
+            return CertUtils.decodeBase64(CERT_PATH_1_BASE64);
+        } catch (Exception e){
+            throw new RuntimeException(e);
+        }
+    }
+
+    public static byte[] getCertPath2Bytes() {
+        try {
+            return CertUtils.decodeBase64(CERT_PATH_2_BASE64);
+        } catch (Exception e){
+            throw new RuntimeException(e);
+        }
+    }
+
+    public static final CertPath CERT_PATH_1;
+    public static final CertPath CERT_PATH_2;
+
+    static {
+        try {
+            CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
+            CERT_PATH_1 = certFactory.generateCertPath(
+                    new ByteArrayInputStream(getCertPath1Bytes()), CERT_PATH_ENCODING);
+            CERT_PATH_2 = certFactory.generateCertPath(
+                    new ByteArrayInputStream(getCertPath2Bytes()), CERT_PATH_ENCODING);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    public static byte[] getCertXmlWithSerial(long serial) {
+        String xml = THM_CERT_XML_BEFORE_SERIAL + serial + THM_CERT_XML_AFTER_SERIAL;
+        return xml.getBytes(StandardCharsets.UTF_8);
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/certificate/CertUtilsTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/certificate/CertUtilsTest.java
index ac6d293..d08dab4 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/certificate/CertUtilsTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/certificate/CertUtilsTest.java
@@ -146,14 +146,14 @@
     @Test
     public void getXmlNodeContents_singleLevel_succeeds() throws Exception {
         Element root = CertUtils.getXmlRootNode(XML_STR.getBytes(UTF_8));
-        assertThat(CertUtils.getXmlNodeContents(CertUtils.MustExist.FALSE, root, "node1"))
+        assertThat(CertUtils.getXmlNodeContents(CertUtils.MUST_EXIST_UNENFORCED, root, "node1"))
                 .containsExactly("node1-1", "node1-2");
     }
 
     @Test
     public void getXmlNodeContents_multipleLevels_succeeds() throws Exception {
         Element root = CertUtils.getXmlRootNode(XML_STR.getBytes(UTF_8));
-        assertThat(CertUtils.getXmlNodeContents(CertUtils.MustExist.FALSE, root, "node2", "node1"))
+        assertThat(CertUtils.getXmlNodeContents(CertUtils.MUST_EXIST_UNENFORCED, root, "node2", "node1"))
                 .containsExactly("node2-node1-1", "node2-node1-2", "node2-node1-3");
     }
 
@@ -162,7 +162,7 @@
         Element root = CertUtils.getXmlRootNode(XML_STR.getBytes(UTF_8));
         assertThat(
                 CertUtils.getXmlNodeContents(
-                        CertUtils.MustExist.FALSE, root, "node2", "node-not-exist"))
+                        CertUtils.MUST_EXIST_UNENFORCED, root, "node2", "node-not-exist"))
                 .isEmpty();
     }
 
@@ -174,7 +174,7 @@
                         CertParsingException.class,
                         () ->
                                 CertUtils.getXmlNodeContents(
-                                        CertUtils.MustExist.AT_LEAST_ONE, root, "node2",
+                                        CertUtils.MUST_EXIST_AT_LEAST_ONE, root, "node2",
                                         "node-not-exist"));
         assertThat(expected.getMessage()).contains("must contain at least one");
     }
@@ -187,7 +187,7 @@
                         CertParsingException.class,
                         () ->
                                 CertUtils.getXmlNodeContents(
-                                        CertUtils.MustExist.EXACTLY_ONE, root, "node-not-exist",
+                                        CertUtils.MUST_EXIST_EXACTLY_ONE, root, "node-not-exist",
                                         "node1"));
         assertThat(expected.getMessage()).contains("must contain exactly one");
     }
@@ -200,7 +200,7 @@
                         CertParsingException.class,
                         () ->
                                 CertUtils.getXmlNodeContents(
-                                        CertUtils.MustExist.EXACTLY_ONE, root, "node2", "node1"));
+                                        CertUtils.MUST_EXIST_EXACTLY_ONE, root, "node2", "node1"));
         assertThat(expected.getMessage()).contains("must contain exactly one");
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbHelperTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbHelperTest.java
new file mode 100644
index 0000000..37482a3
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbHelperTest.java
@@ -0,0 +1,179 @@
+/*
+ * 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.locksettings.recoverablekeystore.storage;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import android.content.ContentValues;
+import android.content.Context;
+import android.database.sqlite.SQLiteDatabase;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import com.android.server.locksettings.recoverablekeystore.storage.RecoverableKeyStoreDbContract.KeysEntry;
+import com.android.server.locksettings.recoverablekeystore.storage.RecoverableKeyStoreDbContract.RecoveryServiceMetadataEntry;
+import com.android.server.locksettings.recoverablekeystore.storage.RecoverableKeyStoreDbContract.UserMetadataEntry;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class RecoverableKeyStoreDbHelperTest {
+
+    private static final long TEST_USER_ID = 10L;
+    private static final long TEST_UID = 60001L;
+    private static final String TEST_ALIAS = "test-alias";
+    private static final byte[] TEST_NONCE = "test-nonce".getBytes(UTF_8);
+    private static final byte[] TEST_WRAPPED_KEY = "test-wrapped-key".getBytes(UTF_8);
+    private static final long TEST_GENERATION_ID = 13L;
+    private static final long TEST_LAST_SYNCED_AT = 1517990732000L;
+    private static final int TEST_RECOVERY_STATUS = 3;
+    private static final int TEST_PLATFORM_KEY_GENERATION_ID = 11;
+    private static final int TEST_SNAPSHOT_VERSION = 31;
+    private static final int TEST_SHOULD_CREATE_SNAPSHOT = 1;
+    private static final byte[] TEST_PUBLIC_KEY = "test-public-key".getBytes(UTF_8);
+    private static final String TEST_SECRET_TYPES = "test-secret-types";
+    private static final long TEST_COUNTER_ID = -3981205205038476415L;
+    private static final byte[] TEST_SERVER_PARAMS = "test-server-params".getBytes(UTF_8);
+    private static final byte[] TEST_CERT_PATH = "test-cert-path".getBytes(UTF_8);
+    private static final long TEST_CERT_SERIAL = 1000L;
+
+    private static final String SQL_CREATE_V2_TABLE_KEYS =
+            "CREATE TABLE " + KeysEntry.TABLE_NAME + "( "
+                    + KeysEntry._ID + " INTEGER PRIMARY KEY,"
+                    + KeysEntry.COLUMN_NAME_USER_ID + " INTEGER,"
+                    + KeysEntry.COLUMN_NAME_UID + " INTEGER,"
+                    + KeysEntry.COLUMN_NAME_ALIAS + " TEXT,"
+                    + KeysEntry.COLUMN_NAME_NONCE + " BLOB,"
+                    + KeysEntry.COLUMN_NAME_WRAPPED_KEY + " BLOB,"
+                    + KeysEntry.COLUMN_NAME_GENERATION_ID + " INTEGER,"
+                    + KeysEntry.COLUMN_NAME_LAST_SYNCED_AT + " INTEGER,"
+                    + KeysEntry.COLUMN_NAME_RECOVERY_STATUS + " INTEGER,"
+                    + "UNIQUE(" + KeysEntry.COLUMN_NAME_UID + ","
+                    + KeysEntry.COLUMN_NAME_ALIAS + "))";
+
+    private static final String SQL_CREATE_V2_TABLE_USER_METADATA =
+            "CREATE TABLE " + UserMetadataEntry.TABLE_NAME + "( "
+                    + UserMetadataEntry._ID + " INTEGER PRIMARY KEY,"
+                    + UserMetadataEntry.COLUMN_NAME_USER_ID + " INTEGER UNIQUE,"
+                    + UserMetadataEntry.COLUMN_NAME_PLATFORM_KEY_GENERATION_ID + " INTEGER)";
+
+    private static final String SQL_CREATE_V2_TABLE_RECOVERY_SERVICE_METADATA =
+            "CREATE TABLE " + RecoveryServiceMetadataEntry.TABLE_NAME + " ("
+                    + RecoveryServiceMetadataEntry._ID + " INTEGER PRIMARY KEY,"
+                    + RecoveryServiceMetadataEntry.COLUMN_NAME_USER_ID + " INTEGER,"
+                    + RecoveryServiceMetadataEntry.COLUMN_NAME_UID + " INTEGER,"
+                    + RecoveryServiceMetadataEntry.COLUMN_NAME_SNAPSHOT_VERSION + " INTEGER,"
+                    + RecoveryServiceMetadataEntry.COLUMN_NAME_SHOULD_CREATE_SNAPSHOT + " INTEGER,"
+                    + RecoveryServiceMetadataEntry.COLUMN_NAME_PUBLIC_KEY + " BLOB,"
+                    + RecoveryServiceMetadataEntry.COLUMN_NAME_SECRET_TYPES + " TEXT,"
+                    + RecoveryServiceMetadataEntry.COLUMN_NAME_COUNTER_ID + " INTEGER,"
+                    + RecoveryServiceMetadataEntry.COLUMN_NAME_SERVER_PARAMS + " BLOB,"
+                    + "UNIQUE("
+                    + RecoveryServiceMetadataEntry.COLUMN_NAME_USER_ID  + ","
+                    + RecoveryServiceMetadataEntry.COLUMN_NAME_UID + "))";
+
+    private SQLiteDatabase mDatabase;
+    private RecoverableKeyStoreDbHelper mDatabaseHelper;
+
+    @Before
+    public void setUp() throws Exception {
+        Context context = InstrumentationRegistry.getTargetContext();
+        mDatabaseHelper = new RecoverableKeyStoreDbHelper(context);
+        mDatabase = SQLiteDatabase.create(null);
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        mDatabase.close();
+    }
+
+    private void createV2Tables() throws Exception {
+        mDatabase.execSQL(SQL_CREATE_V2_TABLE_KEYS);
+        mDatabase.execSQL(SQL_CREATE_V2_TABLE_USER_METADATA);
+        mDatabase.execSQL(SQL_CREATE_V2_TABLE_RECOVERY_SERVICE_METADATA);
+    }
+
+    @Test
+    public void onCreate() throws Exception {
+        mDatabaseHelper.onCreate(mDatabase);
+        checkAllColumns();
+    }
+
+    @Test
+    public void onUpgrade_beforeV2() throws Exception {
+        mDatabaseHelper.onUpgrade(mDatabase, /*oldVersion=*/ 1,
+                RecoverableKeyStoreDbHelper.DATABASE_VERSION);
+        checkAllColumns();
+    }
+
+    @Test
+    public void onUpgrade_fromV2() throws Exception {
+        createV2Tables();
+        mDatabaseHelper.onUpgrade(mDatabase, /*oldVersion=*/ 2,
+                RecoverableKeyStoreDbHelper.DATABASE_VERSION);
+        checkAllColumns();
+    }
+
+    private void checkAllColumns() throws Exception {
+        // Check the table containing encrypted application keys
+        ContentValues values = new ContentValues();
+        values.put(KeysEntry.COLUMN_NAME_USER_ID, TEST_USER_ID);
+        values.put(KeysEntry.COLUMN_NAME_UID, TEST_UID);
+        values.put(KeysEntry.COLUMN_NAME_ALIAS, TEST_ALIAS);
+        values.put(KeysEntry.COLUMN_NAME_NONCE, TEST_NONCE);
+        values.put(KeysEntry.COLUMN_NAME_WRAPPED_KEY, TEST_WRAPPED_KEY);
+        values.put(KeysEntry.COLUMN_NAME_GENERATION_ID, TEST_GENERATION_ID);
+        values.put(KeysEntry.COLUMN_NAME_LAST_SYNCED_AT, TEST_LAST_SYNCED_AT);
+        values.put(KeysEntry.COLUMN_NAME_RECOVERY_STATUS, TEST_RECOVERY_STATUS);
+        assertThat(mDatabase.insert(KeysEntry.TABLE_NAME, /*nullColumnHack=*/ null, values))
+                .isGreaterThan(-1L);
+
+        // Check the table about user metadata
+        values = new ContentValues();
+        values.put(UserMetadataEntry.COLUMN_NAME_USER_ID, TEST_USER_ID);
+        values.put(UserMetadataEntry.COLUMN_NAME_PLATFORM_KEY_GENERATION_ID,
+                TEST_PLATFORM_KEY_GENERATION_ID);
+        assertThat(mDatabase.insert(UserMetadataEntry.TABLE_NAME, /*nullColumnHack=*/ null, values))
+                .isGreaterThan(-1L);
+
+        // Check the table about recovery service metadata
+        values = new ContentValues();
+        values.put(RecoveryServiceMetadataEntry.COLUMN_NAME_USER_ID, TEST_USER_ID);
+        values.put(RecoveryServiceMetadataEntry.COLUMN_NAME_UID, TEST_UID);
+        values.put(RecoveryServiceMetadataEntry.COLUMN_NAME_SNAPSHOT_VERSION,
+                TEST_SNAPSHOT_VERSION);
+        values.put(RecoveryServiceMetadataEntry.COLUMN_NAME_SHOULD_CREATE_SNAPSHOT,
+                TEST_SHOULD_CREATE_SNAPSHOT);
+        values.put(RecoveryServiceMetadataEntry.COLUMN_NAME_PUBLIC_KEY, TEST_PUBLIC_KEY);
+        values.put(RecoveryServiceMetadataEntry.COLUMN_NAME_SECRET_TYPES, TEST_SECRET_TYPES);
+        values.put(RecoveryServiceMetadataEntry.COLUMN_NAME_COUNTER_ID, TEST_COUNTER_ID);
+        values.put(RecoveryServiceMetadataEntry.COLUMN_NAME_SERVER_PARAMS, TEST_SERVER_PARAMS);
+        values.put(RecoveryServiceMetadataEntry.COLUMN_NAME_CERT_PATH, TEST_CERT_PATH);
+        values.put(RecoveryServiceMetadataEntry.COLUMN_NAME_CERT_SERIAL, TEST_CERT_SERIAL);
+        assertThat(
+                mDatabase.insert(RecoveryServiceMetadataEntry.TABLE_NAME, /*nullColumnHack=*/ null,
+                        values))
+                .isGreaterThan(-1L);
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbTest.java
index 097d214..1c5bcd4 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbTest.java
@@ -32,6 +32,8 @@
 import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
+
+import com.android.server.locksettings.recoverablekeystore.TestData;
 import com.android.server.locksettings.recoverablekeystore.WrappedKey;
 
 import java.io.File;
@@ -370,6 +372,57 @@
                 pubkey);
     }
 
+    public void setRecoveryServiceCertPath_replaceOldValue() throws Exception {
+        int userId = 12;
+        int uid = 10009;
+        mRecoverableKeyStoreDb.setRecoveryServiceCertPath(userId, uid, TestData.CERT_PATH_1);
+        mRecoverableKeyStoreDb.setRecoveryServiceCertPath(userId, uid, TestData.CERT_PATH_2);
+        assertThat(mRecoverableKeyStoreDb.getRecoveryServiceCertPath(userId, uid)).isEqualTo(
+                TestData.CERT_PATH_2);
+    }
+
+    @Test
+    public void getRecoveryServiceCertPath_returnsNullIfNoValue() throws Exception {
+        int userId = 12;
+        int uid = 10009;
+        assertThat(mRecoverableKeyStoreDb.getRecoveryServiceCertPath(userId, uid)).isNull();
+    }
+
+    @Test
+    public void getRecoveryServiceCertPath_returnsInsertedValue() throws Exception {
+        int userId = 12;
+        int uid = 10009;
+        mRecoverableKeyStoreDb.setRecoveryServiceCertPath(userId, uid, TestData.CERT_PATH_1);
+        assertThat(mRecoverableKeyStoreDb.getRecoveryServiceCertPath(userId, uid)).isEqualTo(
+                TestData.CERT_PATH_1);
+    }
+
+    @Test
+    public void setRecoveryServiceCertSerial_replaceOldValue() throws Exception {
+        int userId = 12;
+        int uid = 10009;
+
+        mRecoverableKeyStoreDb.setRecoveryServiceCertSerial(userId, uid, 1L);
+        mRecoverableKeyStoreDb.setRecoveryServiceCertSerial(userId, uid, 3L);
+        assertThat(mRecoverableKeyStoreDb.getRecoveryServiceCertSerial(userId, uid)).isEqualTo(3L);
+    }
+
+    @Test
+    public void getRecoveryServiceCertSerial_returnsNullIfNoValue() throws Exception {
+        int userId = 12;
+        int uid = 10009;
+        assertThat(mRecoverableKeyStoreDb.getRecoveryServiceCertSerial(userId, uid)).isNull();
+    }
+
+    @Test
+    public void getRecoveryServiceCertSerial_returnsInsertedValue() throws Exception {
+        int userId = 12;
+        int uid = 10009;
+        mRecoverableKeyStoreDb.setRecoveryServiceCertSerial(userId, uid, 1234L);
+        assertThat(mRecoverableKeyStoreDb.getRecoveryServiceCertSerial(userId, uid)).isEqualTo(
+                1234L);
+    }
+
     @Test
     public void getRecoveryAgents_returnsUidIfSet() throws Exception {
         int userId = 12;
@@ -493,17 +546,6 @@
     }
 
     @Test
-    public void getRecoveryServicePublicKey_returnsFirstKey() throws Exception {
-        int userId = 68;
-        int uid = 12904;
-        PublicKey publicKey = genRandomPublicKey();
-
-        mRecoverableKeyStoreDb.setRecoveryServicePublicKey(userId, uid, publicKey);
-
-        assertThat(mRecoverableKeyStoreDb.getRecoveryServicePublicKey(userId)).isEqualTo(publicKey);
-    }
-
-    @Test
     public void setServerParams_replaceOldValue() throws Exception {
         int userId = 12;
         int uid = 10009;
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..28b54ef 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,13 @@
                 + ". Full list: " + uids);
     }
 
-    private void turnBatteryOff() throws Exception {
+    private void turnBatteryOn() throws Exception {
         executeCommand("cmd battery unplug");
-        assertBatteryOff();
+        executeCommand("cmd battery set status " + BatteryManager.BATTERY_STATUS_NOT_CHARGING);
+        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 +335,12 @@
         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);
+        executeCommand("cmd battery set status " + BatteryManager.BATTERY_STATUS_CHARGING);
+    }
+
+    private static void batteryReset() throws Exception {
         executeCommand("cmd battery reset");
     }
 
@@ -348,7 +355,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/net/watchlist/WatchlistLoggingHandlerTests.java b/services/tests/servicestests/src/com/android/server/net/watchlist/WatchlistLoggingHandlerTests.java
index 070de5b..a38b353 100644
--- a/services/tests/servicestests/src/com/android/server/net/watchlist/WatchlistLoggingHandlerTests.java
+++ b/services/tests/servicestests/src/com/android/server/net/watchlist/WatchlistLoggingHandlerTests.java
@@ -16,18 +16,43 @@
 
 package com.android.server.net.watchlist;
 
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.doAnswer;
+
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
+import android.content.Context;
+import android.content.ContextWrapper;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.UserInfo;
+import android.os.FileUtils;
+import android.os.Looper;
+import android.os.UserManager;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
+import android.support.test.InstrumentationRegistry;
 
 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.mockito.invocation.InvocationOnMock;
 
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
+
+import java.io.File;
+import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
 
 /**
  * runtest frameworks-services -c com.android.server.net.watchlist.WatchlistLoggingHandlerTests
@@ -36,18 +61,126 @@
 @SmallTest
 public class WatchlistLoggingHandlerTests {
 
+    private static final String APK_A = "A.apk";
+    private static final String APK_B = "B.apk";
+    private static final String APK_A_CONTENT = "AAA";
+    private static final String APK_B_CONTENT = "BBB";
+    // Sha256 of "AAA"
+    private static final String APK_A_CONTENT_HASH =
+            "CB1AD2119D8FAFB69566510EE712661F9F14B83385006EF92AEC47F523A38358";
+    // Sha256 of "BBB"
+    private static final String APK_B_CONTENT_HASH =
+            "DCDB704109A454784B81229D2B05F368692E758BFA33CB61D04C1B93791B0273";
+
+    private Context mServiceContext;
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+
+        final Context context = InstrumentationRegistry.getContext();
+        final UserManager mockUserManager = mock(UserManager.class);
+        final PackageManager mockPackageManager = mock(PackageManager.class);
+
+        // Context that will be used by WatchlistLoggingHandler
+        mServiceContext = new ContextWrapper(context) {
+            @Override
+            public PackageManager getPackageManager() {
+                return mockPackageManager;
+            }
+
+            @Override
+            public Object getSystemService(String name) {
+                switch (name) {
+                    case Context.USER_SERVICE:
+                        return mockUserManager;
+                    default:
+                        return super.getSystemService(name);
+                }
+            }
+        };
+
+        // Returns 2 users, user 0 and user 10
+        doAnswer((InvocationOnMock invocation) -> {
+            final ArrayList<UserInfo> info = new ArrayList<>();
+            info.add(new UserInfo(0, "user1", 0));
+            info.add(new UserInfo(10, "user2", 0));
+            return info;
+        }).when(mockUserManager).getUsers();
+
+        // Returns 2 apps, with uid 1 and uid 2
+        doAnswer((InvocationOnMock invocation) -> {
+            final List<ApplicationInfo> result = new ArrayList<>();
+            ApplicationInfo info1 = new ApplicationInfo();
+            info1.uid = 1;
+            result.add(info1);
+            ApplicationInfo info2 = new ApplicationInfo();
+            info2.uid = 2;
+            result.add(info2);
+            return result;
+        }).when(mockPackageManager).getInstalledApplications(anyInt());
+
+        // Uid 1 app with is installed in primary user and package name is "A"
+        // Uid 2 app is installed in secondary user and package name is "B"
+        doAnswer((InvocationOnMock invocation) -> {
+            int uid = (int) invocation.getArguments()[0];
+            if (uid == 1) {
+                return new String[]{"A"};
+            } else if (uid == 1000001) {
+                return null;
+            } else if (uid == 2) {
+                return null;
+            } else if (uid == 1000002) {
+                return new String[]{"B"};
+            }
+            return null;
+        }).when(mockPackageManager).getPackagesForUid(anyInt());
+
+        String fileDir = InstrumentationRegistry.getContext().getFilesDir().getAbsolutePath();
+        // Simulate app's apk file path
+        doAnswer((InvocationOnMock invocation) -> {
+            String pkg = (String) invocation.getArguments()[0];
+            PackageInfo result = new PackageInfo();
+            result.applicationInfo = new ApplicationInfo();
+            result.applicationInfo.publicSourceDir = fileDir + "/" + pkg + ".apk";
+            return result;
+        }).when(mockPackageManager).getPackageInfoAsUser(anyString(), anyInt(), anyInt());
+
+        FileUtils.bytesToFile(fileDir + "/" + APK_A, APK_A_CONTENT.getBytes());
+        FileUtils.bytesToFile(fileDir + "/" + APK_B, APK_B_CONTENT.getBytes());
+    }
+
+    @After
+    public void tearDown() {
+        String fileDir = InstrumentationRegistry.getContext().getFilesDir().getAbsolutePath();
+        new File(fileDir, APK_A).delete();
+        new File(fileDir, APK_B).delete();
+    }
+
+    @Test
+    public void testWatchlistLoggingHandler_getAllDigestsForReportWithMultiUsers()
+            throws Exception {
+        List<String> result = new WatchlistLoggingHandler(mServiceContext,
+                Looper.getMainLooper()).getAllDigestsForReport(
+                new WatchlistReportDbHelper.AggregatedResult(new HashSet<String>(), null,
+                        new HashMap<String, String>()));
+        assertEquals(2, result.size());
+        assertEquals(APK_A_CONTENT_HASH, result.get(0));
+        assertEquals(APK_B_CONTENT_HASH, result.get(1));
+    }
+
     @Test
     public void testWatchlistLoggingHandler_getAllSubDomains() throws Exception {
         String[] subDomains = WatchlistLoggingHandler.getAllSubDomains("abc.def.gh.i.jkl.mm");
-        assertTrue(Arrays.equals(subDomains, new String[] {"abc.def.gh.i.jkl.mm",
+        assertTrue(Arrays.equals(subDomains, new String[]{"abc.def.gh.i.jkl.mm",
                 "def.gh.i.jkl.mm", "gh.i.jkl.mm", "i.jkl.mm", "jkl.mm", "mm"}));
         subDomains = WatchlistLoggingHandler.getAllSubDomains(null);
         assertNull(subDomains);
         subDomains = WatchlistLoggingHandler.getAllSubDomains("jkl.mm");
-        assertTrue(Arrays.equals(subDomains, new String[] {"jkl.mm", "mm"}));
+        assertTrue(Arrays.equals(subDomains, new String[]{"jkl.mm", "mm"}));
         subDomains = WatchlistLoggingHandler.getAllSubDomains("abc");
-        assertTrue(Arrays.equals(subDomains, new String[] {"abc"}));
+        assertTrue(Arrays.equals(subDomains, new String[]{"abc"}));
         subDomains = WatchlistLoggingHandler.getAllSubDomains("jkl.mm.");
-        assertTrue(Arrays.equals(subDomains, new String[] {"jkl.mm.", "mm."}));
+        assertTrue(Arrays.equals(subDomains, new String[]{"jkl.mm.", "mm."}));
     }
 }
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 0abb48f..53d97e7 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
@@ -294,7 +294,7 @@
                 null /*disabledPkg*/,
                 null /*sharedUser*/,
                 UPDATED_CODE_PATH /*codePath*/,
-                null /*resourcePath*/,
+                UPDATED_CODE_PATH /*resourcePath*/,
                 null /*legacyNativeLibraryPath*/,
                 "arm64-v8a" /*primaryCpuAbi*/,
                 "armeabi" /*secondaryCpuAbi*/,
@@ -328,7 +328,7 @@
                 null /*disabledPkg*/,
                 null /*sharedUser*/,
                 UPDATED_CODE_PATH /*codePath*/,
-                null /*resourcePath*/,
+                UPDATED_CODE_PATH /*resourcePath*/,
                 null /*legacyNativeLibraryPath*/,
                 "arm64-v8a" /*primaryCpuAbi*/,
                 "armeabi" /*secondaryCpuAbi*/,
@@ -561,34 +561,6 @@
                 false /*notLaunched*/, false /*stopped*/, true /*installed*/);
     }
 
-    @Test
-    public void testInsertPackageSetting() {
-        final PackageSetting ps = createPackageSetting(0 /*sharedUserId*/, 0 /*pkgFlags*/);
-        final PackageParser.Package pkg = new PackageParser.Package(PACKAGE_NAME);
-        pkg.applicationInfo.setCodePath(ps.codePathString);
-        pkg.applicationInfo.setResourcePath(ps.resourcePathString);
-        final Context context = InstrumentationRegistry.getContext();
-        final Object lock = new Object();
-        PermissionManagerInternal pmInt = PermissionManagerService.create(context, null, lock);
-        final Settings settings =
-                new Settings(context.getFilesDir(), pmInt.getPermissionSettings(), lock);
-        pkg.usesStaticLibraries = new ArrayList<>(
-                Arrays.asList("foo.bar1", "foo.bar2", "foo.bar3"));
-        pkg.usesStaticLibrariesVersions = new long[] {2, 4, 6};
-        settings.insertPackageSettingLPw(ps, pkg);
-        assertEquals(pkg, ps.pkg);
-        assertArrayEquals(pkg.usesStaticLibraries.toArray(new String[0]), ps.usesStaticLibraries);
-        assertArrayEquals(pkg.usesStaticLibrariesVersions, ps.usesStaticLibrariesVersions);
-
-        pkg.usesStaticLibraries = null;
-        pkg.usesStaticLibrariesVersions = null;
-        settings.insertPackageSettingLPw(ps, pkg);
-        assertEquals(pkg, ps.pkg);
-        assertNull("Actual: " + Arrays.toString(ps.usesStaticLibraries), ps.usesStaticLibraries);
-        assertNull("Actual: " + Arrays.toString(ps.usesStaticLibrariesVersions),
-                ps.usesStaticLibrariesVersions);
-    }
-
     private <T> void assertArrayEquals(T[] a, T[] b) {
         assertTrue("Expected: " + Arrays.toString(a) + ", actual: " + Arrays.toString(b),
                 Arrays.equals(a, b));
@@ -640,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/pm/dex/DexoptOptionsTests.java b/services/tests/servicestests/src/com/android/server/pm/dex/DexoptOptionsTests.java
index f559986a..93064bc 100644
--- a/services/tests/servicestests/src/com/android/server/pm/dex/DexoptOptionsTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/dex/DexoptOptionsTests.java
@@ -118,7 +118,7 @@
     public void testCreateDexoptOptionsSplit() {
         int flags = DexoptOptions.DEXOPT_FORCE | DexoptOptions.DEXOPT_BOOT_COMPLETE;
 
-        DexoptOptions opt = new DexoptOptions(mPackageName, mCompilerFilter, mSplitName, flags);
+        DexoptOptions opt = new DexoptOptions(mPackageName, -1, mCompilerFilter, mSplitName, flags);
         assertEquals(mPackageName, opt.getPackageName());
         assertEquals(mCompilerFilter, opt.getCompilerFilter());
         assertEquals(mSplitName, opt.getSplitName());
diff --git a/services/tests/servicestests/src/com/android/server/power/batterysaver/BatterySavingStatsTest.java b/services/tests/servicestests/src/com/android/server/power/batterysaver/BatterySavingStatsTest.java
index f7516b2..f7112d4 100644
--- a/services/tests/servicestests/src/com/android/server/power/batterysaver/BatterySavingStatsTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/batterysaver/BatterySavingStatsTest.java
@@ -15,25 +15,30 @@
  */
 package com.android.server.power.batterysaver;
 
+import static com.android.server.power.batterysaver.BatterySavingStats.SEND_TRON_EVENTS;
+
 import static org.junit.Assert.assertEquals;
+import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 
+import android.metrics.LogMaker;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
 
 import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.server.power.batterysaver.BatterySavingStats.BatterySaverState;
 import com.android.server.power.batterysaver.BatterySavingStats.DozeState;
 import com.android.server.power.batterysaver.BatterySavingStats.InteractiveState;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
 
 import java.io.ByteArrayOutputStream;
 import java.io.PrintWriter;
@@ -222,8 +227,28 @@
                 target.toDebugString());
     }
 
-    private void assertMetricsLog(String counter, int value) {
-        verify(mMetricsLogger, times(1)).count(eq(counter), eq(value));
+    private void assertLog(boolean batterySaver, boolean interactive, long deltaTimeMs,
+            int deltaBatteryLevelUa, int deltaBatteryLevelPercent) {
+        if (SEND_TRON_EVENTS) {
+            ArgumentCaptor<LogMaker> ac = ArgumentCaptor.forClass(LogMaker.class);
+            verify(mMetricsLogger, times(1)).write(ac.capture());
+
+            LogMaker lm = ac.getValue();
+            assertEquals(MetricsEvent.BATTERY_SAVER, lm.getCategory());
+            assertEquals(batterySaver ? 1 : 0,
+                    lm.getTaggedData(MetricsEvent.RESERVED_FOR_LOGBUILDER_SUBTYPE));
+            assertEquals(interactive ? 1 : 0, lm.getTaggedData(MetricsEvent.FIELD_INTERACTIVE));
+            assertEquals(deltaTimeMs, lm.getTaggedData(MetricsEvent.FIELD_DURATION_MILLIS));
+
+            assertEquals(deltaBatteryLevelUa,
+                    (int) lm.getTaggedData(MetricsEvent.FIELD_START_BATTERY_UA)
+                            - (int) lm.getTaggedData(MetricsEvent.FIELD_END_BATTERY_UA));
+            assertEquals(deltaBatteryLevelPercent,
+                    (int) lm.getTaggedData(MetricsEvent.FIELD_START_BATTERY_PERCENT)
+                            - (int) lm.getTaggedData(MetricsEvent.FIELD_END_BATTERY_PERCENT));
+        } else {
+            verify(mMetricsLogger, times(0)).write(any(LogMaker.class));
+        }
     }
 
     @Test
@@ -249,9 +274,7 @@
                 InteractiveState.NON_INTERACTIVE,
                 DozeState.NOT_DOZING);
 
-        assertMetricsLog(BatterySavingStats.COUNTER_POWER_MILLIAMPS_PREFIX + "01", 2);
-        assertMetricsLog(BatterySavingStats.COUNTER_POWER_PERCENT_PREFIX + "01", 200);
-        assertMetricsLog(BatterySavingStats.COUNTER_TIME_SECONDS_PREFIX + "01", 60);
+        assertLog(false, true, 60_000, 2000, 200);
 
         target.advanceClock(1);
         target.drainBattery(2000);
@@ -282,9 +305,7 @@
                 InteractiveState.INTERACTIVE,
                 DozeState.NOT_DOZING);
 
-        assertMetricsLog(BatterySavingStats.COUNTER_POWER_MILLIAMPS_PREFIX + "00", 2 * 3);
-        assertMetricsLog(BatterySavingStats.COUNTER_POWER_PERCENT_PREFIX + "00", 200 * 3);
-        assertMetricsLog(BatterySavingStats.COUNTER_TIME_SECONDS_PREFIX + "00", 60 * 3);
+        assertLog(false, false, 60_000 * 3, 2000 * 3, 200 * 3);
 
         target.advanceClock(10);
         target.drainBattery(10000);
@@ -292,9 +313,7 @@
         reset(mMetricsLogger);
         target.startCharging();
 
-        assertMetricsLog(BatterySavingStats.COUNTER_POWER_MILLIAMPS_PREFIX + "11", 10);
-        assertMetricsLog(BatterySavingStats.COUNTER_POWER_PERCENT_PREFIX + "11", 1000);
-        assertMetricsLog(BatterySavingStats.COUNTER_TIME_SECONDS_PREFIX + "11", 60 * 10);
+        assertLog(true, true, 60_000 * 10, 10000, 1000);
 
         target.advanceClock(1);
         target.drainBattery(2000);
@@ -312,8 +331,6 @@
 
         target.startCharging();
 
-        assertMetricsLog(BatterySavingStats.COUNTER_POWER_MILLIAMPS_PREFIX + "10", 2);
-        assertMetricsLog(BatterySavingStats.COUNTER_POWER_PERCENT_PREFIX + "10", 200);
-        assertMetricsLog(BatterySavingStats.COUNTER_TIME_SECONDS_PREFIX + "10", 60);
+        assertLog(true, false, 60_000, 2000, 200);
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/testutils/TestHandler.java b/services/tests/servicestests/src/com/android/server/testutils/TestHandler.java
index 029d9f1..1222b59 100644
--- a/services/tests/servicestests/src/com/android/server/testutils/TestHandler.java
+++ b/services/tests/servicestests/src/com/android/server/testutils/TestHandler.java
@@ -16,10 +16,11 @@
 package com.android.server.testutils;
 
 
-import static android.util.ExceptionUtils.getRootCause;
+import static android.util.ExceptionUtils.appendCause;
 import static android.util.ExceptionUtils.propagate;
 
 import android.os.Handler;
+import android.os.Looper;
 import android.os.Message;
 import android.os.SystemClock;
 import android.util.ArrayMap;
@@ -60,7 +61,7 @@
     }
 
     public TestHandler(Callback callback, LongSupplier clock) {
-        super(callback);
+        super(Looper.getMainLooper(), callback);
         mClock = clock;
     }
 
@@ -132,7 +133,7 @@
         } catch (Throwable t) {
             // Append stack trace of this message being posted as a cause for a helpful
             // test error message
-            throw propagate(getRootCause(t).initCause(msg.postPoint));
+            throw propagate(appendCause(t, msg.postPoint));
         } finally {
             msg.message.recycle();
         }
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/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java b/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
index 78b6077..cbbdca6 100644
--- a/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
@@ -308,6 +308,7 @@
     private void reportEvent(AppStandbyController controller, int eventType,
             long elapsedTime) {
         // Back to ACTIVE on event
+        mInjector.mElapsedRealtime = elapsedTime;
         UsageEvents.Event ev = new UsageEvents.Event();
         ev.mPackage = PACKAGE_1;
         ev.mEventType = eventType;
@@ -487,6 +488,89 @@
     }
 
     @Test
+    public void testCascadingTimeouts() throws Exception {
+        setChargingState(mController, false);
+
+        reportEvent(mController, USER_INTERACTION, 0);
+        assertBucket(STANDBY_BUCKET_ACTIVE);
+
+        reportEvent(mController, NOTIFICATION_SEEN, 1000);
+        assertBucket(STANDBY_BUCKET_ACTIVE);
+
+        mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_WORKING_SET,
+                REASON_PREDICTED, 1000);
+        assertBucket(STANDBY_BUCKET_ACTIVE);
+
+        mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_FREQUENT,
+                REASON_PREDICTED, 2000 + mController.mStrongUsageTimeoutMillis);
+        assertBucket(STANDBY_BUCKET_WORKING_SET);
+
+        mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_FREQUENT,
+                REASON_PREDICTED, 2000 + mController.mNotificationSeenTimeoutMillis);
+        assertBucket(STANDBY_BUCKET_FREQUENT);
+    }
+
+    @Test
+    public void testOverlappingTimeouts() throws Exception {
+        setChargingState(mController, false);
+
+        reportEvent(mController, USER_INTERACTION, 0);
+        assertBucket(STANDBY_BUCKET_ACTIVE);
+
+        reportEvent(mController, NOTIFICATION_SEEN, 1000);
+        assertBucket(STANDBY_BUCKET_ACTIVE);
+
+        // Overlapping USER_INTERACTION before previous one times out
+        reportEvent(mController, USER_INTERACTION, mController.mStrongUsageTimeoutMillis - 1000);
+        assertBucket(STANDBY_BUCKET_ACTIVE);
+
+        // Still in ACTIVE after first USER_INTERACTION times out
+        mInjector.mElapsedRealtime = mController.mStrongUsageTimeoutMillis + 1000;
+        mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_FREQUENT,
+                REASON_PREDICTED, mInjector.mElapsedRealtime);
+        assertBucket(STANDBY_BUCKET_ACTIVE);
+
+        // Both timed out, so NOTIFICATION_SEEN timeout should be effective
+        mInjector.mElapsedRealtime = mController.mStrongUsageTimeoutMillis * 2 + 2000;
+        mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_FREQUENT,
+                REASON_PREDICTED, mInjector.mElapsedRealtime);
+        assertBucket(STANDBY_BUCKET_WORKING_SET);
+
+        mInjector.mElapsedRealtime = mController.mNotificationSeenTimeoutMillis + 2000;
+        mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RARE,
+                REASON_PREDICTED, mInjector.mElapsedRealtime);
+        assertBucket(STANDBY_BUCKET_RARE);
+    }
+
+    @Test
+    public void testPredictionNotOverridden() throws Exception {
+        setChargingState(mController, false);
+
+        reportEvent(mController, USER_INTERACTION, 0);
+        assertBucket(STANDBY_BUCKET_ACTIVE);
+
+        mInjector.mElapsedRealtime = WORKING_SET_THRESHOLD - 1000;
+        reportEvent(mController, NOTIFICATION_SEEN, mInjector.mElapsedRealtime);
+        assertBucket(STANDBY_BUCKET_ACTIVE);
+
+        // Falls back to WORKING_SET
+        mInjector.mElapsedRealtime += 5000;
+        mController.checkIdleStates(USER_ID);
+        assertBucket(STANDBY_BUCKET_WORKING_SET);
+
+        // Predict to ACTIVE
+        mInjector.mElapsedRealtime += 1000;
+        mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_ACTIVE,
+                REASON_PREDICTED, mInjector.mElapsedRealtime);
+        assertBucket(STANDBY_BUCKET_ACTIVE);
+
+        // CheckIdleStates should not change the prediction
+        mInjector.mElapsedRealtime += 1000;
+        mController.checkIdleStates(USER_ID);
+        assertBucket(STANDBY_BUCKET_ACTIVE);
+    }
+
+    @Test
     public void testAddActiveDeviceAdmin() {
         assertActiveAdmins(USER_ID, (String[]) null);
         assertActiveAdmins(USER_ID2, (String[]) null);
diff --git a/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
index 2284bbb..63ac4af 100644
--- a/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
@@ -28,6 +28,7 @@
 import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
 import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION;
 import static com.android.server.wm.WindowContainer.POSITION_TOP;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
@@ -38,7 +39,6 @@
 import android.annotation.SuppressLint;
 import android.content.res.Configuration;
 import android.graphics.Path;
-import android.graphics.Point;
 import android.graphics.Rect;
 import android.os.SystemClock;
 import android.platform.test.annotations.Presubmit;
@@ -166,6 +166,7 @@
         assertTrue(appWin.canBeImeTarget());
         WindowState imeTarget = mDisplayContent.computeImeTarget(false /* updateImeTarget */);
         assertEquals(appWin, imeTarget);
+        appWin.mHidden = false;
 
         // Verify that an child window can be an ime target.
         final WindowState childWin = createWindow(appWin,
diff --git a/services/tests/servicestests/src/com/android/server/wm/ScreenDecorWindowTests.java b/services/tests/servicestests/src/com/android/server/wm/ScreenDecorWindowTests.java
index f23bd62..3a1485e 100644
--- a/services/tests/servicestests/src/com/android/server/wm/ScreenDecorWindowTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/ScreenDecorWindowTests.java
@@ -17,7 +17,6 @@
 package com.android.server.wm;
 
 import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
-import static android.graphics.Color.BLUE;
 import static android.graphics.Color.RED;
 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY;
 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_PRESENTATION;
@@ -27,7 +26,6 @@
 import static android.view.Gravity.RIGHT;
 import static android.view.Gravity.TOP;
 import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
-import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
 import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
 import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
 import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
@@ -49,6 +47,7 @@
 import android.os.Handler;
 import android.platform.test.annotations.Presubmit;
 import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.FlakyTest;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
 import android.util.Pair;
@@ -66,18 +65,19 @@
 import org.junit.runner.RunWith;
 
 import java.util.ArrayList;
+import java.util.function.BooleanSupplier;
 
 /**
  * Tests for the {@link android.view.WindowManager.LayoutParams#PRIVATE_FLAG_IS_SCREEN_DECOR} flag.
  *
  * Build/Install/Run:
- *  bit FrameworksServicesTests:com.android.server.wm.ScreenDecorWindowTests
+ *  atest FrameworksServicesTests:com.android.server.wm.ScreenDecorWindowTests
  */
 // TODO: Add test for FLAG_FULLSCREEN which hides the status bar and also other flags.
 // TODO: Test non-Activity windows.
 @SmallTest
-// TODO(b/68957554)
-//@Presubmit
+@Presubmit
+@FlakyTest(bugId = 68957554)
 @RunWith(AndroidJUnit4.class)
 public class ScreenDecorWindowTests {
 
@@ -123,40 +123,33 @@
     public void testScreenSides() throws Exception {
         // Decor on top
         final View decorWindow = createDecorWindow(TOP, MATCH_PARENT, mDecorThickness);
-        WindowInsets insets = getInsets(mTestActivity);
-        assertGreaterOrEqual(insets.getSystemWindowInsetTop(), mDecorThickness);
+        assertInsetGreaterOrEqual(mTestActivity, TOP, mDecorThickness);
 
         // Decor at the bottom
         updateWindow(decorWindow, BOTTOM, MATCH_PARENT, mDecorThickness, 0, 0);
-        insets = getInsets(mTestActivity);
-        assertGreaterOrEqual(insets.getSystemWindowInsetBottom(), mDecorThickness);
+        assertInsetGreaterOrEqual(mTestActivity, BOTTOM, mDecorThickness);
 
         // Decor to the left
         updateWindow(decorWindow, LEFT, mDecorThickness, MATCH_PARENT, 0, 0);
-        insets = getInsets(mTestActivity);
-        assertGreaterOrEqual(insets.getSystemWindowInsetLeft(), mDecorThickness);
+        assertInsetGreaterOrEqual(mTestActivity, LEFT, mDecorThickness);
 
         // Decor to the right
         updateWindow(decorWindow, RIGHT, mDecorThickness, MATCH_PARENT, 0, 0);
-        insets = getInsets(mTestActivity);
-        assertGreaterOrEqual(insets.getSystemWindowInsetRight(), mDecorThickness);
+        assertInsetGreaterOrEqual(mTestActivity, RIGHT, mDecorThickness);
     }
 
     @Test
     public void testMultipleDecors() throws Exception {
         // Test 2 decor windows on-top.
         createDecorWindow(TOP, MATCH_PARENT, mHalfDecorThickness);
-        WindowInsets insets = getInsets(mTestActivity);
-        assertGreaterOrEqual(insets.getSystemWindowInsetTop(), mHalfDecorThickness);
+        assertInsetGreaterOrEqual(mTestActivity, TOP, mHalfDecorThickness);
         createDecorWindow(TOP, MATCH_PARENT, mDecorThickness);
-        insets = getInsets(mTestActivity);
-        assertGreaterOrEqual(insets.getSystemWindowInsetTop(), mDecorThickness);
+        assertInsetGreaterOrEqual(mTestActivity, TOP, mDecorThickness);
 
         // And one at the bottom.
         createDecorWindow(BOTTOM, MATCH_PARENT, mHalfDecorThickness);
-        insets = getInsets(mTestActivity);
-        assertGreaterOrEqual(insets.getSystemWindowInsetTop(), mDecorThickness);
-        assertGreaterOrEqual(insets.getSystemWindowInsetBottom(), mHalfDecorThickness);
+        assertInsetGreaterOrEqual(mTestActivity, TOP, mDecorThickness);
+        assertInsetGreaterOrEqual(mTestActivity, BOTTOM, mHalfDecorThickness);
     }
 
     @Test
@@ -164,18 +157,15 @@
         WindowInsets initialInsets = getInsets(mTestActivity);
 
         final View decorWindow = createDecorWindow(TOP, MATCH_PARENT, mDecorThickness);
-        WindowInsets insets = getInsets(mTestActivity);
-        assertEquals(mDecorThickness, insets.getSystemWindowInsetTop());
+        assertTopInsetEquals(mTestActivity, mDecorThickness);
 
         updateWindow(decorWindow, TOP, MATCH_PARENT, mDecorThickness,
                 0, PRIVATE_FLAG_IS_SCREEN_DECOR);
-        insets = getInsets(mTestActivity);
-        assertEquals(initialInsets.getSystemWindowInsetTop(), insets.getSystemWindowInsetTop());
+        assertTopInsetEquals(mTestActivity, initialInsets.getSystemWindowInsetTop());
 
         updateWindow(decorWindow, TOP, MATCH_PARENT, mDecorThickness,
                 PRIVATE_FLAG_IS_SCREEN_DECOR, PRIVATE_FLAG_IS_SCREEN_DECOR);
-        insets = getInsets(mTestActivity);
-        assertEquals(mDecorThickness, insets.getSystemWindowInsetTop());
+        assertTopInsetEquals(mTestActivity, mDecorThickness);
     }
 
     @Test
@@ -183,17 +173,10 @@
         WindowInsets initialInsets = getInsets(mTestActivity);
 
         final View decorWindow = createDecorWindow(TOP, MATCH_PARENT, mDecorThickness);
-        WindowInsets insets = getInsets(mTestActivity);
-        assertGreaterOrEqual(insets.getSystemWindowInsetTop(), mDecorThickness);
+        assertInsetGreaterOrEqual(mTestActivity, TOP, mDecorThickness);
 
         removeWindow(decorWindow);
-        insets = getInsets(mTestActivity);
-        assertEquals(initialInsets.getSystemWindowInsetTop(), insets.getSystemWindowInsetTop());
-    }
-
-    private View createAppWindow() {
-        return createWindow("appWindow", TOP, MATCH_PARENT, MATCH_PARENT, BLUE,
-                FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR, 0);
+        assertTopInsetEquals(mTestActivity, initialInsets.getSystemWindowInsetTop());
     }
 
     private View createDecorWindow(int gravity, int width, int height) {
@@ -249,10 +232,6 @@
         waitForIdle();
     }
 
-    private WindowInsets getInsets(View v) {
-        return new WindowInsets(v.getRootWindowInsets());
-    }
-
     private WindowInsets getInsets(Activity a) {
         return new WindowInsets(a.getWindow().getDecorView().getRootWindowInsets());
     }
@@ -269,11 +248,59 @@
         lp.flags = (lp.flags & ~mask) | (flags & mask);
     }
 
+    /**
+     * Asserts the top inset of {@param activity} is equal to {@param expected} waiting as needed.
+     */
+    private void assertTopInsetEquals(Activity activity, int expected) throws Exception {
+        waitFor(() -> getInsets(activity).getSystemWindowInsetTop() == expected);
+        assertEquals(expected, getInsets(activity).getSystemWindowInsetTop());
+    }
+
+    /**
+     * Asserts the inset at {@param side} of {@param activity} is equal to {@param expected}
+     * waiting as needed.
+     */
+    private void assertInsetGreaterOrEqual(Activity activity, int side, int expected)
+            throws Exception {
+        waitFor(() -> {
+            final WindowInsets insets = getInsets(activity);
+            switch (side) {
+                case TOP: return insets.getSystemWindowInsetTop() >= expected;
+                case BOTTOM: return insets.getSystemWindowInsetBottom() >= expected;
+                case LEFT: return insets.getSystemWindowInsetLeft() >= expected;
+                case RIGHT: return insets.getSystemWindowInsetRight() >= expected;
+                default: return true;
+            }
+        });
+
+        final WindowInsets insets = getInsets(activity);
+        switch (side) {
+            case TOP: assertGreaterOrEqual(insets.getSystemWindowInsetTop(), expected); break;
+            case BOTTOM: assertGreaterOrEqual(insets.getSystemWindowInsetBottom(), expected); break;
+            case LEFT: assertGreaterOrEqual(insets.getSystemWindowInsetLeft(), expected); break;
+            case RIGHT: assertGreaterOrEqual(insets.getSystemWindowInsetRight(), expected); break;
+        }
+    }
+
     /** Asserts that the first entry is greater than or equal to the second entry. */
     private void assertGreaterOrEqual(int first, int second) throws Exception {
         Assert.assertTrue("Excepted " + first + " >= " + second, first >= second);
     }
 
+    private void waitFor(BooleanSupplier waitCondition) {
+        int retriesLeft = 5;
+        do {
+            if (waitCondition.getAsBoolean()) {
+                break;
+            }
+            try {
+                Thread.sleep(500);
+            } catch (InterruptedException e) {
+                // Well I guess we are not waiting...
+            }
+        } while (retriesLeft-- > 0);
+    }
+
     private void finishActivity(Activity a) {
         if (a == null) {
             return;
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotControllerTest.java b/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotControllerTest.java
index 920796e..5650050 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotControllerTest.java
@@ -29,6 +29,7 @@
 import android.support.test.runner.AndroidJUnit4;
 import android.util.ArraySet;
 
+import com.google.android.collect.Sets;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -74,6 +75,21 @@
     }
 
     @Test
+    public void testGetClosingApps_skipClosingAppsSnapshotTasks() throws Exception {
+        final WindowState closingWindow = createWindow(null, FIRST_APPLICATION_WINDOW,
+                "closingWindow");
+        closingWindow.mAppToken.setVisibility(null, false /* visible */, TRANSIT_UNSET,
+                true /* performLayout */, false /* isVoiceInteraction */);
+        final ArraySet<AppWindowToken> closingApps = new ArraySet<>();
+        closingApps.add(closingWindow.mAppToken);
+        final ArraySet<Task> closingTasks = new ArraySet<>();
+        sWm.mTaskSnapshotController.addSkipClosingAppSnapshotTasks(
+                Sets.newArraySet(closingWindow.mAppToken.getTask()));
+        sWm.mTaskSnapshotController.getClosingTasks(closingApps, closingTasks);
+        assertEquals(0, closingTasks.size());
+    }
+
+    @Test
     public void testGetSnapshotMode() throws Exception {
         final WindowState disabledWindow = createWindow(null,
                 FIRST_APPLICATION_WINDOW, mDisplayContent, "disabledWindow");
diff --git a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
index 000cf38..7a55904 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
@@ -16,6 +16,7 @@
 
 package com.android.server.wm;
 
+import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
 import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
 
@@ -107,6 +108,13 @@
 
             sWm = WindowManagerService.main(context, ims, true, false,
                     false, new TestWindowManagerPolicy());
+
+            sWm.onInitReady();
+
+            // Display creation is driven by the ActivityManagerService via ActivityStackSupervisor.
+            // We emulate those steps here.
+            sWm.mRoot.createDisplayContent(sWm.mDisplayManager.getDisplay(DEFAULT_DISPLAY),
+                    mock(DisplayWindowController.class));
         }
         return sWm;
     }
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java b/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java
index 6a4710b..74c72bf 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java
@@ -36,10 +36,15 @@
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL;
 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.verify;
 
 /**
  * Tests for the {@link WindowState} class.
@@ -57,15 +62,17 @@
         final WindowState child1 = createWindow(parentWindow, FIRST_SUB_WINDOW, "child1");
         final WindowState child2 = createWindow(parentWindow, FIRST_SUB_WINDOW, "child2");
 
-        assertFalse(parentWindow.mHidden);
+        // parentWindow is initially set to hidden.
+        assertTrue(parentWindow.mHidden);
+        assertFalse(parentWindow.isParentWindowHidden());
+        assertTrue(child1.isParentWindowHidden());
+        assertTrue(child2.isParentWindowHidden());
+
+        parentWindow.mHidden = false;
         assertFalse(parentWindow.isParentWindowHidden());
         assertFalse(child1.isParentWindowHidden());
         assertFalse(child2.isParentWindowHidden());
 
-        parentWindow.mHidden = true;
-        assertFalse(parentWindow.isParentWindowHidden());
-        assertTrue(child1.isParentWindowHidden());
-        assertTrue(child2.isParentWindowHidden());
     }
 
     @Test
@@ -237,11 +244,11 @@
     }
 
     private void testPrepareWindowToDisplayDuringRelayout(boolean wasVisible) {
+        reset(mPowerManagerWrapper);
         final WindowState root = createWindow(null, TYPE_APPLICATION, "root");
         root.mAttrs.flags |= WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON;
-        root.mTurnOnScreen = false;
 
         root.prepareWindowToDisplayDuringRelayout(wasVisible /*wasVisible*/);
-        assertTrue(root.mTurnOnScreen);
+        verify(mPowerManagerWrapper).wakeUp(anyLong(), anyString());
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
index 69b1378..91d5ea4 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
@@ -29,6 +29,7 @@
 import org.junit.Assert;
 import org.junit.After;
 import org.junit.Before;
+import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
 import android.content.Context;
@@ -84,6 +85,9 @@
     WindowState mChildAppWindowBelow;
     HashSet<WindowState> mCommonWindows;
 
+    @Mock
+    static WindowState.PowerManagerWrapper mPowerManagerWrapper;
+
     @Before
     public void setUp() throws Exception {
         if (!sOneTimeSetupDone) {
@@ -245,7 +249,7 @@
         attrs.setTitle(name);
 
         final WindowState w = new WindowState(sWm, sMockSession, sIWindow, token, parent, OP_NONE,
-                0, attrs, VISIBLE, ownerId, ownerCanAddInternalSystemWindow);
+                0, attrs, VISIBLE, ownerId, ownerCanAddInternalSystemWindow, mPowerManagerWrapper);
         // TODO: Probably better to make this call in the WindowState ctor to avoid errors with
         // adding it to the token...
         token.addWindow(w);
@@ -284,7 +288,8 @@
         final int displayId = sNextDisplayId++;
         final Display display = new Display(DisplayManagerGlobal.getInstance(), displayId,
                 mDisplayInfo, DEFAULT_DISPLAY_ADJUSTMENTS);
-        return new DisplayContent(display, sWm, new WallpaperController(sWm));
+        return new DisplayContent(display, sWm, new WallpaperController(sWm),
+                mock(DisplayWindowController.class));
     }
 
     /** Creates a {@link com.android.server.wm.WindowTestUtils.TestWindowState} */
diff --git a/services/tests/uiservicestests/Android.mk b/services/tests/uiservicestests/Android.mk
index d8e14ec..d7c3f7f 100644
--- a/services/tests/uiservicestests/Android.mk
+++ b/services/tests/uiservicestests/Android.mk
@@ -14,7 +14,6 @@
 	$(call all-java-files-under, ../../core/java/com/android/server/slice) \
 
 LOCAL_STATIC_JAVA_LIBRARIES := \
-    frameworks-base-testutils \
     services.accessibility \
     services.core \
     services.devicepolicy \
@@ -22,7 +21,7 @@
     services.usage \
     guava \
     android-support-test \
-    mockito-target-minus-junit4 \
+    mockito-target-inline-minus-junit4 \
     platform-test-annotations \
     testables
 
@@ -36,8 +35,12 @@
 
 LOCAL_CERTIFICATE := platform
 
+LOCAL_MULTILIB := both
+
 # These are not normally accessible from apps so they must be explicitly included.
 LOCAL_JNI_SHARED_LIBRARIES := \
+    libdexmakerjvmtiagent \
+    libmultiplejvmtiagentsinterferenceagent \
     libbacktrace \
     libbase \
     libbinder \
diff --git a/services/tests/uiservicestests/AndroidManifest.xml b/services/tests/uiservicestests/AndroidManifest.xml
index aabf9ea..fc459a0 100644
--- a/services/tests/uiservicestests/AndroidManifest.xml
+++ b/services/tests/uiservicestests/AndroidManifest.xml
@@ -28,7 +28,7 @@
     <uses-permission android:name="android.permission.ACCESS_VOICE_INTERACTION_SERVICE" />
     <uses-permission android:name="android.permission.DEVICE_POWER" />
 
-    <application>
+    <application android:debuggable="true">
         <uses-library android:name="android.test.runner" />
 
         <provider android:name=".DummyProvider"
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index cd32425..7b2c040 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -38,6 +38,7 @@
 import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.atLeastOnce;
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
@@ -49,8 +50,10 @@
 import static org.mockito.Mockito.when;
 
 import android.app.ActivityManager;
+import android.app.IActivityManager;
 import android.app.INotificationManager;
 import android.app.Notification;
+import android.app.Notification.MessagingStyle.Message;
 import android.app.NotificationChannel;
 import android.app.NotificationChannelGroup;
 import android.app.NotificationManager;
@@ -64,9 +67,11 @@
 import android.content.pm.ParceledListSlice;
 import android.graphics.Color;
 import android.media.AudioManager;
+import android.net.Uri;
 import android.os.Binder;
 import android.os.Build;
 import android.os.Bundle;
+import android.os.IBinder;
 import android.os.Process;
 import android.os.UserHandle;
 import android.provider.Settings.Secure;
@@ -149,6 +154,10 @@
     @Mock private ICompanionDeviceManager mCompanionMgr;
     @Mock SnoozeHelper mSnoozeHelper;
     @Mock GroupHelper mGroupHelper;
+    @Mock
+    IBinder mPermOwner;
+    @Mock
+    IActivityManager mAm;
 
     // Use a Testable subclass so we can simulate calls from the system without failing.
     private static class TestableNotificationManagerService extends NotificationManagerService {
@@ -179,6 +188,11 @@
         protected void reportSeen(NotificationRecord r) {
             return;
         }
+
+        @Override
+        protected void reportUserInteraction(NotificationRecord r) {
+            return;
+        }
     }
 
     @Before
@@ -208,6 +222,7 @@
         when(mockLightsManager.getLight(anyInt())).thenReturn(mock(Light.class));
         when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_NORMAL);
         when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(false);
+        when(mAm.newUriPermissionOwner(anyString())).thenReturn(mPermOwner);
 
         // write to a test file; the system file isn't readable from tests
         mFile = new File(mContext.getCacheDir(), "test.xml");
@@ -238,7 +253,7 @@
                     mPackageManager, mPackageManagerClient, mockLightsManager,
                     mListeners, mAssistants, mConditionProviders,
                     mCompanionMgr, mSnoozeHelper, mUsageStats, mPolicyFile, mActivityManager,
-                    mGroupHelper);
+                    mGroupHelper, mAm);
         } catch (SecurityException e) {
             if (!e.getMessage().contains("Permission Denial: not allowed to send broadcast")) {
                 throw e;
@@ -592,6 +607,8 @@
                 mBinderService.getActiveNotifications(PKG);
         assertEquals(0, notifs.length);
         assertEquals(0, mService.getNotificationRecordCount());
+        verify(mAm, atLeastOnce()).revokeUriPermissionFromOwner(
+                any(), any(), anyInt(), anyInt());
     }
 
     @Test
@@ -610,6 +627,7 @@
         ArgumentCaptor<NotificationStats> captor = ArgumentCaptor.forClass(NotificationStats.class);
         verify(mListeners, times(1)).notifyRemovedLocked(any(), anyInt(), captor.capture());
         assertEquals(NotificationStats.DISMISSAL_OTHER, captor.getValue().getDismissalSurface());
+        verify(mAm, atLeastOnce()).revokeUriPermissionFromOwner(any(), any(), anyInt(), anyInt());
     }
 
     @Test
@@ -624,6 +642,7 @@
                 mBinderService.getActiveNotifications(sbn.getPackageName());
         assertEquals(0, notifs.length);
         assertEquals(0, mService.getNotificationRecordCount());
+        verify(mAm, atLeastOnce()).revokeUriPermissionFromOwner(any(), any(), anyInt(), anyInt());
     }
 
     @Test
@@ -637,6 +656,7 @@
                 mBinderService.getActiveNotifications(sbn.getPackageName());
         assertEquals(0, notifs.length);
         assertEquals(0, mService.getNotificationRecordCount());
+        verify(mAm, atLeastOnce()).revokeUriPermissionFromOwner(any(), any(), anyInt(), anyInt());
     }
 
     @Test
@@ -658,6 +678,7 @@
         ArgumentCaptor<NotificationStats> captor = ArgumentCaptor.forClass(NotificationStats.class);
         verify(mListeners, times(1)).notifyRemovedLocked(any(), anyInt(), captor.capture());
         assertEquals(NotificationStats.DISMISSAL_OTHER, captor.getValue().getDismissalSurface());
+        verify(mAm, atLeastOnce()).revokeUriPermissionFromOwner(any(), any(), anyInt(), anyInt());
     }
 
     @Test
@@ -676,6 +697,7 @@
         mBinderService.cancelAllNotifications(PKG, parent.sbn.getUserId());
         waitForIdle();
         assertEquals(0, mService.getNotificationRecordCount());
+        verify(mAm, atLeastOnce()).revokeUriPermissionFromOwner(any(), any(), anyInt(), anyInt());
     }
 
     @Test
@@ -689,6 +711,7 @@
         waitForIdle();
 
         assertEquals(0, mService.getNotificationRecordCount());
+        verify(mAm, atLeastOnce()).revokeUriPermissionFromOwner(any(), any(), anyInt(), anyInt());
     }
 
     @Test
@@ -2447,4 +2470,64 @@
         mBinderService.getBackupPayload(1);
         assertEquals(1, mService.countSystemChecks - systemChecks);
     }
+
+    @Test
+    public void revokeUriPermissions_update() throws Exception {
+        NotificationChannel c = new NotificationChannel(
+                TEST_CHANNEL_ID, TEST_CHANNEL_ID, NotificationManager.IMPORTANCE_DEFAULT);
+        c.setSound(null, Notification.AUDIO_ATTRIBUTES_DEFAULT);
+        Message message1 = new Message("", 0, "");
+        message1.setData("", Uri.fromParts("old", "", "old stuff"));
+        Message message2 = new Message("", 1, "");
+        message2.setData("", Uri.fromParts("new", "", "new stuff"));
+
+        Notification.Builder nb = new Notification.Builder(mContext, c.getId())
+                .setContentTitle("foo")
+                .setSmallIcon(android.R.drawable.sym_def_app_icon)
+                .setStyle(new Notification.MessagingStyle("")
+                        .addMessage(message1)
+                        .addMessage(message2));
+        StatusBarNotification oldSbn = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
+                nb.build(), new UserHandle(mUid), null, 0);
+        NotificationRecord oldRecord =
+                new NotificationRecord(mContext, oldSbn, c);
+
+        Notification.Builder nb1 = new Notification.Builder(mContext, c.getId())
+                .setContentTitle("foo")
+                .setSmallIcon(android.R.drawable.sym_def_app_icon)
+                .setStyle(new Notification.MessagingStyle("").addMessage(message2));
+        StatusBarNotification newSbn = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
+                nb1.build(), new UserHandle(mUid), null, 0);
+        NotificationRecord newRecord =
+                new NotificationRecord(mContext, newSbn, c);
+
+        mService.revokeUriPermissions(newRecord, oldRecord);
+
+        verify(mAm, times(1)).revokeUriPermissionFromOwner(any(), eq(message1.getDataUri()),
+                anyInt(), anyInt());
+    }
+
+    @Test
+    public void revokeUriPermissions_cancel() throws Exception {
+        NotificationChannel c = new NotificationChannel(
+                TEST_CHANNEL_ID, TEST_CHANNEL_ID, NotificationManager.IMPORTANCE_DEFAULT);
+        c.setSound(null, Notification.AUDIO_ATTRIBUTES_DEFAULT);
+        Message message1 = new Message("", 0, "");
+        message1.setData("", Uri.fromParts("old", "", "old stuff"));
+
+        Notification.Builder nb = new Notification.Builder(mContext, c.getId())
+                .setContentTitle("foo")
+                .setSmallIcon(android.R.drawable.sym_def_app_icon)
+                .setStyle(new Notification.MessagingStyle("")
+                        .addMessage(message1));
+        StatusBarNotification oldSbn = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
+                nb.build(), new UserHandle(mUid), null, 0);
+        NotificationRecord oldRecord =
+                new NotificationRecord(mContext, oldSbn, c);
+
+        mService.revokeUriPermissions(null, oldRecord);
+
+        verify(mAm, times(1)).revokeUriPermissionFromOwner(any(), eq(message1.getDataUri()),
+                anyInt(), anyInt());
+    }
 }
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/tests/uiservicestests/src/com/android/server/notification/ScheduleConditionProviderTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ScheduleConditionProviderTest.java
index 17fed83..efa70e7 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ScheduleConditionProviderTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ScheduleConditionProviderTest.java
@@ -12,6 +12,8 @@
 import android.service.notification.ZenModeConfig;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper.RunWithLooper;
 
 import com.android.server.UiServiceTestCase;
 
@@ -23,8 +25,9 @@
 import java.util.Calendar;
 import java.util.GregorianCalendar;
 
-@RunWith(AndroidJUnit4.class)
+@RunWith(AndroidTestingRunner.class)
 @SmallTest
+@RunWithLooper
 public class ScheduleConditionProviderTest extends UiServiceTestCase {
 
     ScheduleConditionProvider mService;
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
index c532a8a..6144c51 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
@@ -17,21 +17,32 @@
 package com.android.server.notification;
 
 import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertEquals;
 import static junit.framework.TestCase.assertTrue;
 
+import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.atLeastOnce;
 import static org.mockito.Mockito.doNothing;
+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 android.app.NotificationManager;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.res.Resources;
 import android.media.AudioAttributes;
 import android.provider.Settings;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 
+import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
 import com.android.server.UiServiceTestCase;
 
 import org.junit.Before;
@@ -46,15 +57,24 @@
 public class ZenModeHelperTest extends UiServiceTestCase {
 
     @Mock ConditionProviders mConditionProviders;
+    @Mock NotificationManager mNotificationManager;
+    @Mock private Resources mResources;
     private TestableLooper mTestableLooper;
     private ZenModeHelper mZenModeHelperSpy;
+    private Context mContext;
+    private ContentResolver mContentResolver;
 
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
 
         mTestableLooper = TestableLooper.get(this);
-        mZenModeHelperSpy = spy(new ZenModeHelper(getContext(), mTestableLooper.getLooper(),
+        mContext = spy(getContext());
+        mContentResolver = mContext.getContentResolver();
+        when(mContext.getResources()).thenReturn(mResources);
+        when(mContext.getSystemService(NotificationManager.class)).thenReturn(mNotificationManager);
+
+        mZenModeHelperSpy = spy(new ZenModeHelper(mContext, mTestableLooper.getLooper(),
                 mConditionProviders));
     }
 
@@ -194,4 +214,31 @@
             verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(shouldMute, usage);
         }
     }
+
+    @Test
+    public void testZenUpgradeNotification() {
+        // shows zen upgrade notification if stored settings says to shows, boot is completed
+        // and we're setting zen mode on
+        Settings.Global.putInt(mContentResolver, Settings.Global.SHOW_ZEN_UPGRADE_NOTIFICATION, 1);
+        mZenModeHelperSpy.mIsBootComplete = true;
+        mZenModeHelperSpy.setZenModeSetting(Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS);
+
+        verify(mZenModeHelperSpy, times(1)).createZenUpgradeNotification();
+        verify(mNotificationManager, times(1)).notify(eq(ZenModeHelper.TAG),
+                eq(SystemMessage.NOTE_ZEN_UPGRADE), any());
+        assertEquals(0, Settings.Global.getInt(mContentResolver,
+                Settings.Global.SHOW_ZEN_UPGRADE_NOTIFICATION, -1));
+    }
+
+    @Test
+    public void testNoZenUpgradeNotification() {
+        // doesn't show upgrade notification if stored settings says don't show
+        Settings.Global.putInt(mContentResolver, Settings.Global.SHOW_ZEN_UPGRADE_NOTIFICATION, 0);
+        mZenModeHelperSpy.mIsBootComplete = true;
+        mZenModeHelperSpy.setZenModeSetting(Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS);
+
+        verify(mZenModeHelperSpy, never()).createZenUpgradeNotification();
+        verify(mNotificationManager, never()).notify(eq(ZenModeHelper.TAG),
+                eq(SystemMessage.NOTE_ZEN_UPGRADE), any());
+    }
 }
diff --git a/services/usage/java/com/android/server/usage/AppIdleHistory.java b/services/usage/java/com/android/server/usage/AppIdleHistory.java
index b654a66..f26c2ae 100644
--- a/services/usage/java/com/android/server/usage/AppIdleHistory.java
+++ b/services/usage/java/com/android/server/usage/AppIdleHistory.java
@@ -23,6 +23,7 @@
 import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_ACTIVE;
 import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_NEVER;
 import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_RARE;
+import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_WORKING_SET;
 
 import android.app.usage.UsageStatsManager;
 import android.os.SystemClock;
@@ -87,7 +88,9 @@
     // The last time a job was run for this app
     private static final String ATTR_LAST_RUN_JOB_TIME = "lastJobRunTime";
     // The time when the forced active state can be overridden.
-    private static final String ATTR_BUCKET_TIMEOUT_TIME = "bucketTimeoutTime";
+    private static final String ATTR_BUCKET_ACTIVE_TIMEOUT_TIME = "activeTimeoutTime";
+    // The time when the forced working_set state can be overridden.
+    private static final String ATTR_BUCKET_WORKING_SET_TIMEOUT_TIME = "workingSetTimeoutTime";
 
     // device on time = mElapsedDuration + (timeNow - mElapsedSnapshot)
     private long mElapsedSnapshot; // Elapsed time snapshot when last write of mDeviceOnDuration
@@ -117,11 +120,15 @@
         int lastInformedBucket;
         // The last time a job was run for this app, using elapsed timebase
         long lastJobRunTime;
-        // When should the bucket state timeout, in elapsed timebase, if greater than
+        // When should the bucket active state timeout, in elapsed timebase, if greater than
         // lastUsedElapsedTime.
         // This is used to keep the app in a high bucket regardless of other timeouts and
         // predictions.
-        long bucketTimeoutTime;
+        long bucketActiveTimeoutTime;
+        // If there's a forced working_set state, this is when it times out. This can be sitting
+        // under any active state timeout, so that it becomes applicable after the active state
+        // timeout expires.
+        long bucketWorkingSetTimeoutTime;
     }
 
     AppIdleHistory(File storageDir, long elapsedRealtime) {
@@ -208,11 +215,28 @@
      * @param packageName name of the app being updated, for logging purposes
      * @param newBucket the bucket to set the app to
      * @param elapsedRealtime mark as used time if non-zero
-     * @param timeout set the timeout of the specified bucket, if non-zero
+     * @param timeout set the timeout of the specified bucket, if non-zero. Can only be used
+     *                with bucket values of ACTIVE and WORKING_SET.
      * @return
      */
     public AppUsageHistory reportUsage(AppUsageHistory appUsageHistory, String packageName,
             int newBucket, long elapsedRealtime, long timeout) {
+        // Set the timeout if applicable
+        if (timeout > elapsedRealtime) {
+            // Convert to elapsed timebase
+            final long timeoutTime = mElapsedDuration + (timeout - mElapsedSnapshot);
+            if (newBucket == STANDBY_BUCKET_ACTIVE) {
+                appUsageHistory.bucketActiveTimeoutTime = Math.max(timeoutTime,
+                        appUsageHistory.bucketActiveTimeoutTime);
+            } else if (newBucket == STANDBY_BUCKET_WORKING_SET) {
+                appUsageHistory.bucketWorkingSetTimeoutTime = Math.max(timeoutTime,
+                        appUsageHistory.bucketWorkingSetTimeoutTime);
+            } else {
+                throw new IllegalArgumentException("Cannot set a timeout on bucket=" +
+                        newBucket);
+            }
+        }
+
         if (elapsedRealtime != 0) {
             appUsageHistory.lastUsedElapsedTime = mElapsedDuration
                     + (elapsedRealtime - mElapsedSnapshot);
@@ -226,12 +250,6 @@
                         .currentBucket
                         + ", reason=" + appUsageHistory.bucketingReason);
             }
-            if (timeout > elapsedRealtime) {
-                // Convert to elapsed timebase
-                appUsageHistory.bucketTimeoutTime =
-                        Math.max(appUsageHistory.bucketTimeoutTime,
-                                mElapsedDuration + (timeout - mElapsedSnapshot));
-            }
         }
         appUsageHistory.bucketingReason = REASON_USAGE;
 
@@ -247,7 +265,8 @@
      * @param userId
      * @param newBucket the bucket to set the app to
      * @param elapsedRealtime mark as used time if non-zero
-     * @param timeout set the timeout of the specified bucket, if non-zero
+     * @param timeout set the timeout of the specified bucket, if non-zero. Can only be used
+     *                with bucket values of ACTIVE and WORKING_SET.
      * @return
      */
     public AppUsageHistory reportUsage(String packageName, int userId, int newBucket,
@@ -504,8 +523,10 @@
                                 parser.getAttributeValue(null, ATTR_BUCKETING_REASON);
                         appUsageHistory.lastJobRunTime = getLongValue(parser,
                                 ATTR_LAST_RUN_JOB_TIME, Long.MIN_VALUE);
-                        appUsageHistory.bucketTimeoutTime = getLongValue(parser,
-                                ATTR_BUCKET_TIMEOUT_TIME, 0L);
+                        appUsageHistory.bucketActiveTimeoutTime = getLongValue(parser,
+                                ATTR_BUCKET_ACTIVE_TIMEOUT_TIME, 0L);
+                        appUsageHistory.bucketWorkingSetTimeoutTime = getLongValue(parser,
+                                ATTR_BUCKET_WORKING_SET_TIMEOUT_TIME, 0L);
                         if (appUsageHistory.bucketingReason == null) {
                             appUsageHistory.bucketingReason = REASON_DEFAULT;
                         }
@@ -557,9 +578,13 @@
                 xml.attribute(null, ATTR_CURRENT_BUCKET,
                         Integer.toString(history.currentBucket));
                 xml.attribute(null, ATTR_BUCKETING_REASON, history.bucketingReason);
-                if (history.bucketTimeoutTime > 0) {
-                    xml.attribute(null, ATTR_BUCKET_TIMEOUT_TIME, Long.toString(history
-                            .bucketTimeoutTime));
+                if (history.bucketActiveTimeoutTime > 0) {
+                    xml.attribute(null, ATTR_BUCKET_ACTIVE_TIMEOUT_TIME, Long.toString(history
+                            .bucketActiveTimeoutTime));
+                }
+                if (history.bucketWorkingSetTimeoutTime > 0) {
+                    xml.attribute(null, ATTR_BUCKET_WORKING_SET_TIMEOUT_TIME, Long.toString(history
+                            .bucketWorkingSetTimeoutTime));
                 }
                 if (history.lastJobRunTime != Long.MIN_VALUE) {
                     xml.attribute(null, ATTR_LAST_RUN_JOB_TIME, Long.toString(history
@@ -593,14 +618,19 @@
                 continue;
             }
             idpw.print("package=" + packageName);
+            idpw.print(" userId=" + userId);
             idpw.print(" lastUsedElapsed=");
             TimeUtils.formatDuration(totalElapsedTime - appUsageHistory.lastUsedElapsedTime, idpw);
             idpw.print(" lastUsedScreenOn=");
             TimeUtils.formatDuration(screenOnTime - appUsageHistory.lastUsedScreenTime, idpw);
             idpw.print(" lastPredictedTime=");
             TimeUtils.formatDuration(totalElapsedTime - appUsageHistory.lastPredictedTime, idpw);
-            idpw.print(" bucketTimeoutTime=");
-            TimeUtils.formatDuration(totalElapsedTime - appUsageHistory.bucketTimeoutTime, idpw);
+            idpw.print(" bucketActiveTimeoutTime=");
+            TimeUtils.formatDuration(totalElapsedTime - appUsageHistory.bucketActiveTimeoutTime,
+                    idpw);
+            idpw.print(" bucketWorkingSetTimeoutTime=");
+            TimeUtils.formatDuration(totalElapsedTime - appUsageHistory.bucketWorkingSetTimeoutTime,
+                    idpw);
             idpw.print(" lastJobRunTime=");
             TimeUtils.formatDuration(totalElapsedTime - appUsageHistory.lastJobRunTime, idpw);
             idpw.print(" idle=" + (isIdle(packageName, userId, elapsedRealtime) ? "y" : "n"));
diff --git a/services/usage/java/com/android/server/usage/AppStandbyController.java b/services/usage/java/com/android/server/usage/AppStandbyController.java
index cc21199..c31809e 100644
--- a/services/usage/java/com/android/server/usage/AppStandbyController.java
+++ b/services/usage/java/com/android/server/usage/AppStandbyController.java
@@ -30,6 +30,7 @@
 import static com.android.server.SystemService.PHASE_BOOT_COMPLETED;
 import static com.android.server.SystemService.PHASE_SYSTEM_SERVICES_READY;
 
+import android.annotation.UserIdInt;
 import android.app.ActivityManager;
 import android.app.AppGlobals;
 import android.app.usage.UsageStatsManager.StandbyBuckets;
@@ -171,12 +172,20 @@
     static final int MSG_REPORT_CONTENT_PROVIDER_USAGE = 8;
     static final int MSG_PAROLE_STATE_CHANGED = 9;
     static final int MSG_ONE_TIME_CHECK_IDLE_STATES = 10;
+    /** Check the state of one app: arg1 = userId, arg2 = uid, obj = (String) packageName */
+    static final int MSG_CHECK_PACKAGE_IDLE_STATE = 11;
 
     long mCheckIdleIntervalMillis;
     long mAppIdleParoleIntervalMillis;
     long mAppIdleParoleDurationMillis;
     long[] mAppStandbyScreenThresholds = SCREEN_TIME_THRESHOLDS;
     long[] mAppStandbyElapsedThresholds = ELAPSED_TIME_THRESHOLDS;
+    /** Minimum time a strong usage event should keep the bucket elevated. */
+    long mStrongUsageTimeoutMillis;
+    /** Minimum time a notification seen event should keep the bucket elevated. */
+    long mNotificationSeenTimeoutMillis;
+    /** Minimum time a system update event should keep the buckets elevated. */
+    long mSystemUpdateUsageTimeoutMillis;
 
     volatile boolean mAppIdleEnabled;
     boolean mAppIdleTempParoled;
@@ -316,7 +325,7 @@
         // Get sync adapters for the authority
         String[] packages = ContentResolver.getSyncAdapterPackagesForAuthorityAsUser(
                 authority, userId);
-        final long elapsedRealtime = SystemClock.elapsedRealtime();
+        final long elapsedRealtime = mInjector.elapsedRealtime();
         for (String packageName: packages) {
             // Only force the sync adapters to active if the provider is not in the same package and
             // the sync adapter is a system package.
@@ -330,7 +339,7 @@
                     synchronized (mAppIdleLock) {
                         AppUsageHistory appUsage = mAppIdleHistory.reportUsage(packageName, userId,
                                 STANDBY_BUCKET_ACTIVE, elapsedRealtime,
-                                elapsedRealtime + 2 * ONE_HOUR);
+                                elapsedRealtime + mStrongUsageTimeoutMillis);
                         maybeInformListeners(packageName, userId, elapsedRealtime,
                                 appUsage.currentBucket, false);
                     }
@@ -454,53 +463,8 @@
             for (int p = 0; p < packageCount; p++) {
                 final PackageInfo pi = packages.get(p);
                 final String packageName = pi.packageName;
-                final boolean isSpecial = isAppSpecial(packageName,
-                        UserHandle.getAppId(pi.applicationInfo.uid),
-                        userId);
-                if (DEBUG) {
-                    Slog.d(TAG, "   Checking idle state for " + packageName + " special=" +
-                            isSpecial);
-                }
-                if (isSpecial) {
-                    synchronized (mAppIdleLock) {
-                        mAppIdleHistory.setAppStandbyBucket(packageName, userId, elapsedRealtime,
-                                STANDBY_BUCKET_EXEMPTED, REASON_DEFAULT);
-                    }
-                    maybeInformListeners(packageName, userId, elapsedRealtime,
-                            STANDBY_BUCKET_EXEMPTED, false);
-                } else {
-                    synchronized (mAppIdleLock) {
-                        AppIdleHistory.AppUsageHistory app =
-                                mAppIdleHistory.getAppUsageHistory(packageName,
-                                userId, elapsedRealtime);
-                        // If the bucket was forced by the developer or the app is within the
-                        // temporary active period, leave it alone.
-                        if (REASON_FORCED.equals(app.bucketingReason)
-                                || !hasBucketTimeoutPassed(app, elapsedRealtime)) {
-                            continue;
-                        }
-                        boolean predictionLate = false;
-                        // If the bucket was moved up due to usage, let the timeouts apply.
-                        if (REASON_DEFAULT.equals(app.bucketingReason)
-                                || REASON_USAGE.equals(app.bucketingReason)
-                                || REASON_TIMEOUT.equals(app.bucketingReason)
-                                || (predictionLate = predictionTimedOut(app, elapsedRealtime))) {
-                            int oldBucket = app.currentBucket;
-                            int newBucket = getBucketForLocked(packageName, userId,
-                                    elapsedRealtime);
-                            if (DEBUG) {
-                                Slog.d(TAG, "     Old bucket=" + oldBucket
-                                        + ", newBucket=" + newBucket);
-                            }
-                            if (oldBucket < newBucket || predictionLate) {
-                                mAppIdleHistory.setAppStandbyBucket(packageName, userId,
-                                        elapsedRealtime, newBucket, REASON_TIMEOUT);
-                                maybeInformListeners(packageName, userId, elapsedRealtime,
-                                        newBucket, false);
-                            }
-                        }
-                    }
-                }
+                checkAndUpdateStandbyState(packageName, userId, pi.applicationInfo.uid,
+                        elapsedRealtime);
             }
         }
         if (DEBUG) {
@@ -510,6 +474,90 @@
         return true;
     }
 
+    /** Check if we need to update the standby state of a specific app. */
+    private void checkAndUpdateStandbyState(String packageName, @UserIdInt int userId,
+            int uid, long elapsedRealtime) {
+        if (uid <= 0) {
+            try {
+                uid = mPackageManager.getPackageUidAsUser(packageName, userId);
+            } catch (PackageManager.NameNotFoundException e) {
+                // Not a valid package for this user, nothing to do
+                // TODO: Remove any history of removed packages
+                return;
+            }
+        }
+        final boolean isSpecial = isAppSpecial(packageName,
+                UserHandle.getAppId(uid),
+                userId);
+        if (DEBUG) {
+            Slog.d(TAG, "   Checking idle state for " + packageName + " special=" +
+                    isSpecial);
+        }
+        if (isSpecial) {
+            synchronized (mAppIdleLock) {
+                mAppIdleHistory.setAppStandbyBucket(packageName, userId, elapsedRealtime,
+                        STANDBY_BUCKET_EXEMPTED, REASON_DEFAULT);
+            }
+            maybeInformListeners(packageName, userId, elapsedRealtime,
+                    STANDBY_BUCKET_EXEMPTED, false);
+        } else {
+            synchronized (mAppIdleLock) {
+                final AppIdleHistory.AppUsageHistory app =
+                        mAppIdleHistory.getAppUsageHistory(packageName,
+                        userId, elapsedRealtime);
+                String reason = app.bucketingReason;
+
+                // If the bucket was forced by the user/developer, leave it alone.
+                // A usage event will be the only way to bring it out of this forced state
+                if (REASON_FORCED.equals(app.bucketingReason)) {
+                    return;
+                }
+                final int oldBucket = app.currentBucket;
+                int newBucket = Math.max(oldBucket, STANDBY_BUCKET_ACTIVE); // Undo EXEMPTED
+                boolean predictionLate = false;
+                // Compute age-based bucket
+                if (REASON_DEFAULT.equals(app.bucketingReason)
+                        || REASON_USAGE.equals(app.bucketingReason)
+                        || REASON_TIMEOUT.equals(app.bucketingReason)
+                        || (predictionLate = predictionTimedOut(app, elapsedRealtime))) {
+                    newBucket = getBucketForLocked(packageName, userId,
+                            elapsedRealtime);
+                    if (DEBUG) {
+                        Slog.d(TAG, "Evaluated AOSP newBucket = " + newBucket);
+                    }
+                    reason = REASON_TIMEOUT;
+                }
+                // Check if the app is within one of the timeouts for forced bucket elevation
+                final long elapsedTimeAdjusted = mAppIdleHistory.getElapsedTime(elapsedRealtime);
+                if (newBucket >= STANDBY_BUCKET_ACTIVE
+                        && app.bucketActiveTimeoutTime > elapsedTimeAdjusted) {
+                    newBucket = STANDBY_BUCKET_ACTIVE;
+                    reason = REASON_USAGE;
+                    if (DEBUG) {
+                        Slog.d(TAG, "    Keeping at ACTIVE due to min timeout");
+                    }
+                } else if (newBucket >= STANDBY_BUCKET_WORKING_SET
+                        && app.bucketWorkingSetTimeoutTime > elapsedTimeAdjusted) {
+                    newBucket = STANDBY_BUCKET_WORKING_SET;
+                    reason = REASON_USAGE;
+                    if (DEBUG) {
+                        Slog.d(TAG, "    Keeping at WORKING_SET due to min timeout");
+                    }
+                }
+                if (DEBUG) {
+                    Slog.d(TAG, "     Old bucket=" + oldBucket
+                            + ", newBucket=" + newBucket);
+                }
+                if (oldBucket < newBucket || predictionLate) {
+                    mAppIdleHistory.setAppStandbyBucket(packageName, userId,
+                            elapsedRealtime, newBucket, reason);
+                    maybeInformListeners(packageName, userId, elapsedRealtime,
+                            newBucket, false);
+                }
+            }
+        }
+    }
+
     private boolean predictionTimedOut(AppIdleHistory.AppUsageHistory app, long elapsedRealtime) {
         return app.bucketingReason != null
                 && app.bucketingReason.startsWith(REASON_PREDICTED)
@@ -520,7 +568,9 @@
 
     private boolean hasBucketTimeoutPassed(AppIdleHistory.AppUsageHistory app,
             long elapsedRealtime) {
-        return app.bucketTimeoutTime < mAppIdleHistory.getElapsedTime(elapsedRealtime);
+        final long elapsedTimeAdjusted = mAppIdleHistory.getElapsedTime(elapsedRealtime);
+        return app.bucketActiveTimeoutTime < elapsedTimeAdjusted
+                && app.bucketWorkingSetTimeoutTime < elapsedTimeAdjusted;
     }
 
     private void maybeInformListeners(String packageName, int userId,
@@ -539,6 +589,7 @@
         }
     }
 
+    @GuardedBy("mAppIdleLock")
     @StandbyBuckets int getBucketForLocked(String packageName, int userId,
             long elapsedRealtime) {
         int bucketIndex = mAppIdleHistory.getThresholdIndex(packageName, userId,
@@ -624,16 +675,22 @@
                         event.mPackage, userId, elapsedRealtime);
                 final int prevBucket = appHistory.currentBucket;
                 final String prevBucketReason = appHistory.bucketingReason;
+                final long nextCheckTime;
                 if (event.mEventType == UsageEvents.Event.NOTIFICATION_SEEN) {
+                    // Mild usage elevates to WORKING_SET but doesn't change usage time.
                     mAppIdleHistory.reportUsage(appHistory, event.mPackage,
                             STANDBY_BUCKET_WORKING_SET,
-                            elapsedRealtime, elapsedRealtime + 2 * ONE_HOUR);
+                            0, elapsedRealtime + mNotificationSeenTimeoutMillis);
+                    nextCheckTime = mNotificationSeenTimeoutMillis;
                 } else {
-                    mAppIdleHistory.reportUsage(event.mPackage, userId,
+                    mAppIdleHistory.reportUsage(appHistory, event.mPackage,
                             STANDBY_BUCKET_ACTIVE,
-                            elapsedRealtime, elapsedRealtime + 2 * ONE_HOUR);
+                            elapsedRealtime, elapsedRealtime + mStrongUsageTimeoutMillis);
+                    nextCheckTime = mStrongUsageTimeoutMillis;
                 }
-
+                mHandler.sendMessageDelayed(mHandler.obtainMessage
+                        (MSG_CHECK_PACKAGE_IDLE_STATE, userId, -1, event.mPackage),
+                        nextCheckTime);
                 final boolean userStartedInteracting =
                         appHistory.currentBucket == STANDBY_BUCKET_ACTIVE &&
                         prevBucket != appHistory.currentBucket &&
@@ -925,9 +982,24 @@
 
             // If the bucket is required to stay in a higher state for a specified duration, don't
             // override unless the duration has passed
-            if (predicted && app.currentBucket < newBucket
-                    && !hasBucketTimeoutPassed(app, elapsedRealtime)) {
-                return;
+            if (predicted) {
+                // Check if the app is within one of the timeouts for forced bucket elevation
+                final long elapsedTimeAdjusted = mAppIdleHistory.getElapsedTime(elapsedRealtime);
+                if (newBucket > STANDBY_BUCKET_ACTIVE
+                        && app.bucketActiveTimeoutTime > elapsedTimeAdjusted) {
+                    newBucket = STANDBY_BUCKET_ACTIVE;
+                    reason = REASON_USAGE;
+                    if (DEBUG) {
+                        Slog.d(TAG, "    Keeping at ACTIVE due to min timeout");
+                    }
+                } else if (newBucket > STANDBY_BUCKET_WORKING_SET
+                        && app.bucketWorkingSetTimeoutTime > elapsedTimeAdjusted) {
+                    newBucket = STANDBY_BUCKET_WORKING_SET;
+                    reason = REASON_USAGE;
+                    if (DEBUG) {
+                        Slog.d(TAG, "    Keeping at WORKING_SET due to min timeout");
+                    }
+                }
             }
 
             mAppIdleHistory.setAppStandbyBucket(packageName, userId, elapsedRealtime, newBucket,
@@ -1113,10 +1185,10 @@
                 final PackageInfo pi = packages.get(i);
                 String packageName = pi.packageName;
                 if (pi.applicationInfo != null && pi.applicationInfo.isSystemApp()) {
-                    // Mark app as used for 4 hours. After that it can timeout to whatever the
+                    // Mark app as used for 2 hours. After that it can timeout to whatever the
                     // past usage pattern was.
                     mAppIdleHistory.reportUsage(packageName, userId, STANDBY_BUCKET_ACTIVE, 0,
-                            elapsedRealtime + 4 * ONE_HOUR);
+                            elapsedRealtime + mSystemUpdateUsageTimeoutMillis);
                 }
             }
         }
@@ -1340,6 +1412,10 @@
                             + ", Charging state:" + mCharging);
                     informParoleStateChanged();
                     break;
+                case MSG_CHECK_PACKAGE_IDLE_STATE:
+                    checkAndUpdateStandbyState((String) msg.obj, msg.arg1, msg.arg2,
+                            mInjector.elapsedRealtime());
+                    break;
                 default:
                     super.handleMessage(msg);
                     break;
@@ -1395,6 +1471,12 @@
         private static final String KEY_PAROLE_DURATION = "parole_duration";
         private static final String KEY_SCREEN_TIME_THRESHOLDS = "screen_thresholds";
         private static final String KEY_ELAPSED_TIME_THRESHOLDS = "elapsed_thresholds";
+        private static final String KEY_STRONG_USAGE_HOLD_DURATION = "strong_usage_duration";
+        private static final String KEY_NOTIFICATION_SEEN_HOLD_DURATION =
+                "notification_seen_duration";
+        private static final String KEY_SYSTEM_UPDATE_HOLD_DURATION =
+                "system_update_usage_duration";
+
 
         private final KeyValueListParser mParser = new KeyValueListParser(',');
 
@@ -1455,7 +1537,15 @@
                         ELAPSED_TIME_THRESHOLDS);
                 mCheckIdleIntervalMillis = Math.min(mAppStandbyElapsedThresholds[1] / 4,
                         COMPRESS_TIME ? ONE_MINUTE : 4 * 60 * ONE_MINUTE); // 4 hours
-
+                mStrongUsageTimeoutMillis = mParser.getDurationMillis
+                        (KEY_STRONG_USAGE_HOLD_DURATION,
+                                COMPRESS_TIME ? ONE_MINUTE : 1 * ONE_HOUR);
+                mNotificationSeenTimeoutMillis = mParser.getDurationMillis
+                        (KEY_NOTIFICATION_SEEN_HOLD_DURATION,
+                                COMPRESS_TIME ? 12 * ONE_MINUTE : 12 * ONE_HOUR);
+                mSystemUpdateUsageTimeoutMillis = mParser.getDurationMillis
+                        (KEY_SYSTEM_UPDATE_HOLD_DURATION,
+                                COMPRESS_TIME ? 2 * ONE_MINUTE : 2 * ONE_HOUR);
             }
         }
 
diff --git a/services/usb/OWNERS b/services/usb/OWNERS
new file mode 100644
index 0000000..7897a0c
--- /dev/null
+++ b/services/usb/OWNERS
@@ -0,0 +1,4 @@
+badhri@google.com
+elaurent@google.com
+moltmann@google.com
+zhangjerry@google.com
diff --git a/services/usb/java/com/android/server/usb/UsbAlsaDevice.java b/services/usb/java/com/android/server/usb/UsbAlsaDevice.java
index 7480e56..9d4db00 100644
--- a/services/usb/java/com/android/server/usb/UsbAlsaDevice.java
+++ b/services/usb/java/com/android/server/usb/UsbAlsaDevice.java
@@ -17,9 +17,14 @@
 package com.android.server.usb;
 
 import android.annotation.NonNull;
+import android.media.AudioSystem;
+import android.media.IAudioService;
+import android.os.RemoteException;
 import android.service.usb.UsbAlsaDeviceProto;
+import android.util.Slog;
 
 import com.android.internal.util.dump.DualDumpOutputStream;
+import com.android.server.audio.AudioService;
 
 /**
  * Represents the ALSA specification, and attributes of an ALSA device.
@@ -30,25 +35,31 @@
 
     private final int mCardNum;
     private final int mDeviceNum;
-    private final boolean mHasPlayback;
-    private final boolean mHasCapture;
+    private final String mDeviceAddress;
+    private final boolean mHasOutput;
+    private final boolean mHasInput;
 
     private final boolean mIsInputHeadset;
     private final boolean mIsOutputHeadset;
 
-    private final String mDeviceAddress;
+    private boolean mSelected = false;
+    private int mOutputState;
+    private int mInputState;
+    private UsbAlsaJackDetector mJackDetector;
+    private IAudioService mAudioService;
 
     private String mDeviceName = "";
     private String mDeviceDescription = "";
 
-    public UsbAlsaDevice(int card, int device, String deviceAddress,
-            boolean hasPlayback, boolean hasCapture,
+    public UsbAlsaDevice(IAudioService audioService, int card, int device, String deviceAddress,
+            boolean hasOutput, boolean hasInput,
             boolean isInputHeadset, boolean isOutputHeadset) {
+        mAudioService = audioService;
         mCardNum = card;
         mDeviceNum = device;
         mDeviceAddress = deviceAddress;
-        mHasPlayback = hasPlayback;
-        mHasCapture = hasCapture;
+        mHasOutput = hasOutput;
+        mHasInput = hasInput;
         mIsInputHeadset = isInputHeadset;
         mIsOutputHeadset = isOutputHeadset;
     }
@@ -75,71 +86,187 @@
     }
 
     /**
-     * @returns true if the device supports playback.
+     * @returns the ALSA card/device address string.
      */
-    public boolean hasPlayback() {
-        return mHasPlayback;
+    public String getAlsaCardDeviceString() {
+        if (mCardNum < 0 || mDeviceNum < 0) {
+            Slog.e(TAG, "Invalid alsa card or device alsaCard: " + mCardNum
+                        + " alsaDevice: " + mDeviceNum);
+            return null;
+        }
+        return AudioService.makeAlsaAddressString(mCardNum, mDeviceNum);
     }
 
     /**
-     * @returns true if the device supports capture (recording).
+     * @returns true if the device supports output.
      */
-    public boolean hasCapture() {
-        return mHasCapture;
+    public boolean hasOutput() {
+        return mHasOutput;
     }
 
     /**
-     * @returns true if the device is a headset for purposes of capture.
+     * @returns true if the device supports input (recording).
+     */
+    public boolean hasInput() {
+        return mHasInput;
+    }
+
+    /**
+     * @returns true if the device is a headset for purposes of input.
      */
     public boolean isInputHeadset() {
         return mIsInputHeadset;
     }
 
     /**
-     * @returns true if the device is a headset for purposes of playback.
+     * @returns true if the device is a headset for purposes of output.
      */
     public boolean isOutputHeadset() {
         return mIsOutputHeadset;
     }
 
     /**
+     * @returns true if input jack is detected or jack detection is not supported.
+     */
+    private synchronized boolean isInputJackConnected() {
+        if (mJackDetector == null) {
+            return true;  // If jack detect isn't supported, say it's connected.
+        }
+        return mJackDetector.isInputJackConnected();
+    }
+
+    /**
+     * @returns true if input jack is detected or jack detection is not supported.
+     */
+    private synchronized boolean isOutputJackConnected() {
+        if (mJackDetector == null) {
+            return true;  // if jack detect isn't supported, say it's connected.
+        }
+        return mJackDetector.isOutputJackConnected();
+    }
+
+    /** Begins a jack-detection thread. */
+    private synchronized void startJackDetect() {
+        // If no jack detect capabilities exist, mJackDetector will be null.
+        mJackDetector = UsbAlsaJackDetector.startJackDetect(this);
+    }
+
+    /** Stops a jack-detection thread. */
+    private synchronized void stopJackDetect() {
+        if (mJackDetector != null) {
+            mJackDetector.pleaseStop();
+        }
+        mJackDetector = null;
+    }
+
+    /** Start using this device as the selected USB Audio Device. */
+    public synchronized void start() {
+        mSelected = true;
+        mInputState = 0;
+        mOutputState = 0;
+        startJackDetect();
+        updateWiredDeviceConnectionState(true);
+    }
+
+    /** Stop using this device as the selected USB Audio Device. */
+    public synchronized void stop() {
+        stopJackDetect();
+        updateWiredDeviceConnectionState(false);
+        mSelected = false;
+    }
+
+    /** Updates AudioService with the connection state of the alsaDevice.
+     *  Checks ALSA Jack state for inputs and outputs before reporting.
+     */
+    public synchronized void updateWiredDeviceConnectionState(boolean enable) {
+        if (!mSelected) {
+            Slog.e(TAG, "updateWiredDeviceConnectionState on unselected AlsaDevice!");
+            return;
+        }
+        String alsaCardDeviceString = getAlsaCardDeviceString();
+        if (alsaCardDeviceString == null) {
+            return;
+        }
+        try {
+            // Output Device
+            if (mHasOutput) {
+                int device = mIsOutputHeadset
+                        ? AudioSystem.DEVICE_OUT_USB_HEADSET
+                        : AudioSystem.DEVICE_OUT_USB_DEVICE;
+                if (DEBUG) {
+                    Slog.d(TAG, "pre-call device:0x" + Integer.toHexString(device)
+                            + " addr:" + alsaCardDeviceString
+                            + " name:" + mDeviceName);
+                }
+                boolean connected = isOutputJackConnected();
+                Slog.i(TAG, "OUTPUT JACK connected: " + connected);
+                int outputState = (enable && connected) ? 1 : 0;
+                if (outputState != mOutputState) {
+                    mOutputState = outputState;
+                    mAudioService.setWiredDeviceConnectionState(device, outputState,
+                                                                alsaCardDeviceString,
+                                                                mDeviceName, TAG);
+                }
+            }
+
+            // Input Device
+            if (mHasInput) {
+                int device = mIsInputHeadset ? AudioSystem.DEVICE_IN_USB_HEADSET
+                        : AudioSystem.DEVICE_IN_USB_DEVICE;
+                boolean connected = isInputJackConnected();
+                Slog.i(TAG, "INPUT JACK connected: " + connected);
+                int inputState = (enable && connected) ? 1 : 0;
+                if (inputState != mInputState) {
+                    mInputState = inputState;
+                    mAudioService.setWiredDeviceConnectionState(
+                            device, inputState, alsaCardDeviceString,
+                            mDeviceName, TAG);
+                }
+            }
+        } catch (RemoteException e) {
+            Slog.e(TAG, "RemoteException in setWiredDeviceConnectionState");
+        }
+    }
+
+
+    /**
      * @Override
      * @returns a string representation of the object.
      */
-    public String toString() {
+    public synchronized String toString() {
         return "UsbAlsaDevice: [card: " + mCardNum
             + ", device: " + mDeviceNum
             + ", name: " + mDeviceName
-            + ", hasPlayback: " + mHasPlayback
-            + ", hasCapture: " + mHasCapture + "]";
+            + ", hasOutput: " + mHasOutput
+            + ", hasInput: " + mHasInput + "]";
     }
 
     /**
      * Write a description of the device to a dump stream.
      */
-    public void dump(@NonNull DualDumpOutputStream dump, String idName, long id) {
+    public synchronized void dump(@NonNull DualDumpOutputStream dump, String idName, long id) {
         long token = dump.start(idName, id);
 
         dump.write("card", UsbAlsaDeviceProto.CARD, mCardNum);
         dump.write("device", UsbAlsaDeviceProto.DEVICE, mDeviceNum);
         dump.write("name", UsbAlsaDeviceProto.NAME, mDeviceName);
-        dump.write("has_playback", UsbAlsaDeviceProto.HAS_PLAYBACK, mHasPlayback);
-        dump.write("has_capture", UsbAlsaDeviceProto.HAS_CAPTURE, mHasCapture);
+        dump.write("has_output", UsbAlsaDeviceProto.HAS_PLAYBACK, mHasOutput);
+        dump.write("has_input", UsbAlsaDeviceProto.HAS_CAPTURE, mHasInput);
         dump.write("address", UsbAlsaDeviceProto.ADDRESS, mDeviceAddress);
 
         dump.end(token);
     }
 
     // called by logDevices
-    String toShortString() {
+    synchronized String toShortString() {
         return "[card:" + mCardNum + " device:" + mDeviceNum + " " + mDeviceName + "]";
     }
 
-    String getDeviceName() {
+    synchronized String getDeviceName() {
         return mDeviceName;
     }
 
-    void setDeviceNameAndDescription(String deviceName, String deviceDescription) {
+    synchronized void setDeviceNameAndDescription(String deviceName, String deviceDescription) {
         mDeviceName = deviceName;
         mDeviceDescription = deviceDescription;
     }
@@ -155,8 +282,8 @@
         UsbAlsaDevice other = (UsbAlsaDevice) obj;
         return (mCardNum == other.mCardNum
                 && mDeviceNum == other.mDeviceNum
-                && mHasPlayback == other.mHasPlayback
-                && mHasCapture == other.mHasCapture
+                && mHasOutput == other.mHasOutput
+                && mHasInput == other.mHasInput
                 && mIsInputHeadset == other.mIsInputHeadset
                 && mIsOutputHeadset == other.mIsOutputHeadset);
     }
@@ -170,8 +297,8 @@
         int result = 1;
         result = prime * result + mCardNum;
         result = prime * result + mDeviceNum;
-        result = prime * result + (mHasPlayback ? 0 : 1);
-        result = prime * result + (mHasCapture ? 0 : 1);
+        result = prime * result + (mHasOutput ? 0 : 1);
+        result = prime * result + (mHasInput ? 0 : 1);
         result = prime * result + (mIsInputHeadset ? 0 : 1);
         result = prime * result + (mIsOutputHeadset ? 0 : 1);
 
diff --git a/services/usb/java/com/android/server/usb/UsbAlsaJackDetector.java b/services/usb/java/com/android/server/usb/UsbAlsaJackDetector.java
new file mode 100644
index 0000000..c498847
--- /dev/null
+++ b/services/usb/java/com/android/server/usb/UsbAlsaJackDetector.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.usb;
+
+/**
+ * Detects and reports ALSA jack state and events.
+ */
+public final class UsbAlsaJackDetector implements Runnable {
+    private static final String TAG = "UsbAlsaJackDetector";
+
+    private static native boolean nativeHasJackDetect(int card);
+    private native boolean nativeJackDetect(int card);
+    private native boolean nativeOutputJackConnected(int card);
+    private native boolean nativeInputJackConnected(int card);
+
+    private boolean mStopJackDetect = false;
+    private UsbAlsaDevice mAlsaDevice;
+
+    /* use startJackDetect to create a UsbAlsaJackDetector */
+    private UsbAlsaJackDetector(UsbAlsaDevice device) {
+        mAlsaDevice = device;
+    }
+
+    /** If jack detection is detected on the given Alsa Device,
+     * create and return a UsbAlsaJackDetector which will update wired device state
+     * each time a jack detection event is registered.
+     *
+     * @returns UsbAlsaJackDetector if jack detect is supported, or null.
+     */
+    public static UsbAlsaJackDetector startJackDetect(UsbAlsaDevice device) {
+        if (!nativeHasJackDetect(device.getCardNum())) {
+            return null;
+        }
+        UsbAlsaJackDetector jackDetector = new UsbAlsaJackDetector(device);
+
+        // This thread will exit once the USB device disappears.
+        // It can also be convinced to stop with pleaseStop().
+        new Thread(jackDetector, "USB jack detect thread").start();
+        return jackDetector;
+    }
+
+    public boolean isInputJackConnected() {
+        return nativeInputJackConnected(mAlsaDevice.getCardNum());
+    }
+
+    public boolean isOutputJackConnected() {
+        return nativeOutputJackConnected(mAlsaDevice.getCardNum());
+    }
+
+    /**
+     * Stop the jack detect thread from calling back into UsbAlsaDevice.
+     * This doesn't force the thread to stop (which is deprecated in java and dangerous due to
+     * locking issues), but will cause the thread to exit at the next safe opportunity.
+     */
+    public void pleaseStop() {
+        synchronized (this) {
+            mStopJackDetect = true;
+        }
+    }
+
+    /**
+     * Called by nativeJackDetect each time a jack detect event is reported.
+     * @return false when the jackDetect thread should stop.  true otherwise.
+     */
+    public boolean jackDetectCallback() {
+        synchronized (this) {
+            if (mStopJackDetect) {
+                return false;
+            }
+            mAlsaDevice.updateWiredDeviceConnectionState(true);
+        }
+        return true;
+    }
+
+    /**
+     * This will call jackDetectCallback each time it detects a jack detect event.
+     * If jackDetectCallback returns false, this function will return.
+     */
+    public void run() {
+        nativeJackDetect(mAlsaDevice.getCardNum());
+    }
+}
+
diff --git a/services/usb/java/com/android/server/usb/UsbAlsaManager.java b/services/usb/java/com/android/server/usb/UsbAlsaManager.java
index 0c5f8f1..2f1c516 100644
--- a/services/usb/java/com/android/server/usb/UsbAlsaManager.java
+++ b/services/usb/java/com/android/server/usb/UsbAlsaManager.java
@@ -20,11 +20,9 @@
 import android.content.pm.PackageManager;
 import android.content.res.Resources;
 import android.hardware.usb.UsbDevice;
-import android.media.AudioSystem;
 import android.media.IAudioService;
 import android.media.midi.MidiDeviceInfo;
 import android.os.Bundle;
-import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.provider.Settings;
 import android.service.usb.UsbAlsaManagerProto;
@@ -32,7 +30,6 @@
 
 import com.android.internal.alsa.AlsaCardsParser;
 import com.android.internal.util.dump.DualDumpOutputStream;
-import com.android.server.audio.AudioService;
 import com.android.server.usb.descriptors.UsbDescriptorParser;
 
 import libcore.io.IoUtils;
@@ -58,6 +55,7 @@
     // this is needed to map USB devices to ALSA Audio Devices, especially to remove an
     // ALSA device when we are notified that its associated USB device has been removed.
     private final ArrayList<UsbAlsaDevice> mAlsaDevices = new ArrayList<UsbAlsaDevice>();
+    private UsbAlsaDevice mSelectedDevice;
 
     /**
      * List of connected MIDI devices
@@ -78,17 +76,19 @@
                         ServiceManager.getService(Context.AUDIO_SERVICE));
     }
 
-    // Notifies AudioService when a device is added or removed
-    // audioDevice - the AudioDevice that was added or removed
-    // enabled - if true, we're connecting a device (it's arrived), else disconnecting
-    private void notifyDeviceState(UsbAlsaDevice alsaDevice, boolean enabled) {
+    /**
+     * Select the AlsaDevice to be used for AudioService.
+     * AlsaDevice.start() notifies AudioService of it's connected state.
+     *
+     * @param alsaDevice The selected UsbAlsaDevice for system USB audio.
+     */
+    private synchronized void selectAlsaDevice(UsbAlsaDevice alsaDevice) {
         if (DEBUG) {
-            Slog.d(TAG, "notifyDeviceState " + enabled + " " + alsaDevice);
+            Slog.d(TAG, "selectAlsaDevice " + alsaDevice);
         }
 
-        if (mAudioService == null) {
-            Slog.e(TAG, "no AudioService");
-            return;
+        if (mSelectedDevice != null) {
+            deselectAlsaDevice();
         }
 
         // FIXME Does not yet handle the case where the setting is changed
@@ -102,40 +102,14 @@
             return;
         }
 
-        int state = (enabled ? 1 : 0);
-        int cardNum = alsaDevice.getCardNum();
-        int deviceNum = alsaDevice.getDeviceNum();
-        if (cardNum < 0 || deviceNum < 0) {
-            Slog.e(TAG, "Invalid alsa card or device alsaCard: " + cardNum
-                        + " alsaDevice: " + deviceNum);
-            return;
-        }
+        mSelectedDevice = alsaDevice;
+        alsaDevice.start();
+    }
 
-        String address = AudioService.makeAlsaAddressString(cardNum, deviceNum);
-        try {
-            // Playback Device
-            if (alsaDevice.hasPlayback()) {
-                int device = alsaDevice.isOutputHeadset()
-                        ? AudioSystem.DEVICE_OUT_USB_HEADSET
-                        : AudioSystem.DEVICE_OUT_USB_DEVICE;
-                if (DEBUG) {
-                    Slog.i(TAG, "pre-call device:0x" + Integer.toHexString(device) +
-                            " addr:" + address + " name:" + alsaDevice.getDeviceName());
-                }
-                mAudioService.setWiredDeviceConnectionState(
-                        device, state, address, alsaDevice.getDeviceName(), TAG);
-            }
-
-            // Capture Device
-            if (alsaDevice.hasCapture()) {
-                int device = alsaDevice.isInputHeadset()
-                        ? AudioSystem.DEVICE_IN_USB_HEADSET
-                        : AudioSystem.DEVICE_IN_USB_DEVICE;
-                mAudioService.setWiredDeviceConnectionState(
-                        device, state, address, alsaDevice.getDeviceName(), TAG);
-            }
-        } catch (RemoteException e) {
-            Slog.e(TAG, "RemoteException in setWiredDeviceConnectionState");
+    private synchronized void deselectAlsaDevice() {
+        if (mSelectedDevice != null) {
+            mSelectedDevice.stop();
+            mSelectedDevice = null;
         }
     }
 
@@ -168,7 +142,7 @@
                 Slog.d(TAG, "  alsaDevice:" + alsaDevice);
             }
             if (alsaDevice != null) {
-                notifyDeviceState(alsaDevice, true /*enabled*/);
+                selectAlsaDevice(alsaDevice);
             }
             return alsaDevice;
         } else {
@@ -202,16 +176,21 @@
         if (hasInput || hasOutput) {
             boolean isInputHeadset = parser.isInputHeadset();
             boolean isOutputHeadset = parser.isOutputHeadset();
-            UsbAlsaDevice alsaDevice =
-                    new UsbAlsaDevice(cardRec.getCardNum(), 0 /*device*/, deviceAddress,
-                            hasOutput, hasInput, isInputHeadset, isOutputHeadset);
-            alsaDevice.setDeviceNameAndDescription(
-                    cardRec.getCardName(), cardRec.getCardDescription());
-            mAlsaDevices.add(0, alsaDevice);
 
-            // Select it
+            if (mAudioService == null) {
+                Slog.e(TAG, "no AudioService");
+                return;
+            }
+
+            UsbAlsaDevice alsaDevice =
+                    new UsbAlsaDevice(mAudioService, cardRec.getCardNum(), 0 /*device*/,
+                                      deviceAddress, hasOutput, hasInput,
+                                      isInputHeadset, isOutputHeadset);
             if (alsaDevice != null) {
-                notifyDeviceState(alsaDevice, true /*enabled*/);
+                alsaDevice.setDeviceNameAndDescription(
+                          cardRec.getCardName(), cardRec.getCardDescription());
+                mAlsaDevices.add(0, alsaDevice);
+                selectAlsaDevice(alsaDevice);
             }
         }
 
@@ -256,7 +235,7 @@
         }
     }
 
-    /* package */ void usbDeviceRemoved(String deviceAddress/*UsbDevice usbDevice*/) {
+    /* package */ synchronized void usbDeviceRemoved(String deviceAddress/*UsbDevice usbDevice*/) {
         if (DEBUG) {
             Slog.d(TAG, "deviceRemoved(" + deviceAddress + ")");
         }
@@ -264,13 +243,9 @@
         // Audio
         UsbAlsaDevice alsaDevice = removeAlsaDeviceFromList(deviceAddress);
         Slog.i(TAG, "USB Audio Device Removed: " + alsaDevice);
-        if (alsaDevice != null) {
-            if (alsaDevice.hasPlayback() || alsaDevice.hasCapture()) {
-                notifyDeviceState(alsaDevice, false /*enabled*/);
-
-                // if there any external devices left, select one of them
-                selectDefaultDevice();
-            }
+        if (alsaDevice != null && alsaDevice == mSelectedDevice) {
+            deselectAlsaDevice();
+            selectDefaultDevice(); // if there any external devices left, select one of them
         }
 
         // MIDI
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index 8a75b7e..c6e5750 100755
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -1790,7 +1790,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/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java b/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java
index 4b2d9b9..43f189b 100644
--- a/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java
+++ b/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java
@@ -314,6 +314,7 @@
      * Upgrade any single-user settings from {@link #sSingleUserSettingsFile}.
      * Should only by called by owner.
      */
+    @GuardedBy("mLock")
     private void upgradeSingleUserLocked() {
         if (sSingleUserSettingsFile.exists()) {
             mDevicePreferenceMap.clear();
@@ -347,6 +348,7 @@
         }
     }
 
+    @GuardedBy("mLock")
     private void readSettingsLocked() {
         if (DEBUG) Slog.v(TAG, "readSettingsLocked()");
 
@@ -386,6 +388,7 @@
      * <p>In the uncommon case that the system crashes in between the scheduling and the write the
      * update is lost.</p>
      */
+    @GuardedBy("mLock")
     private void scheduleWriteSettingsLocked() {
         if (mIsWriteSettingsScheduled) {
             return;
@@ -869,6 +872,7 @@
         return null;
     }
 
+    @GuardedBy("mLock")
     private boolean clearCompatibleMatchesLocked(@NonNull UserPackage userPackage,
             @NonNull DeviceFilter filter) {
         ArrayList<DeviceFilter> keysToRemove = new ArrayList<>();
@@ -892,6 +896,7 @@
         return !keysToRemove.isEmpty();
     }
 
+    @GuardedBy("mLock")
     private boolean clearCompatibleMatchesLocked(@NonNull UserPackage userPackage,
             @NonNull AccessoryFilter filter) {
         ArrayList<AccessoryFilter> keysToRemove = new ArrayList<>();
@@ -915,6 +920,7 @@
         return !keysToRemove.isEmpty();
     }
 
+    @GuardedBy("mLock")
     private boolean handlePackageAddedLocked(UserPackage userPackage, ActivityInfo aInfo,
             String metaDataName) {
         XmlResourceParser parser = null;
diff --git a/services/usb/java/com/android/server/usb/UsbService.java b/services/usb/java/com/android/server/usb/UsbService.java
index 1edc469..c1a7591 100644
--- a/services/usb/java/com/android/server/usb/UsbService.java
+++ b/services/usb/java/com/android/server/usb/UsbService.java
@@ -236,6 +236,7 @@
      *
      * @return Iff the caller is in the current user's profile group
      */
+    @GuardedBy("mLock")
     private boolean isCallerInCurrentUserProfileGroupLocked() {
         int userIdInt = UserHandle.getCallingUserId();
 
diff --git a/telecomm/OWNERS b/telecomm/OWNERS
new file mode 100644
index 0000000..a3bcfb2
--- /dev/null
+++ b/telecomm/OWNERS
@@ -0,0 +1,6 @@
+set noparent
+
+tgunn@google.com
+breadley@google.com
+hallliu@google.com
+rgreenwalt@google.com
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index 034dc76..8d370f2 100644
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -356,7 +356,10 @@
          * Add participant in an active or conference call option
          * @hide
          */
-        public static final int CAPABILITY_ADD_PARTICIPANT = 0x01000000;
+        public static final int CAPABILITY_ADD_PARTICIPANT = 0x02000000;
+
+        /** Call supports the deflect feature. */
+        public static final int CAPABILITY_SUPPORT_DEFLECT = 0x01000000;
 
         //******************************************************************************************
         // Next CAPABILITY value: 0x02000000
@@ -428,8 +431,14 @@
          */
         public static final int PROPERTY_ASSISTED_DIALING_USED = 0x00000200;
 
+        /**
+         * Indicates that the call is an RTT call. Use {@link #getRttCall()} to get the
+         * {@link RttCall} object that is used to send and receive text.
+         */
+        public static final int PROPERTY_RTT = 0x00000400;
+
         //******************************************************************************************
-        // Next PROPERTY value: 0x00000400
+        // Next PROPERTY value: 0x00000800
         //******************************************************************************************
 
         private final String mTelecomCallId;
@@ -537,6 +546,9 @@
             if (can(capabilities, CAPABILITY_ADD_PARTICIPANT)) {
                 builder.append(" CAPABILITY_ADD_PARTICIPANT");
             }
+            if (can(capabilities, CAPABILITY_SUPPORT_DEFLECT)) {
+                builder.append(" CAPABILITY_SUPPORT_DEFLECT");
+            }
             builder.append("]");
             return builder.toString();
         }
@@ -1192,6 +1204,23 @@
                 return null;
             }
         }
+
+        /**
+         * Closes the underlying file descriptors
+         * @hide
+         */
+        public void close() {
+            try {
+                mReceiveStream.close();
+            } catch (IOException e) {
+                // ignore
+            }
+            try {
+                mTransmitStream.close();
+            } catch (IOException e) {
+                // ignore
+            }
+        }
     }
 
     /**
@@ -1244,6 +1273,15 @@
     }
 
     /**
+     * Instructs this {@link #STATE_RINGING} {@code Call} to deflect.
+     *
+     * @param address The address to which the call will be deflected.
+     */
+    public void deflect(Uri address) {
+        mInCallAdapter.deflectCall(mTelecomCallId, address);
+    }
+
+    /**
      * Instructs this {@link #STATE_RINGING} {@code Call} to reject.
      *
      * @param rejectWithMessage Whether to reject with a text message.
@@ -1658,7 +1696,7 @@
      * @return true if there is a connection, false otherwise.
      */
     public boolean isRttActive() {
-        return mRttCall != null;
+        return mRttCall != null && mDetails.hasProperty(Details.PROPERTY_RTT);
     }
 
     /**
@@ -1861,7 +1899,8 @@
 
         boolean isRttChanged = false;
         boolean rttModeChanged = false;
-        if (parcelableCall.getParcelableRttCall() != null && parcelableCall.getIsRttCallChanged()) {
+        if (parcelableCall.getIsRttCallChanged()
+                && mDetails.hasProperty(Details.PROPERTY_RTT)) {
             ParcelableRttCall parcelableRttCall = parcelableCall.getParcelableRttCall();
             InputStreamReader receiveStream = new InputStreamReader(
                     new ParcelFileDescriptor.AutoCloseInputStream(
diff --git a/telecomm/java/android/telecom/Conference.java b/telecomm/java/android/telecom/Conference.java
index 824e97e..b5043fe 100644
--- a/telecomm/java/android/telecom/Conference.java
+++ b/telecomm/java/android/telecom/Conference.java
@@ -29,7 +29,6 @@
 import java.util.Collections;
 import java.util.List;
 import java.util.Locale;
-import java.util.Objects;
 import java.util.Set;
 import java.util.concurrent.CopyOnWriteArrayList;
 import java.util.concurrent.CopyOnWriteArraySet;
@@ -82,7 +81,7 @@
     private int mConnectionProperties;
     private String mDisconnectMessage;
     private long mConnectTimeMillis = CONNECT_TIME_NOT_SPECIFIED;
-    private long mConnectElapsedTimeMillis = CONNECT_TIME_NOT_SPECIFIED;
+    private long mConnectionStartElapsedRealTime = CONNECT_TIME_NOT_SPECIFIED;
     private StatusHints mStatusHints;
     private Bundle mExtras;
     private Set<String> mPreviousExtraKeys;
@@ -592,30 +591,36 @@
     }
 
     /**
-     * Sets the connection start time of the {@code Conference}.  Should be specified in wall-clock
-     * time returned by {@link System#currentTimeMillis()}.
+     * Sets the connection start time of the {@code Conference}.  This is used in the call log to
+     * indicate the date and time when the conference took place.
+     * <p>
+     * Should be specified in wall-clock time returned by {@link System#currentTimeMillis()}.
      * <p>
      * When setting the connection time, you should always set the connection elapsed time via
-     * {@link #setConnectionElapsedTime(long)}.
+     * {@link #setConnectionStartElapsedRealTime(long)} to ensure the duration is reflected.
      *
-     * @param connectionTimeMillis The connection time, in milliseconds.
+     * @param connectionTimeMillis The connection time, in milliseconds, as returned by
+     *                             {@link System#currentTimeMillis()}.
      */
     public final void setConnectionTime(long connectionTimeMillis) {
         mConnectTimeMillis = connectionTimeMillis;
     }
 
     /**
-     * Sets the elapsed time since system boot when the {@link Conference} was connected.
-     * This is used to determine the duration of the {@link Conference}.
+     * Sets the start time of the {@link Conference} which is the basis for the determining the
+     * duration of the {@link Conference}.
      * <p>
-     * When setting the connection elapsed time, you should always set the connection time via
+     * You should use a value returned by {@link SystemClock#elapsedRealtime()} to ensure that time
+     * zone changes do not impact the conference duration.
+     * <p>
+     * When setting this, you should also set the connection time via
      * {@link #setConnectionTime(long)}.
      *
-     * @param connectionElapsedTime The connection time, as measured by
+     * @param connectionStartElapsedRealTime The connection time, as measured by
      * {@link SystemClock#elapsedRealtime()}.
      */
-    public final void setConnectionElapsedTime(long connectionElapsedTime) {
-        mConnectElapsedTimeMillis = connectionElapsedTime;
+    public final void setConnectionStartElapsedRealTime(long connectionStartElapsedRealTime) {
+        mConnectionStartElapsedRealTime = connectionStartElapsedRealTime;
     }
 
     /**
@@ -650,8 +655,8 @@
      * @return The elapsed time at which the {@link Conference} was connected.
      * @hide
      */
-    public final long getConnectElapsedTime() {
-        return mConnectElapsedTimeMillis;
+    public final long getConnectionStartElapsedRealTime() {
+        return mConnectionStartElapsedRealTime;
     }
 
     /**
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index fc19c9b..b1c1db1 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -41,6 +41,8 @@
 import android.util.ArraySet;
 import android.view.Surface;
 
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStreamReader;
 import java.io.OutputStreamWriter;
@@ -333,8 +335,10 @@
      *
      * @hide
      */
-    public static final int CAPABILITY_ADD_PARTICIPANT = 0x02000000;
+    public static final int CAPABILITY_ADD_PARTICIPANT = 0x04000000;
 
+    /** Call supports the deflect feature. */
+    public static final int CAPABILITY_SUPPORT_DEFLECT = 0x02000000;
 
     //**********************************************************************************************
     // Next CAPABILITY value: 0x04000000
@@ -734,6 +738,9 @@
         if (can(capabilities, CAPABILITY_CAN_PULL_CALL)) {
             builder.append(isLong ? " CAPABILITY_CAN_PULL_CALL" : " pull");
         }
+        if (can(capabilities, CAPABILITY_SUPPORT_DEFLECT)) {
+            builder.append(isLong ? " CAPABILITY_SUPPORT_DEFLECT" : " sup_def");
+        }
 
         builder.append("]");
         return builder.toString();
@@ -862,18 +869,19 @@
             mFdFromInCall = fromInCall;
             mFdToInCall = toInCall;
             mPipeFromInCall = new InputStreamReader(
-                    new ParcelFileDescriptor.AutoCloseInputStream(fromInCall));
+                    new FileInputStream(fromInCall.getFileDescriptor()));
             mPipeToInCall = new OutputStreamWriter(
-                    new ParcelFileDescriptor.AutoCloseOutputStream(toInCall));
+                    new FileOutputStream(toInCall.getFileDescriptor()));
         }
 
         /**
          * Writes the string {@param input} into the text stream to the UI for this RTT call. Since
          * RTT transmits text in real-time, this method should be called as often as text snippets
          * are received from the remote user, even if it is only one character.
-         *
+         * <p>
          * This method is not thread-safe -- calling it from multiple threads simultaneously may
          * lead to interleaved text.
+         *
          * @param input The message to send to the in-call app.
          */
         public void write(String input) throws IOException {
@@ -886,9 +894,10 @@
          * Reads a string from the in-call app, blocking if there is no data available. Returns
          * {@code null} if the RTT conversation has been terminated and there is no further data
          * to read.
-         *
+         * <p>
          * This method is not thread-safe -- calling it from multiple threads simultaneously may
          * lead to interleaved text.
+         *
          * @return A string containing text entered by the user, or {@code null} if the
          * conversation has been terminated or if there was an error while reading.
          */
@@ -903,6 +912,7 @@
         /**
          * Non-blocking version of {@link #read()}. Returns {@code null} if there is nothing to
          * be read.
+         *
          * @return A string containing text entered by the user, or {@code null} if the user has
          * not entered any new text yet.
          */
@@ -2301,7 +2311,7 @@
      *
      * @hide
      */
-    public final void setConnectElapsedTimeMillis(long connectElapsedTimeMillis) {
+    public final void setConnectionStartElapsedRealTime(long connectElapsedTimeMillis) {
         mConnectElapsedTimeMillis = connectElapsedTimeMillis;
     }
 
@@ -2637,7 +2647,6 @@
      * {@link #onStartRtt(RttTextStream)} has succeeded.
      */
     public final void sendRttInitiationSuccess() {
-        setRttProperty();
         mListeners.forEach((l) -> l.onRttInitiationSuccess(Connection.this));
     }
 
@@ -2649,7 +2658,6 @@
      *               exception of {@link RttModifyStatus#SESSION_MODIFY_REQUEST_SUCCESS}.
      */
     public final void sendRttInitiationFailure(int reason) {
-        unsetRttProperty();
         mListeners.forEach((l) -> l.onRttInitiationFailure(Connection.this, reason));
     }
 
@@ -2658,7 +2666,6 @@
      * side of the coll.
      */
     public final void sendRttSessionRemotelyTerminated() {
-        unsetRttProperty();
         mListeners.forEach((l) -> l.onRttSessionRemotelyTerminated(Connection.this));
     }
 
@@ -2745,7 +2752,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) {}
@@ -2753,6 +2773,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);
@@ -2760,7 +2794,27 @@
 
     /**
      * Notifies this Connection, which is in {@link #STATE_RINGING}, of
+     * a request to deflect.
+     */
+    public void onDeflect(Uri address) {}
+
+    /**
+     * 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() {}
 
@@ -2843,9 +2897,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.
@@ -2910,22 +2965,6 @@
      */
     public void handleRttUpgradeResponse(@Nullable RttTextStream rttTextStream) {}
 
-    /**
-     * Internal method to set {@link #PROPERTY_IS_RTT}.
-     * @hide
-     */
-    void setRttProperty() {
-        setConnectionProperties(getConnectionProperties() | PROPERTY_IS_RTT);
-    }
-
-    /**
-     * Internal method to un-set {@link #PROPERTY_IS_RTT}.
-     * @hide
-     */
-    void unsetRttProperty() {
-        setConnectionProperties(getConnectionProperties() & (~PROPERTY_IS_RTT));
-    }
-
     static String toLogSafePhoneNumber(String number) {
         // For unknown number, log empty string.
         if (number == null) {
diff --git a/telecomm/java/android/telecom/ConnectionRequest.java b/telecomm/java/android/telecom/ConnectionRequest.java
index 658b473..b6e6b0e 100644
--- a/telecomm/java/android/telecom/ConnectionRequest.java
+++ b/telecomm/java/android/telecom/ConnectionRequest.java
@@ -143,6 +143,8 @@
     private final boolean mShouldShowIncomingCallUi;
     private final ParcelFileDescriptor mRttPipeToInCall;
     private final ParcelFileDescriptor mRttPipeFromInCall;
+    // Cached return value of getRttTextStream -- we don't want to wrap it more than once.
+    private Connection.RttTextStream mRttTextStream;
 
     /**
      * @param accountHandle The accountHandle which should be used to place the call.
@@ -312,7 +314,10 @@
      */
     public Connection.RttTextStream getRttTextStream() {
         if (isRequestingRtt()) {
-            return new Connection.RttTextStream(mRttPipeToInCall, mRttPipeFromInCall);
+            if (mRttTextStream == null) {
+                mRttTextStream = new Connection.RttTextStream(mRttPipeToInCall, mRttPipeFromInCall);
+            }
+            return mRttTextStream;
         } else {
             return null;
         }
diff --git a/telecomm/java/android/telecom/ConnectionService.java b/telecomm/java/android/telecom/ConnectionService.java
index 109896a..9a5e08b 100644
--- a/telecomm/java/android/telecom/ConnectionService.java
+++ b/telecomm/java/android/telecom/ConnectionService.java
@@ -21,7 +21,6 @@
 import android.content.ComponentName;
 import android.content.Intent;
 import android.net.Uri;
-import android.os.Build;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
@@ -124,6 +123,7 @@
     private static final String SESSION_ABORT = "CS.ab";
     private static final String SESSION_ANSWER = "CS.an";
     private static final String SESSION_ANSWER_VIDEO = "CS.anV";
+    private static final String SESSION_DEFLECT = "CS.def";
     private static final String SESSION_REJECT = "CS.r";
     private static final String SESSION_REJECT_MESSAGE = "CS.rWM";
     private static final String SESSION_SILENCE = "CS.s";
@@ -143,6 +143,7 @@
     private static final String SESSION_HANDOVER_COMPLETE = "CS.hC";
     private static final String SESSION_EXTRAS_CHANGED = "CS.oEC";
     private static final String SESSION_START_RTT = "CS.+RTT";
+    private static final String SESSION_UPDATE_RTT_PIPES = "CS.uRTT";
     private static final String SESSION_STOP_RTT = "CS.-RTT";
     private static final String SESSION_RTT_UPGRADE_RESPONSE = "CS.rTRUR";
     private static final String SESSION_CONNECTION_SERVICE_FOCUS_LOST = "CS.cSFL";
@@ -181,6 +182,7 @@
     private static final int MSG_CONNECTION_SERVICE_FOCUS_GAINED = 31;
     private static final int MSG_HANDOVER_FAILED = 32;
     private static final int MSG_HANDOVER_COMPLETE = 33;
+    private static final int MSG_DEFLECT = 34;
     //Proprietary values starts after this.
     private static final int MSG_ADD_PARTICIPANT_WITH_CONFERENCE = 40;
 
@@ -355,6 +357,20 @@
         }
 
         @Override
+        public void deflect(String callId, Uri address, Session.Info sessionInfo) {
+            Log.startSession(sessionInfo, SESSION_DEFLECT);
+            try {
+                SomeArgs args = SomeArgs.obtain();
+                args.arg1 = callId;
+                args.arg2 = address;
+                args.arg3 = Log.createSubsession();
+                mHandler.obtainMessage(MSG_DEFLECT, args).sendToTarget();
+            } finally {
+                Log.endSession();
+            }
+        }
+
+        @Override
         public void reject(String callId, Session.Info sessionInfo) {
             Log.startSession(sessionInfo, SESSION_REJECT);
             try {
@@ -857,6 +873,17 @@
                     }
                     break;
                 }
+                case MSG_DEFLECT: {
+                    SomeArgs args = (SomeArgs) msg.obj;
+                    Log.continueSession((Session) args.arg3, SESSION_HANDLER + SESSION_DEFLECT);
+                    try {
+                        deflect((String) args.arg1, (Uri) args.arg2);
+                    } finally {
+                        args.recycle();
+                        Log.endSession();
+                    }
+                    break;
+                }
                 case MSG_REJECT: {
                     SomeArgs args = (SomeArgs) msg.obj;
                     Log.continueSession((Session) args.arg2, SESSION_HANDLER + SESSION_REJECT);
@@ -1626,6 +1653,11 @@
         findConnectionForAction(callId, "answer").onAnswer();
     }
 
+    private void deflect(String callId, Uri address) {
+        Log.d(this, "deflect %s", callId);
+        findConnectionForAction(callId, "deflect").onDeflect(address);
+    }
+
     private void reject(String callId) {
         Log.d(this, "reject %s", callId);
         findConnectionForAction(callId, "reject").onReject();
@@ -1865,7 +1897,6 @@
         Log.d(this, "stopRtt(%s)", callId);
         if (mConnectionById.containsKey(callId)) {
             findConnectionForAction(callId, "stopRtt").onStopRtt();
-            findConnectionForAction(callId, "stopRtt").unsetRttProperty();
         } else if (mConferenceById.containsKey(callId)) {
             Log.w(this, "stopRtt called on a conference.");
         }
@@ -2007,7 +2038,7 @@
                             null : conference.getVideoProvider().getInterface(),
                     conference.getVideoState(),
                     conference.getConnectTimeMillis(),
-                    conference.getConnectElapsedTime(),
+                    conference.getConnectionStartElapsedRealTime(),
                     conference.getStatusHints(),
                     conference.getExtras());
 
diff --git a/telecomm/java/android/telecom/DisconnectCause.java b/telecomm/java/android/telecom/DisconnectCause.java
index dcf5c27..1de67a5 100644
--- a/telecomm/java/android/telecom/DisconnectCause.java
+++ b/telecomm/java/android/telecom/DisconnectCause.java
@@ -33,47 +33,48 @@
 public final class DisconnectCause implements Parcelable {
 
     /** Disconnected because of an unknown or unspecified reason. */
-    public static final int UNKNOWN = 0;
+    public static final int UNKNOWN = TelecomProtoEnums.UNKNOWN; // = 0
     /** Disconnected because there was an error, such as a problem with the network. */
-    public static final int ERROR = 1;
+    public static final int ERROR = TelecomProtoEnums.ERROR; // = 1
     /** Disconnected because of a local user-initiated action, such as hanging up. */
-    public static final int LOCAL = 2;
+    public static final int LOCAL = TelecomProtoEnums.LOCAL; // = 2
     /**
      * Disconnected because of a remote user-initiated action, such as the other party hanging up
      * up.
      */
-    public static final int REMOTE = 3;
+    public static final int REMOTE = TelecomProtoEnums.REMOTE; // = 3
     /** Disconnected because it has been canceled. */
-    public static final int CANCELED = 4;
+    public static final int CANCELED = TelecomProtoEnums.CANCELED; // = 4
     /** Disconnected because there was no response to an incoming call. */
-    public static final int MISSED = 5;
+    public static final int MISSED = TelecomProtoEnums.MISSED; // = 5
     /** Disconnected because the user rejected an incoming call. */
-    public static final int REJECTED = 6;
+    public static final int REJECTED = TelecomProtoEnums.REJECTED; // = 6
     /** Disconnected because the other party was busy. */
-    public static final int BUSY = 7;
+    public static final int BUSY = TelecomProtoEnums.BUSY; // = 7
     /**
      * Disconnected because of a restriction on placing the call, such as dialing in airplane
      * mode.
      */
-    public static final int RESTRICTED = 8;
+    public static final int RESTRICTED = TelecomProtoEnums.RESTRICTED; // = 8
     /** Disconnected for reason not described by other disconnect codes. */
-    public static final int OTHER = 9;
+    public static final int OTHER = TelecomProtoEnums.OTHER; // = 9
     /**
      * Disconnected because the connection manager did not support the call. The call will be tried
      * again without a connection manager. See {@link PhoneAccount#CAPABILITY_CONNECTION_MANAGER}.
      */
-    public static final int CONNECTION_MANAGER_NOT_SUPPORTED = 10;
+    public static final int CONNECTION_MANAGER_NOT_SUPPORTED =
+            TelecomProtoEnums.CONNECTION_MANAGER_NOT_SUPPORTED; // = 10
 
     /**
      * Disconnected because the user did not locally answer the incoming call, but it was answered
      * on another device where the call was ringing.
      */
-    public static final int ANSWERED_ELSEWHERE = 11;
+    public static final int ANSWERED_ELSEWHERE = TelecomProtoEnums.ANSWERED_ELSEWHERE; // = 11
 
     /**
      * Disconnected because the call was pulled from the current device to another device.
      */
-    public static final int CALL_PULLED = 12;
+    public static final int CALL_PULLED = TelecomProtoEnums.CALL_PULLED; // = 12
 
     /**
      * Reason code (returned via {@link #getReason()}) which indicates that a call could not be
diff --git a/telecomm/java/android/telecom/InCallAdapter.java b/telecomm/java/android/telecom/InCallAdapter.java
index 658685f..8678e33 100644
--- a/telecomm/java/android/telecom/InCallAdapter.java
+++ b/telecomm/java/android/telecom/InCallAdapter.java
@@ -16,6 +16,7 @@
 
 package android.telecom;
 
+import android.net.Uri;
 import android.bluetooth.BluetoothDevice;
 import android.os.Bundle;
 import android.os.RemoteException;
@@ -61,6 +62,19 @@
     }
 
     /**
+     * Instructs Telecom to deflect the specified call.
+     *
+     * @param callId The identifier of the call to deflect.
+     * @param address The address to deflect.
+     */
+    public void deflectCall(String callId, Uri address) {
+        try {
+            mAdapter.deflectCall(callId, address);
+        } catch (RemoteException e) {
+        }
+    }
+
+    /**
      * Instructs Telecom to reject the specified call.
      *
      * @param callId The identifier of the call to reject.
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/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index 1fe5db5..a180da6 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -1320,7 +1320,7 @@
     public boolean endCall() {
         try {
             if (isServiceConnected()) {
-                return getTelecomService().endCall();
+                return getTelecomService().endCall(mContext.getPackageName());
             }
         } catch (RemoteException e) {
             Log.e(TAG, "Error calling ITelecomService#endCall", e);
diff --git a/telecomm/java/com/android/internal/telecom/IConnectionService.aidl b/telecomm/java/com/android/internal/telecom/IConnectionService.aidl
index 803b0e2..acb3e6f 100644
--- a/telecomm/java/com/android/internal/telecom/IConnectionService.aidl
+++ b/telecomm/java/com/android/internal/telecom/IConnectionService.aidl
@@ -16,6 +16,7 @@
 
 package com.android.internal.telecom;
 
+import android.net.Uri;
 import android.os.Bundle;
 import android.os.ParcelFileDescriptor;
 import android.telecom.CallAudioState;
@@ -58,6 +59,8 @@
 
     void answer(String callId, in Session.Info sessionInfo);
 
+    void deflect(String callId, in Uri address, in Session.Info sessionInfo);
+
     void reject(String callId, in Session.Info sessionInfo);
 
     void rejectWithMessage(String callId, String message, in Session.Info sessionInfo);
diff --git a/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl b/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl
index 87ccd3e..57df5c1 100644
--- a/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl
+++ b/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl
@@ -16,6 +16,7 @@
 
 package com.android.internal.telecom;
 
+import android.net.Uri;
 import android.os.Bundle;
 import android.telecom.PhoneAccountHandle;
 
@@ -29,6 +30,8 @@
 oneway interface IInCallAdapter {
     void answerCall(String callId, int videoState);
 
+    void deflectCall(String callId, in Uri address);
+
     void rejectCall(String callId, boolean rejectWithMessage, String textMessage);
 
     void disconnectCall(String callId);
diff --git a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
index 3460754..b4e7d56 100644
--- a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
+++ b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
@@ -187,7 +187,7 @@
     /**
      * @see TelecomServiceImpl#endCall
      */
-    boolean endCall();
+    boolean endCall(String callingPackage);
 
     /**
      * @see TelecomServiceImpl#acceptRingingCall
diff --git a/telephony/OWNERS b/telephony/OWNERS
new file mode 100644
index 0000000..6f67bc2
--- /dev/null
+++ b/telephony/OWNERS
@@ -0,0 +1,14 @@
+set noparent
+
+tgunn@google.com
+breadley@google.com
+hallliu@google.com
+rgreenwalt@google.com
+mpq@google.com
+amitmahajan@google.com
+fionaxu@google.com
+jackyu@google.com
+jminjie@google.com
+satk@google.com
+shuoq@google.com
+refuhoo@google.com
diff --git a/telephony/java/android/provider/Telephony.java b/telephony/java/android/provider/Telephony.java
index 8f41c4e..41ce93c 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;
 
@@ -3392,73 +3393,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/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 7eb691b..c8c898a 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -1376,6 +1376,12 @@
      */
     public static final String KEY_ALLOW_HOLD_IN_IMS_CALL_BOOL = "allow_hold_in_ims_call";
 
+    /**
+     * Flag indicating whether the carrier supports call deflection for an incoming IMS call.
+     * @hide
+     */
+    public static final String KEY_CARRIER_ALLOW_DEFLECT_IMS_CALL_BOOL =
+            "carrier_allow_deflect_ims_call_bool";
 
     /**
      * Flag indicating whether the carrier always wants to play an "on-hold" tone when a call has
@@ -1844,6 +1850,7 @@
     static {
         sDefaults = new PersistableBundle();
         sDefaults.putBoolean(KEY_ALLOW_HOLD_IN_IMS_CALL_BOOL, true);
+        sDefaults.putBoolean(KEY_CARRIER_ALLOW_DEFLECT_IMS_CALL_BOOL, false);
         sDefaults.putBoolean(KEY_ALWAYS_PLAY_REMOTE_HOLD_TONE_BOOL, false);
         sDefaults.putBoolean(KEY_ADDITIONAL_CALL_SETTING_BOOL, true);
         sDefaults.putBoolean(KEY_ALLOW_EMERGENCY_NUMBERS_IN_CALL_LOG_BOOL, false);
diff --git a/telephony/java/android/telephony/CellSignalStrengthLte.java b/telephony/java/android/telephony/CellSignalStrengthLte.java
index f009fb1..7e86966 100644
--- a/telephony/java/android/telephony/CellSignalStrengthLte.java
+++ b/telephony/java/android/telephony/CellSignalStrengthLte.java
@@ -172,7 +172,7 @@
     }
 
     /**
-     * Get the timing advance value for LTE, as a value between 0..63.
+     * Get the timing advance value for LTE, as a value in range of 0..1282.
      * Integer.MAX_VALUE is reported when there is no active RRC
      * connection. Refer to 3GPP 36.213 Sec 4.2.3
      * @return the LTE timing advance, if available.
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index cb867ab..ec348df 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -1526,7 +1526,9 @@
      */
     @SystemApi
     public List<NetworkRegistrationState> getNetworkRegistrationStates() {
-        return mNetworkRegistrationStates;
+        synchronized (mNetworkRegistrationStates) {
+            return new ArrayList<>(mNetworkRegistrationStates);
+        }
     }
 
     /**
@@ -1539,11 +1541,15 @@
     @SystemApi
     public List<NetworkRegistrationState> getNetworkRegistrationStates(int transportType) {
         List<NetworkRegistrationState> list = new ArrayList<>();
-        for (NetworkRegistrationState networkRegistrationState : mNetworkRegistrationStates) {
-            if (networkRegistrationState.getTransportType() == transportType) {
-                list.add(networkRegistrationState);
+
+        synchronized (mNetworkRegistrationStates) {
+            for (NetworkRegistrationState networkRegistrationState : mNetworkRegistrationStates) {
+                if (networkRegistrationState.getTransportType() == transportType) {
+                    list.add(networkRegistrationState);
+                }
             }
         }
+
         return list;
     }
 
@@ -1557,12 +1563,36 @@
      */
     @SystemApi
     public NetworkRegistrationState getNetworkRegistrationStates(int transportType, int domain) {
-        for (NetworkRegistrationState networkRegistrationState : mNetworkRegistrationStates) {
-            if (networkRegistrationState.getTransportType() == transportType
-                    && networkRegistrationState.getDomain() == domain) {
-                return networkRegistrationState;
+        synchronized (mNetworkRegistrationStates) {
+            for (NetworkRegistrationState networkRegistrationState : mNetworkRegistrationStates) {
+                if (networkRegistrationState.getTransportType() == transportType
+                        && networkRegistrationState.getDomain() == domain) {
+                    return networkRegistrationState;
+                }
             }
         }
+
         return null;
     }
+
+    /**
+     * @hide
+     */
+    public void addNetworkRegistrationState(NetworkRegistrationState regState) {
+        if (regState == null) return;
+
+        synchronized (mNetworkRegistrationStates) {
+            for (int i = 0; i < mNetworkRegistrationStates.size(); i++) {
+                NetworkRegistrationState curRegState = mNetworkRegistrationStates.get(i);
+                if (curRegState.getTransportType() == regState.getTransportType()
+                        && curRegState.getDomain() == regState.getDomain()) {
+                    mNetworkRegistrationStates.remove(i);
+                    break;
+                }
+            }
+
+            mNetworkRegistrationStates.add(regState);
+        }
+    }
+
 }
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 03a8f33..fefc03d 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -53,6 +53,7 @@
 import android.telephony.ims.aidl.IImsRcsFeature;
 import android.telephony.ims.aidl.IImsRegistration;
 import android.telephony.ims.feature.ImsFeature;
+import android.telephony.ims.stub.ImsRegistrationImplBase;
 import android.util.Log;
 
 import com.android.ims.internal.IImsServiceFeatureCallback;
@@ -904,6 +905,61 @@
     public static final String EVENT_CALL_FORWARDED =
             "android.telephony.event.EVENT_CALL_FORWARDED";
 
+    /**
+     * {@link android.telecom.Connection} event used to indicate that a supplementary service
+     * notification has been received.
+     * <p>
+     * Sent via {@link android.telecom.Connection#sendConnectionEvent(String, Bundle)}.
+     * The {@link Bundle} parameter is expected to include the following extras:
+     * <ul>
+     *     <li>{@link #EXTRA_NOTIFICATION_TYPE} - the notification type.</li>
+     *     <li>{@link #EXTRA_NOTIFICATION_CODE} - the notification code.</li>
+     *     <li>{@link #EXTRA_NOTIFICATION_MESSAGE} - human-readable message associated with the
+     *     supplementary service notification.</li>
+     * </ul>
+     * @hide
+     */
+    public static final String EVENT_SUPPLEMENTARY_SERVICE_NOTIFICATION =
+            "android.telephony.event.EVENT_SUPPLEMENTARY_SERVICE_NOTIFICATION";
+
+    /**
+     * Integer extra key used with {@link #EVENT_SUPPLEMENTARY_SERVICE_NOTIFICATION} which indicates
+     * the type of supplementary service notification which occurred.
+     * Will be either
+     * {@link com.android.internal.telephony.gsm.SuppServiceNotification#NOTIFICATION_TYPE_CODE_1}
+     * or
+     * {@link com.android.internal.telephony.gsm.SuppServiceNotification#NOTIFICATION_TYPE_CODE_2}
+     * <p>
+     * Set in the extras for the {@link #EVENT_SUPPLEMENTARY_SERVICE_NOTIFICATION} connection event.
+     * @hide
+     */
+    public static final String EXTRA_NOTIFICATION_TYPE =
+            "android.telephony.extra.NOTIFICATION_TYPE";
+
+    /**
+     * Integer extra key used with {@link #EVENT_SUPPLEMENTARY_SERVICE_NOTIFICATION} which indicates
+     * the supplementary service notification which occurred.
+     * <p>
+     * Depending on the {@link #EXTRA_NOTIFICATION_TYPE}, the code will be one of the {@code CODE_*}
+     * codes defined in {@link com.android.internal.telephony.gsm.SuppServiceNotification}.
+     * <p>
+     * Set in the extras for the {@link #EVENT_SUPPLEMENTARY_SERVICE_NOTIFICATION} connection event.
+     * @hide
+     */
+    public static final String EXTRA_NOTIFICATION_CODE =
+            "android.telephony.extra.NOTIFICATION_CODE";
+
+    /**
+     * {@link CharSequence} extra key used with {@link #EVENT_SUPPLEMENTARY_SERVICE_NOTIFICATION}
+     * which contains a human-readable message which can be displayed to the user for the
+     * supplementary service notification.
+     * <p>
+     * Set in the extras for the {@link #EVENT_SUPPLEMENTARY_SERVICE_NOTIFICATION} connection event.
+     * @hide
+     */
+    public static final String EXTRA_NOTIFICATION_MESSAGE =
+            "android.telephony.extra.NOTIFICATION_MESSAGE";
+
     /* Visual voicemail protocols */
 
     /**
@@ -4746,7 +4802,7 @@
     }
 
     /**
-     * Sets the telephony property with the value specified.
+     * Sets a per-phone telephony property with the value specified.
      *
      * @hide
      */
@@ -4796,6 +4852,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
@@ -4884,7 +4954,7 @@
     }
 
     /**
-     * Gets the telephony property.
+     * Gets a per-phone telephony property.
      *
      * @hide
      */
@@ -4900,6 +4970,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!
@@ -6328,84 +6411,106 @@
         return false;
     }
 
-   /**
-    * Returns the IMS Registration Status
-    * @hide
-    */
-   public boolean isImsRegistered() {
-       try {
-           ITelephony telephony = getITelephony();
-           if (telephony == null)
-               return false;
-           return telephony.isImsRegistered();
-       } catch (RemoteException ex) {
-           return false;
-       } catch (NullPointerException ex) {
-           return false;
-       }
-   }
-
     /**
-     * Returns the IMS Registration Status for a particular Subscription ID
+     * Returns the IMS Registration Status for a particular Subscription ID.
      *
      * @param subId Subscription ID
      * @return true if IMS status is registered, false if the IMS status is not registered or a
      * RemoteException occurred.
-     *
      * @hide
      */
     public boolean isImsRegistered(int subId) {
-       try {
-           return getITelephony().isImsRegisteredForSubscriber(subId);
-       } catch (RemoteException ex) {
-           return false;
-       } catch (NullPointerException ex) {
-           return false;
-       }
-    }
-
-    /**
-     * Returns the Status of Volte
-     * @hide
-     */
-    public boolean isVolteAvailable() {
-       try {
-           return getITelephony().isVolteAvailable();
-       } catch (RemoteException ex) {
-           return false;
-       } catch (NullPointerException ex) {
-           return false;
-       }
-   }
-
-    /**
-     * Returns the Status of video telephony (VT)
-     * @hide
-     */
-    public boolean isVideoTelephonyAvailable() {
         try {
-            return getITelephony().isVideoTelephonyAvailable();
-        } catch (RemoteException ex) {
-            return false;
-        } catch (NullPointerException ex) {
+            return getITelephony().isImsRegistered(subId);
+        } catch (RemoteException | NullPointerException ex) {
             return false;
         }
     }
 
     /**
-     * Returns the Status of Wi-Fi Calling
+     * Returns the IMS Registration Status for a particular Subscription ID, which is determined
+     * when the TelephonyManager is created using {@link #createForSubscriptionId(int)}. If an
+     * invalid subscription ID is used during creation, will the default subscription ID will be
+     * used.
+     *
+     * @return true if IMS status is registered, false if the IMS status is not registered or a
+     * RemoteException occurred.
+     * @see SubscriptionManager#getDefaultSubscriptionId()
+     * @hide
+     */
+    public boolean isImsRegistered() {
+       try {
+           return getITelephony().isImsRegistered(getSubId());
+       } catch (RemoteException | NullPointerException ex) {
+           return false;
+       }
+    }
+
+    /**
+     * The current status of Voice over LTE for the subscription associated with this instance when
+     * it was created using {@link #createForSubscriptionId(int)}. If an invalid subscription ID was
+     * used during creation, the default subscription ID will be used.
+     * @return true if Voice over LTE is available or false if it is unavailable or unknown.
+     * @see SubscriptionManager#getDefaultSubscriptionId()
+     * @hide
+     */
+    public boolean isVolteAvailable() {
+        try {
+            return getITelephony().isVolteAvailable(getSubId());
+        } catch (RemoteException | NullPointerException ex) {
+            return false;
+        }
+    }
+
+    /**
+     * The availability of Video Telephony (VT) for the subscription ID specified when this instance
+     * was created using {@link #createForSubscriptionId(int)}. If an invalid subscription ID was
+     * used during creation, the default subscription ID will be used. To query the
+     * underlying technology that VT is available on, use {@link #getImsRegTechnologyForMmTel}.
+     * @return true if VT is available, or false if it is unavailable or unknown.
+     * @hide
+     */
+    public boolean isVideoTelephonyAvailable() {
+        try {
+            return getITelephony().isVideoTelephonyAvailable(getSubId());
+        } catch (RemoteException | NullPointerException ex) {
+            return false;
+        }
+    }
+
+    /**
+     * Returns the Status of Wi-Fi calling (Voice over WiFi) for the subscription ID specified.
+     * @param subId the subscription ID.
+     * @return true if VoWiFi is available, or false if it is unavailable or unknown.
      * @hide
      */
     public boolean isWifiCallingAvailable() {
        try {
-           return getITelephony().isWifiCallingAvailable();
-       } catch (RemoteException ex) {
-           return false;
-       } catch (NullPointerException ex) {
+           return getITelephony().isWifiCallingAvailable(getSubId());
+       } catch (RemoteException | NullPointerException ex) {
            return false;
        }
    }
 
+    /**
+     * The technology that IMS is registered for for the MMTEL feature.
+     * @param subId subscription ID to get IMS registration technology for.
+     * @return The IMS registration technology that IMS is registered to for the MMTEL feature.
+     * Valid return results are:
+     *  - {@link ImsRegistrationImplBase#REGISTRATION_TECH_LTE} for LTE registration,
+     *  - {@link ImsRegistrationImplBase#REGISTRATION_TECH_IWLAN} for IWLAN registration, or
+     *  - {@link ImsRegistrationImplBase#REGISTRATION_TECH_NONE} if we are not registered or the
+     *  result is unavailable.
+     *  @hide
+     */
+    public @ImsRegistrationImplBase.ImsRegistrationTech int getImsRegTechnologyForMmTel() {
+        try {
+            return getITelephony().getImsRegTechnologyForMmTel(getSubId());
+        } catch (RemoteException ex) {
+            return ImsRegistrationImplBase.REGISTRATION_TECH_NONE;
+        }
+    }
+
    /**
     * Set TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC for the default phone.
     *
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/UiccSlotInfo.java b/telephony/java/android/telephony/UiccSlotInfo.java
index 0b3cbad..0c17147 100644
--- a/telephony/java/android/telephony/UiccSlotInfo.java
+++ b/telephony/java/android/telephony/UiccSlotInfo.java
@@ -55,10 +55,11 @@
     /** Card state restricted. */
     public static final int CARD_STATE_INFO_RESTRICTED = 4;
 
-    public final boolean isActive;
-    public final boolean isEuicc;
-    public final String cardId;
-    public final @CardStateInfo int cardStateInfo;
+    private final boolean mIsActive;
+    private final boolean mIsEuicc;
+    private final String mCardId;
+    private final @CardStateInfo int mCardStateInfo;
+    private final int mLogicalSlotIdx;
 
     public static final Creator<UiccSlotInfo> CREATOR = new Creator<UiccSlotInfo>() {
         @Override
@@ -73,18 +74,20 @@
     };
 
     private UiccSlotInfo(Parcel in) {
-        isActive = in.readByte() != 0;
-        isEuicc = in.readByte() != 0;
-        cardId = in.readString();
-        cardStateInfo = in.readInt();
+        mIsActive = in.readByte() != 0;
+        mIsEuicc = in.readByte() != 0;
+        mCardId = in.readString();
+        mCardStateInfo = in.readInt();
+        mLogicalSlotIdx = in.readInt();
     }
 
     @Override
     public void writeToParcel(Parcel dest, int flags) {
-        dest.writeByte((byte) (isActive ? 1 : 0));
-        dest.writeByte((byte) (isEuicc ? 1 : 0));
-        dest.writeString(cardId);
-        dest.writeInt(cardStateInfo);
+        dest.writeByte((byte) (mIsActive ? 1 : 0));
+        dest.writeByte((byte) (mIsEuicc ? 1 : 0));
+        dest.writeString(mCardId);
+        dest.writeInt(mCardStateInfo);
+        dest.writeInt(mLogicalSlotIdx);
     }
 
     @Override
@@ -93,28 +96,33 @@
     }
 
     public UiccSlotInfo(boolean isActive, boolean isEuicc, String cardId,
-            @CardStateInfo int cardStateInfo) {
-        this.isActive = isActive;
-        this.isEuicc = isEuicc;
-        this.cardId = cardId;
-        this.cardStateInfo = cardStateInfo;
+            @CardStateInfo int cardStateInfo, int logicalSlotIdx) {
+        this.mIsActive = isActive;
+        this.mIsEuicc = isEuicc;
+        this.mCardId = cardId;
+        this.mCardStateInfo = cardStateInfo;
+        this.mLogicalSlotIdx = logicalSlotIdx;
     }
 
     public boolean getIsActive() {
-        return isActive;
+        return mIsActive;
     }
 
     public boolean getIsEuicc() {
-        return isEuicc;
+        return mIsEuicc;
     }
 
     public String getCardId() {
-        return cardId;
+        return mCardId;
     }
 
     @CardStateInfo
     public int getCardStateInfo() {
-        return cardStateInfo;
+        return mCardStateInfo;
+    }
+
+    public int getLogicalSlotIdx() {
+        return mLogicalSlotIdx;
     }
 
     @Override
@@ -127,32 +135,36 @@
         }
 
         UiccSlotInfo that = (UiccSlotInfo) obj;
-        return (isActive == that.isActive)
-                && (isEuicc == that.isEuicc)
-                && (cardId == that.cardId)
-                && (cardStateInfo == that.cardStateInfo);
+        return (mIsActive == that.mIsActive)
+                && (mIsEuicc == that.mIsEuicc)
+                && (mCardId == that.mCardId)
+                && (mCardStateInfo == that.mCardStateInfo)
+                && (mLogicalSlotIdx == that.mLogicalSlotIdx);
     }
 
     @Override
     public int hashCode() {
         int result = 1;
-        result = 31 * result + (isActive ? 1 : 0);
-        result = 31 * result + (isEuicc ? 1 : 0);
-        result = 31 * result + Objects.hashCode(cardId);
-        result = 31 * result + cardStateInfo;
+        result = 31 * result + (mIsActive ? 1 : 0);
+        result = 31 * result + (mIsEuicc ? 1 : 0);
+        result = 31 * result + Objects.hashCode(mCardId);
+        result = 31 * result + mCardStateInfo;
+        result = 31 * result + mLogicalSlotIdx;
         return result;
     }
 
     @Override
     public String toString() {
-        return "UiccSlotInfo (isActive="
-                + isActive
-                + ", isEuicc="
-                + isEuicc
-                + ", cardId="
-                + cardId
+        return "UiccSlotInfo (mIsActive="
+                + mIsActive
+                + ", mIsEuicc="
+                + mIsEuicc
+                + ", mCardId="
+                + mCardId
                 + ", cardState="
-                + cardStateInfo
+                + mCardStateInfo
+                + ", phoneId="
+                + mLogicalSlotIdx
                 + ")";
     }
 }
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/telephony/java/android/telephony/ims/ImsCallSession.java b/telephony/java/android/telephony/ims/ImsCallSession.java
index c3d103f..a20d4f5 100644
--- a/telephony/java/android/telephony/ims/ImsCallSession.java
+++ b/telephony/java/android/telephony/ims/ImsCallSession.java
@@ -754,6 +754,22 @@
     }
 
     /**
+     * Deflects an incoming call.
+     *
+     * @param number number to be deflected to
+     */
+    public void deflect(String number) {
+        if (mClosed) {
+            return;
+        }
+
+        try {
+            miSession.deflect(number);
+        } catch (RemoteException e) {
+        }
+    }
+
+    /**
      * Rejects an incoming call or session update.
      *
      * @param reason reason code to reject an incoming call
diff --git a/telephony/java/android/telephony/ims/compat/stub/ImsCallSessionImplBase.java b/telephony/java/android/telephony/ims/compat/stub/ImsCallSessionImplBase.java
index 00cb1e2..e5ed825 100644
--- a/telephony/java/android/telephony/ims/compat/stub/ImsCallSessionImplBase.java
+++ b/telephony/java/android/telephony/ims/compat/stub/ImsCallSessionImplBase.java
@@ -182,6 +182,15 @@
     }
 
     /**
+     * Deflects an incoming call.
+     *
+     * @param deflectNumber number to deflect the call
+     */
+    @Override
+    public void deflect(String deflectNumber) {
+    }
+
+    /**
      * Rejects an incoming call or session update.
      *
      * @param reason reason code to reject an incoming call, defined in {@link ImsReasonInfo}.
diff --git a/telephony/java/android/telephony/ims/feature/ImsFeature.java b/telephony/java/android/telephony/ims/feature/ImsFeature.java
index bfdd453..1fdbae9 100644
--- a/telephony/java/android/telephony/ims/feature/ImsFeature.java
+++ b/telephony/java/android/telephony/ims/feature/ImsFeature.java
@@ -80,7 +80,7 @@
     public static final String EXTRA_PHONE_ID = "android:phone_id";
 
     /**
-     * Invalid feature value\
+     * Invalid feature value
      * @hide
      */
     public static final int FEATURE_INVALID = -1;
diff --git a/telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java b/telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java
index c6ca6fd..7b9fe2b 100644
--- a/telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java
@@ -174,6 +174,11 @@
         }
 
         @Override
+        public void deflect(String deflectNumber) {
+            ImsCallSessionImplBase.this.deflect(deflectNumber);
+        }
+
+        @Override
         public void reject(int reason) {
             ImsCallSessionImplBase.this.reject(reason);
         }
@@ -395,6 +400,14 @@
     }
 
     /**
+     * Deflects an incoming call.
+     *
+     * @param deflectNumber number to deflect the call
+     */
+    public void deflect(String deflectNumber) {
+    }
+
+    /**
      * Rejects an incoming call or session update.
      *
      * @param reason reason code to reject an incoming call, defined in {@link ImsReasonInfo}.
diff --git a/telephony/java/com/android/ims/internal/IImsCallSession.aidl b/telephony/java/com/android/ims/internal/IImsCallSession.aidl
index 203e6cf..15234e5 100644
--- a/telephony/java/com/android/ims/internal/IImsCallSession.aidl
+++ b/telephony/java/com/android/ims/internal/IImsCallSession.aidl
@@ -136,6 +136,13 @@
     void accept(int callType, in ImsStreamMediaProfile profile);
 
     /**
+     * Deflects an incoming call.
+     *
+     * @param deflectNumber number to deflect the call
+     */
+    void deflect(String deflectNumber);
+
+    /**
      * Rejects an incoming call or session update.
      *
      * @param reason reason code to reject an incoming call
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 2b4c059..02cc82c 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -1123,33 +1123,33 @@
     boolean isHearingAidCompatibilitySupported();
 
     /**
-     * Get IMS Registration Status
-     */
-    boolean isImsRegistered();
-
-    /**
      * Get IMS Registration Status on a particular subid.
      *
      * @param subId user preferred subId.
      *
      * @return {@code true} if the IMS status is registered.
      */
-    boolean isImsRegisteredForSubscriber(int subId);
+    boolean isImsRegistered(int subId);
 
     /**
-     * Returns the Status of Wi-Fi Calling
+     * Returns the Status of Wi-Fi Calling for the subscription id specified.
      */
-    boolean isWifiCallingAvailable();
+    boolean isWifiCallingAvailable(int subId);
 
     /**
-     * Returns the Status of Volte
+     * Returns the Status of VoLTE for the subscription ID specified.
      */
-    boolean isVolteAvailable();
+    boolean isVolteAvailable(int subId);
 
      /**
-     * Returns the Status of VT (video telephony)
+     * Returns the Status of VT (video telephony) for the subscription ID specified.
      */
-    boolean isVideoTelephonyAvailable();
+    boolean isVideoTelephonyAvailable(int subId);
+
+    /**
+    * Returns the MMTEL IMS registration technology for the subsciption ID specified.
+    */
+    int getImsRegTechnologyForMmTel(int subId);
 
     /**
       * Returns the unique device ID of phone, for example, the IMEI for
diff --git a/test-base/Android.bp b/test-base/Android.bp
index 62fed61..b65cda9 100644
--- a/test-base/Android.bp
+++ b/test-base/Android.bp
@@ -24,6 +24,9 @@
 
     srcs: ["src/**/*.java"],
 
+    // Needs to be consistent with the repackaged version of this make target.
+    java_version: "1.8",
+
     no_framework_libs: true,
     hostdex: true,
     libs: [
@@ -55,21 +58,22 @@
     name: "repackaged.android.test.base",
 
     static_libs: ["android.test.base"],
-
     no_framework_libs: true,
     libs: [
         "framework",
     ],
 
     jarjar_rules: "jarjar-rules.txt",
+    // Pin java_version until jarjar is certified to support later versions. http://b/72703434
+    java_version: "1.8",
 }
 
 // Build the android.test.base-minus-junit library
 // ===============================================
 // This contains the android.test classes from android.test.base plus
 // the com.android.internal.util.Predicate[s] classes. This is only
-// intended for inclusion in the android.test.legacy static library and
-// must not be used elsewhere.
+// intended for inclusion in the android.test.legacy and
+// legacy-android-test static libraries and must not be used elsewhere.
 java_library_static {
     name: "android.test.base-minus-junit",
 
diff --git a/test-mock/Android.bp b/test-mock/Android.bp
index b1ae40e..54e07a16 100644
--- a/test-mock/Android.bp
+++ b/test-mock/Android.bp
@@ -19,6 +19,8 @@
 java_library {
     name: "android.test.mock",
 
+    // Needs to be consistent with the repackaged version of this make target.
+    java_version: "1.8",
     srcs: ["src/**/*.java"],
 
     no_framework_libs: true,
@@ -35,4 +37,6 @@
     static_libs: ["android.test.mock"],
 
     jarjar_rules: "jarjar-rules.txt",
+    // Pin java_version until jarjar is certified to support later versions. http://b/72703434
+    java_version: "1.8",
 }
diff --git a/test-runner/Android.bp b/test-runner/Android.bp
index dfaeed5..66b9527 100644
--- a/test-runner/Android.bp
+++ b/test-runner/Android.bp
@@ -19,6 +19,8 @@
 java_library {
     name: "android.test.runner",
 
+    // Needs to be consistent with the repackaged version of this make target.
+    java_version: "1.8",
     srcs: ["src/**/*.java"],
 
     no_framework_libs: true,
@@ -31,7 +33,8 @@
 
 // Build the android.test.runner-minus-junit library
 // =================================================
-// This is provided solely for use by the legacy-android-test module.
+// This is only intended for inclusion in the android.test.legacy and
+// legacy-android-test static libraries and must not be used elsewhere.
 java_library {
     name: "android.test.runner-minus-junit",
 
@@ -54,4 +57,6 @@
     static_libs: ["android.test.runner"],
 
     jarjar_rules: "jarjar-rules.txt",
+    // Pin java_version until jarjar is certified to support later versions. http://b/72703434
+    java_version: "1.8",
 }
diff --git a/tests/ActivityManagerPerfTests/README.txt b/tests/ActivityManagerPerfTests/README.txt
index 77e0e90..1040ed1 100644
--- a/tests/ActivityManagerPerfTests/README.txt
+++ b/tests/ActivityManagerPerfTests/README.txt
@@ -1,12 +1,15 @@
 ActivityManagerPerfTests
 
 Performance tests for various ActivityManager components, e.g. Services, Broadcasts
+* These are only for tests that don't require a target package to test against
+* Self-contained perf tests should go in frameworks/base/apct-tests/perftests
 
-Command to run tests (not working yet, atest seems buggy)
-* atest .../frameworks/base/tests/ActivityManagerPerfTests
+Command to run tests
+* atest .../frameworks/base/tests/ActivityManagerPerfTests/tests/
+  * Command currently not working: b/71859981
 * m ActivityManagerPerfTests ActivityManagerPerfTestsTestApp && \
-  adb install $OUT/data/app/ActivityManagerPerfTests/ActivityManagerPerfTests.apk && \
-  adb install $OUT/data/app/ActivityManagerPerfTestsTestApp/ActivityManagerPerfTestsTestApp.apk && \
+  adb install "$OUT"/data/app/ActivityManagerPerfTests/ActivityManagerPerfTests.apk && \
+  adb install "$OUT"/data/app/ActivityManagerPerfTestsTestApp/ActivityManagerPerfTestsTestApp.apk && \
   adb shell am instrument -w \
   com.android.frameworks.perftests.amtests/android.support.test.runner.AndroidJUnitRunner
 
@@ -15,20 +18,42 @@
   * For example, the time it takes from sending an Intent to start a Service
     to the time the Service runs its callbacks
 * System.nanoTime() is monotonic and consistent between processes, so we use that for measuring time
-* To make sure the test app is running, we start an Activity
 * If the test app is involved, it will measure the time and send it back to the instrumentation test
-  * The time is sent back through a Binder interface in the Intent
+  * The time is sent back through a Binder interface in the Intent with the help of Utils.sendTime()
   * Each sent time is tagged with an id since there can be multiple events that send back a time
-    * For example, one is sent when the Activity is started, and another could be sent when a
-      Broadcast is received
+* Each test will run multiple times to account for variation in test runs
 
 Structure
 * tests
   * Instrumentation test which runs the various performance tests and reports the results
-
 * test-app
   * Target package which contains the Services, BroadcastReceivers, etc. to test against
   * Sends the time it measures back to the test package
-
 * utils
   * Utilities that both the instrumentation test and test app can use
+
+Adding tests
+* Example
+  * Look at tests/src/com/android/frameworks/perftests/am/BroadcastPerfTest and
+    test-app/src/com/android/frameworks/perftests/amteststestapp/TestBroadcastReceiver
+    for simple examples using this framework
+* Steps
+  * Add any components you will test against in the target package under
+    test-app/src/com/android/frameworks/perftests/amteststestapp/
+  * Add the test class under tests/src/com/android/frameworks/perftests/am/tests/
+    * The class should extend BasePerfTest
+    * Each test should call runPerfFunction() returning the elapsed time for a single iteration
+    * The test has access to a Context through mContext
+  * If you are measuring the time elapsed of something that either starts or ends in the target
+    package
+    * The target package can report the time it measures through an ITimeReceiverCallback passed
+      through an Intent through Utils.sendTime(intent, "tag")
+      (or however a Binder needs to be passed to the target package)
+    * The instrumentation test can collect that time by calling getReceivedTimeNs("tag") and
+      calculate the elapsed time
+    * Each timestamp sent to the instrumentation test is tagged with a tag since multiple timestamps
+      can be reported in an iteration
+  * If the target package should be running before your test logic starts, add startTargetPackage();
+    at the beginning of the iteration
+* Reporting
+  * Look at go/am-perf for how to add new tests to dashboards and receive notification on regression
diff --git a/tests/ActivityManagerPerfTests/test-app/Android.mk b/tests/ActivityManagerPerfTests/test-app/Android.mk
index b0a5db7..767e899 100644
--- a/tests/ActivityManagerPerfTests/test-app/Android.mk
+++ b/tests/ActivityManagerPerfTests/test-app/Android.mk
@@ -23,6 +23,8 @@
 LOCAL_STATIC_JAVA_LIBRARIES := \
     ActivityManagerPerfTestsUtils
 
+LOCAL_MIN_SDK_VERSION := 25
+
 LOCAL_PACKAGE_NAME := ActivityManagerPerfTestsTestApp
 
 include $(BUILD_PACKAGE)
diff --git a/tests/ActivityManagerPerfTests/test-app/AndroidManifest.xml b/tests/ActivityManagerPerfTests/test-app/AndroidManifest.xml
index 021e386..23a151c 100644
--- a/tests/ActivityManagerPerfTests/test-app/AndroidManifest.xml
+++ b/tests/ActivityManagerPerfTests/test-app/AndroidManifest.xml
@@ -15,6 +15,9 @@
 -->
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
         package="com.android.frameworks.perftests.amteststestapp">
+    <uses-sdk
+            android:minSdkVersion="21"
+            android:targetSdkVersion="27" />
     <application android:name=".TestApplication">
         <activity android:name=".TestActivity" android:exported="true"/>
         <provider
@@ -29,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/Android.mk b/tests/ActivityManagerPerfTests/tests/Android.mk
index daf603d..7597e69 100644
--- a/tests/ActivityManagerPerfTests/tests/Android.mk
+++ b/tests/ActivityManagerPerfTests/tests/Android.mk
@@ -27,6 +27,8 @@
 
 LOCAL_PACKAGE_NAME := ActivityManagerPerfTests
 
+LOCAL_MIN_SDK_VERSION := 25
+
 # For android.permission.FORCE_STOP_PACKAGES permission
 LOCAL_CERTIFICATE := platform
 
diff --git a/tests/ActivityManagerPerfTests/tests/AndroidManifest.xml b/tests/ActivityManagerPerfTests/tests/AndroidManifest.xml
index 4e194c6..a1ab33a 100644
--- a/tests/ActivityManagerPerfTests/tests/AndroidManifest.xml
+++ b/tests/ActivityManagerPerfTests/tests/AndroidManifest.xml
@@ -15,6 +15,9 @@
 -->
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
         package="com.android.frameworks.perftests.amtests">
+    <uses-sdk
+            android:minSdkVersion="21"
+            android:targetSdkVersion="27" />
     <uses-permission android:name="android.permission.DUMP" />
     <uses-permission android:name="android.permission.FORCE_STOP_PACKAGES" />
 
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/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java b/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java
index 063060f..83354d5 100644
--- a/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java
+++ b/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java
@@ -65,6 +65,7 @@
 
     private static final int JOIN_TIMEOUT = 10000;
     private static final String TAG = AppLaunch.class.getSimpleName();
+
     // optional parameter: comma separated list of required account types before proceeding
     // with the app launch
     private static final String KEY_REQUIRED_ACCOUNTS = "required_accounts";
@@ -73,32 +74,36 @@
     private static final String KEY_LAUNCH_ITERATIONS = "launch_iterations";
     private static final String KEY_LAUNCH_ORDER = "launch_order";
     private static final String KEY_DROP_CACHE = "drop_cache";
-    private static final String KEY_SIMULATE_MAINTANANCE = "simulate_maintanance";
-    private static final String KEY_SIMPLEPPERF_CMD = "simpleperf_cmd";
+    private static final String KEY_SIMPLEPERF_CMD = "simpleperf_cmd";
+    private static final String KEY_SIMPLEPERF_APP = "simpleperf_app";
     private static final String KEY_TRACE_ITERATIONS = "trace_iterations";
     private static final String KEY_LAUNCH_DIRECTORY = "launch_directory";
     private static final String KEY_TRACE_DIRECTORY = "trace_directory";
     private static final String KEY_TRACE_CATEGORY = "trace_categories";
     private static final String KEY_TRACE_BUFFERSIZE = "trace_bufferSize";
     private static final String KEY_TRACE_DUMPINTERVAL = "tracedump_interval";
+    private static final String KEY_COMPILER_FILTERS = "compiler_filters";
+
+    private static final String SIMPLEPERF_APP_CMD =
+            "simpleperf --log fatal stat --csv -e cpu-cycles,major-faults --app %s & %s";
     private static final String WEARABLE_ACTION_GOOGLE =
             "com.google.android.wearable.action.GOOGLE";
-    private static final int INITIAL_LAUNCH_IDLE_TIMEOUT = 5000; //5s to allow app to idle
-    private static final int POST_LAUNCH_IDLE_TIMEOUT = 750; //750ms idle for non initial launches
-    private static final int BETWEEN_LAUNCH_SLEEP_TIMEOUT = 5000; //5s between launching apps
+    private static final int INITIAL_LAUNCH_IDLE_TIMEOUT = 5000; // 5s to allow app to idle
+    private static final int POST_LAUNCH_IDLE_TIMEOUT = 750; // 750ms idle for non initial launches
+    private static final int BETWEEN_LAUNCH_SLEEP_TIMEOUT = 5000; // 5s between launching apps
     private static final String LAUNCH_SUB_DIRECTORY = "launch_logs";
     private static final String LAUNCH_FILE = "applaunch.txt";
     private static final String TRACE_SUB_DIRECTORY = "atrace_logs";
-    private static final String DEFAULT_TRACE_CATEGORIES = "sched,freq,gfx,view,dalvik,webview,"
-            + "input,wm,disk,am,wm";
+    private static final String DEFAULT_TRACE_CATEGORIES =
+            "sched,freq,gfx,view,dalvik,webview,input,wm,disk,am,wm";
     private static final String DEFAULT_TRACE_BUFFER_SIZE = "20000";
     private static final String DEFAULT_TRACE_DUMP_INTERVAL = "10";
-    private static final String TRIAL_LAUNCH = "TRAIL_LAUNCH";
+    private static final String TRIAL_LAUNCH = "TRIAL_LAUNCH";
     private static final String DELIMITER = ",";
     private static final String DROP_CACHE_SCRIPT = "/data/local/tmp/dropCache.sh";
     private static final String APP_LAUNCH_CMD = "am start -W -n";
     private static final String SUCCESS_MESSAGE = "Status: ok";
-    private static final String PROFILE_COMPILE_SUCCESS = "Success";
+    private static final String COMPILE_SUCCESS = "Success";
     private static final String THIS_TIME = "ThisTime:";
     private static final String LAUNCH_ITERATION = "LAUNCH_ITERATION - %d";
     private static final String TRACE_ITERATION = "TRACE_ITERATION-%d";
@@ -106,14 +111,15 @@
     private static final String TRACE_ITERATION_PREFIX = "TRACE_ITERATION";
     private static final String LAUNCH_ORDER_CYCLIC = "cyclic";
     private static final String LAUNCH_ORDER_SEQUENTIAL = "sequential";
-    private static final String SPEED_PROFILE_CMD = "cmd package compile -f -m speed-profile %s";
-
-
+    private static final String COMPILE_CMD = "cmd package compile -f -m %s %s";
+    private static final String SPEED_PROFILE_FILTER = "speed-profile";
+    private static final String VERIFY_FILTER = "verify";
+    private static final String LAUNCH_SCRIPT_NAME = "appLaunch";
 
     private Map<String, Intent> mNameToIntent;
     private List<LaunchOrder> mLaunchOrderList = new ArrayList<LaunchOrder>();
     private Map<String, String> mNameToResultKey;
-    private Map<String, List<Long>> mNameToLaunchTime;
+    private Map<String, Map<String, List<AppLaunchResult>>> mNameToLaunchTime;
     private IActivityManager mAm;
     private String mSimplePerfCmd = null;
     private String mLaunchOrder = null;
@@ -123,12 +129,10 @@
     private String mTraceDirectoryStr = null;
     private Bundle mResult = new Bundle();
     private Set<String> mRequiredAccounts;
-    private boolean mTrailLaunch = true;
-    private File mFile = null;
-    private FileOutputStream mOutputStream = null;
+    private boolean mTrialLaunch = false;
     private BufferedWriter mBufferedWriter = null;
-    private boolean mSimulateMaintanance = false;
-
+    private boolean mSimplePerfAppOnly = false;
+    private String[] mCompilerFilters = null;
 
     @Override
     protected void setUp() throws Exception {
@@ -142,6 +146,16 @@
         super.tearDown();
     }
 
+    private void addLaunchResult(LaunchOrder launch, AppLaunchResult result) {
+        mNameToLaunchTime.get(launch.getApp()).get(launch.getCompilerFilter()).add(result);
+    }
+
+    private boolean hasFailureOnFirstLaunch(LaunchOrder launch) {
+        List<AppLaunchResult> results =
+            mNameToLaunchTime.get(launch.getApp()).get(launch.getCompilerFilter());
+        return (results.size() > 0) && (results.get(0).mLaunchTime < 0);
+    }
+
     public void testMeasureStartUpTime() throws RemoteException, NameNotFoundException,
             IOException, InterruptedException {
         InstrumentationTestRunner instrumentation =
@@ -149,11 +163,6 @@
         Bundle args = instrumentation.getArguments();
         mAm = ActivityManager.getService();
         String launchDirectory = args.getString(KEY_LAUNCH_DIRECTORY);
-        mTraceDirectoryStr = args.getString(KEY_TRACE_DIRECTORY);
-        mDropCache = Boolean.parseBoolean(args.getString(KEY_DROP_CACHE));
-        mSimplePerfCmd = args.getString(KEY_SIMPLEPPERF_CMD);
-        mLaunchOrder = args.getString(KEY_LAUNCH_ORDER, LAUNCH_ORDER_CYCLIC);
-        mSimulateMaintanance =  Boolean.parseBoolean(args.getString(KEY_SIMULATE_MAINTANANCE));
 
         createMappings();
         parseArgs(args);
@@ -171,13 +180,14 @@
 
         try {
             File launchSubDir = new File(launchRootDir, LAUNCH_SUB_DIRECTORY);
+
             if (!launchSubDir.exists() && !launchSubDir.mkdirs()) {
                 throw new IOException("Unable to create the lauch file sub directory");
             }
-            mFile = new File(launchSubDir, LAUNCH_FILE);
-            mOutputStream = new FileOutputStream(mFile);
+            File file = new File(launchSubDir, LAUNCH_FILE);
+            FileOutputStream outputStream = new FileOutputStream(file);
             mBufferedWriter = new BufferedWriter(new OutputStreamWriter(
-                    mOutputStream));
+                    outputStream));
 
             // Root directory for trace file during the launches
             File rootTrace = null;
@@ -217,70 +227,67 @@
             setLaunchOrder();
 
             for (LaunchOrder launch : mLaunchOrderList) {
+                dropCache();
 
                 // App launch times for trial launch will not be used for final
                 // launch time calculations.
                 if (launch.getLaunchReason().equals(TRIAL_LAUNCH)) {
                     // In the "applaunch.txt" file, trail launches is referenced using
                     // "TRIAL_LAUNCH"
-                    long launchTime = startApp(launch.getApp(), true, launch.getLaunchReason());
-                    if (launchTime < 0) {
-                        List<Long> appLaunchList = new ArrayList<Long>();
-                        appLaunchList.add(-1L);
-                        mNameToLaunchTime.put(launch.getApp(), appLaunchList);
+                    String appPkgName = mNameToIntent.get(launch.getApp())
+                        .getComponent().getPackageName();
+                    if (SPEED_PROFILE_FILTER.equals(launch.getCompilerFilter())) {
+                        assertTrue(String.format("Not able to compile the app : %s", appPkgName),
+                              compileApp(VERIFY_FILTER, appPkgName));
+                    } else if (launch.getCompilerFilter() != null) {
+                        assertTrue(String.format("Not able to compile the app : %s", appPkgName),
+                              compileApp(launch.getCompilerFilter(), appPkgName));
+                    }
+                    // We only need to run a trial for the speed-profile filter, but we always
+                    // run one for "applaunch.txt" consistency.
+                    AppLaunchResult launchResult =
+                        startApp(launch.getApp(), true, launch.getLaunchReason());
+                    if (launchResult.mLaunchTime < 0) {
+                        addLaunchResult(launch, new AppLaunchResult());
                         // simply pass the app if launch isn't successful
                         // error should have already been logged by startApp
                         continue;
                     }
                     sleep(INITIAL_LAUNCH_IDLE_TIMEOUT);
-                    closeApp(launch.getApp(), true);
-                    dropCache();
-                    if (mSimulateMaintanance) {
-                        String appPkgName = mNameToIntent.get(launch.getApp())
-                                .getComponent().getPackageName();
-                        assertTrue(String.format("Not able to speed profile the app : %s",
-                                appPkgName), profileCompileApp(appPkgName));
+                    if (SPEED_PROFILE_FILTER.equals(launch.getCompilerFilter())) {
+                        // Send SIGUSR1 to force dumping a profile.
+                        String sendSignalCommand =
+                            String.format("killall -s SIGUSR1 %s", appPkgName);
+                        getInstrumentation().getUiAutomation().executeShellCommand(
+                            sendSignalCommand);
+                        assertTrue(String.format("Not able to compile the app : %s", appPkgName),
+                              compileApp(launch.getCompilerFilter(), appPkgName));
                     }
-                    sleep(BETWEEN_LAUNCH_SLEEP_TIMEOUT);
                 }
 
                 // App launch times used for final calculation
-                if (launch.getLaunchReason().contains(LAUNCH_ITERATION_PREFIX)) {
-                    long launchTime = -1;
-                    if (null != mNameToLaunchTime.get(launch.getApp())) {
-                        long firstLaunchTime = mNameToLaunchTime.get(launch.getApp()).get(0);
-                        if (firstLaunchTime < 0) {
-                            // skip if the app has failures while launched first
-                            continue;
-                        }
+                else if (launch.getLaunchReason().contains(LAUNCH_ITERATION_PREFIX)) {
+                    AppLaunchResult launchResults = null;
+                    if (hasFailureOnFirstLaunch(launch)) {
+                        // skip if the app has failures while launched first
+                        continue;
                     }
                     // In the "applaunch.txt" file app launches are referenced using
                     // "LAUNCH_ITERATION - ITERATION NUM"
-                    launchTime = startApp(launch.getApp(), true, launch.getLaunchReason());
-                    if (launchTime < 0) {
+                    launchResults = startApp(launch.getApp(), true, launch.getLaunchReason());
+                    if (launchResults.mLaunchTime < 0) {
+                        addLaunchResult(launch, new AppLaunchResult());
                         // if it fails once, skip the rest of the launches
-                        List<Long> appLaunchList = new ArrayList<Long>();
-                        appLaunchList.add(-1L);
-                        mNameToLaunchTime.put(launch.getApp(), appLaunchList);
                         continue;
                     } else {
-                        if (null != mNameToLaunchTime.get(launch.getApp())) {
-                            mNameToLaunchTime.get(launch.getApp()).add(launchTime);
-                        } else {
-                            List<Long> appLaunchList = new ArrayList<Long>();
-                            appLaunchList.add(launchTime);
-                            mNameToLaunchTime.put(launch.getApp(), appLaunchList);
-                        }
+                        addLaunchResult(launch, launchResults);
                     }
                     sleep(POST_LAUNCH_IDLE_TIMEOUT);
-                    closeApp(launch.getApp(), true);
-                    dropCache();
-                    sleep(BETWEEN_LAUNCH_SLEEP_TIMEOUT);
                 }
 
                 // App launch times for trace launch will not be used for final
                 // launch time calculations.
-                if (launch.getLaunchReason().contains(TRACE_ITERATION_PREFIX)) {
+                else if (launch.getLaunchReason().contains(TRACE_ITERATION_PREFIX)) {
                     AtraceLogger atraceLogger = AtraceLogger
                             .getAtraceLoggerInstance(getInstrumentation());
                     // Start the trace
@@ -293,11 +300,10 @@
                     } finally {
                         // Stop the trace
                         atraceLogger.atraceStop();
-                        closeApp(launch.getApp(), true);
-                        dropCache();
-                        sleep(BETWEEN_LAUNCH_SLEEP_TIMEOUT);
                     }
                 }
+                closeApp(launch.getApp());
+                sleep(BETWEEN_LAUNCH_SLEEP_TIMEOUT);
             }
         } finally {
             if (null != mBufferedWriter) {
@@ -306,29 +312,45 @@
         }
 
         for (String app : mNameToResultKey.keySet()) {
-            StringBuilder launchTimes = new StringBuilder();
-            for (Long launch : mNameToLaunchTime.get(app)) {
-                launchTimes.append(launch);
-                launchTimes.append(",");
+            for (String compilerFilter : mCompilerFilters) {
+                StringBuilder launchTimes = new StringBuilder();
+                StringBuilder cpuCycles = new StringBuilder();
+                StringBuilder majorFaults = new StringBuilder();
+                for (AppLaunchResult result : mNameToLaunchTime.get(app).get(compilerFilter)) {
+                    launchTimes.append(result.mLaunchTime);
+                    launchTimes.append(",");
+                    if (mSimplePerfAppOnly) {
+                        cpuCycles.append(result.mCpuCycles);
+                        cpuCycles.append(",");
+                        majorFaults.append(result.mMajorFaults);
+                        majorFaults.append(",");
+                    }
+                }
+                String filterName = (compilerFilter == null) ? "" : ("-" + compilerFilter);
+                mResult.putString(mNameToResultKey.get(app) + filterName, launchTimes.toString());
+                if (mSimplePerfAppOnly) {
+                    mResult.putString(mNameToResultKey.get(app) + filterName + "-cpuCycles",
+                        cpuCycles.toString());
+                    mResult.putString(mNameToResultKey.get(app) + filterName + "-majorFaults",
+                        majorFaults.toString());
+                }
             }
-            mResult.putString(mNameToResultKey.get(app), launchTimes.toString());
         }
         instrumentation.sendStatus(0, mResult);
     }
 
     /**
-     * Compile the app package using speed compile command and return true or false
+     * Compile the app package using compilerFilter and return true or false
      * based on status of the compilation command.
      */
-    private boolean profileCompileApp(String appPkgName) throws IOException {
-        Log.i(TAG, "Starting to speed profile " + appPkgName);
+    private boolean compileApp(String compilerFilter, String appPkgName) throws IOException {
         try (ParcelFileDescriptor result = getInstrumentation().getUiAutomation().
-                executeShellCommand(String.format(SPEED_PROFILE_CMD, appPkgName));
+                executeShellCommand(String.format(COMPILE_CMD, compilerFilter, appPkgName));
                 BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(
                         new FileInputStream(result.getFileDescriptor())))) {
             String line;
             while ((line = bufferedReader.readLine()) != null) {
-                if (line.contains(PROFILE_COMPILE_SUCCESS)) {
+                if (line.contains(COMPILE_SUCCESS)) {
                     return true;
                 }
             }
@@ -344,38 +366,42 @@
      */
     private void setLaunchOrder() {
         if (LAUNCH_ORDER_CYCLIC.equalsIgnoreCase(mLaunchOrder)) {
-            if (mTrailLaunch) {
-                for (String app : mNameToResultKey.keySet()) {
-                    mLaunchOrderList.add(new LaunchOrder(app, TRIAL_LAUNCH));
-                }
-            }
-            for (int launchCount = 0; launchCount < mLaunchIterations; launchCount++) {
-                for (String app : mNameToResultKey.keySet()) {
-                    mLaunchOrderList.add(new LaunchOrder(app,
-                            String.format(LAUNCH_ITERATION, launchCount)));
-                }
-            }
-            if (mTraceDirectoryStr != null && !mTraceDirectoryStr.isEmpty()) {
-                for (int traceCount = 0; traceCount < mTraceLaunchCount; traceCount++) {
+            for (String compilerFilter : mCompilerFilters) {
+                if (mTrialLaunch) {
                     for (String app : mNameToResultKey.keySet()) {
-                        mLaunchOrderList.add(new LaunchOrder(app,
-                                String.format(TRACE_ITERATION, traceCount)));
+                        mLaunchOrderList.add(new LaunchOrder(app, compilerFilter, TRIAL_LAUNCH));
+                    }
+                }
+                for (int launchCount = 0; launchCount < mLaunchIterations; launchCount++) {
+                    for (String app : mNameToResultKey.keySet()) {
+                        mLaunchOrderList.add(new LaunchOrder(app, compilerFilter,
+                                  String.format(LAUNCH_ITERATION, launchCount)));
+                    }
+                }
+                if (mTraceDirectoryStr != null && !mTraceDirectoryStr.isEmpty()) {
+                    for (int traceCount = 0; traceCount < mTraceLaunchCount; traceCount++) {
+                        for (String app : mNameToResultKey.keySet()) {
+                            mLaunchOrderList.add(new LaunchOrder(app, compilerFilter,
+                                      String.format(TRACE_ITERATION, traceCount)));
+                        }
                     }
                 }
             }
         } else if (LAUNCH_ORDER_SEQUENTIAL.equalsIgnoreCase(mLaunchOrder)) {
-            for (String app : mNameToResultKey.keySet()) {
-                if (mTrailLaunch) {
-                    mLaunchOrderList.add(new LaunchOrder(app, TRIAL_LAUNCH));
-                }
-                for (int launchCount = 0; launchCount < mLaunchIterations; launchCount++) {
-                    mLaunchOrderList.add(new LaunchOrder(app,
-                            String.format(LAUNCH_ITERATION, launchCount)));
-                }
-                if (mTraceDirectoryStr != null && !mTraceDirectoryStr.isEmpty()) {
-                    for (int traceCount = 0; traceCount < mTraceLaunchCount; traceCount++) {
-                        mLaunchOrderList.add(new LaunchOrder(app,
-                                String.format(TRACE_ITERATION, traceCount)));
+            for (String compilerFilter : mCompilerFilters) {
+                for (String app : mNameToResultKey.keySet()) {
+                    if (mTrialLaunch) {
+                        mLaunchOrderList.add(new LaunchOrder(app, compilerFilter, TRIAL_LAUNCH));
+                    }
+                    for (int launchCount = 0; launchCount < mLaunchIterations; launchCount++) {
+                        mLaunchOrderList.add(new LaunchOrder(app, compilerFilter,
+                                String.format(LAUNCH_ITERATION, launchCount)));
+                    }
+                    if (mTraceDirectoryStr != null && !mTraceDirectoryStr.isEmpty()) {
+                        for (int traceCount = 0; traceCount < mTraceLaunchCount; traceCount++) {
+                            mLaunchOrderList.add(new LaunchOrder(app, compilerFilter,
+                                    String.format(TRACE_ITERATION, traceCount)));
+                        }
                     }
                 }
             }
@@ -385,7 +411,7 @@
     }
 
     private void dropCache() {
-        if (true == mDropCache) {
+        if (mDropCache) {
             assertNotNull("Issue in dropping the cache",
                     getInstrumentation().getUiAutomation()
                             .executeShellCommand(DROP_CACHE_SCRIPT));
@@ -394,7 +420,7 @@
 
     private void parseArgs(Bundle args) {
         mNameToResultKey = new LinkedHashMap<String, String>();
-        mNameToLaunchTime = new HashMap<String, List<Long>>();
+        mNameToLaunchTime = new HashMap<>();
         String launchIterations = args.getString(KEY_LAUNCH_ITERATIONS);
         if (launchIterations != null) {
             mLaunchIterations = Integer.parseInt(launchIterations);
@@ -421,7 +447,38 @@
                 mRequiredAccounts.add(accountType);
             }
         }
-        mTrailLaunch = "true".equals(args.getString(KEY_TRIAL_LAUNCH));
+
+        String compilerFilterList = args.getString(KEY_COMPILER_FILTERS);
+        if (compilerFilterList != null) {
+            // If a compiler filter is passed, we make a trial launch to force compilation
+            // of the apps.
+            mTrialLaunch = true;
+            mCompilerFilters = compilerFilterList.split("\\|");
+        } else {
+            // Just pass a null compiler filter to use the current state of the app.
+            mCompilerFilters = new String[1];
+        }
+
+        // Pre-populate the results map to avoid null checks.
+        for (String app : mNameToLaunchTime.keySet()) {
+            HashMap<String, List<AppLaunchResult>> map = new HashMap<>();
+            mNameToLaunchTime.put(app, map);
+            for (String compilerFilter : mCompilerFilters) {
+                map.put(compilerFilter, new ArrayList<>());
+            }
+        }
+
+        mTraceDirectoryStr = args.getString(KEY_TRACE_DIRECTORY);
+        mDropCache = Boolean.parseBoolean(args.getString(KEY_DROP_CACHE));
+        mSimplePerfCmd = args.getString(KEY_SIMPLEPERF_CMD);
+        mLaunchOrder = args.getString(KEY_LAUNCH_ORDER, LAUNCH_ORDER_CYCLIC);
+        mSimplePerfAppOnly = Boolean.parseBoolean(args.getString(KEY_SIMPLEPERF_APP));
+        mTrialLaunch = mTrialLaunch || Boolean.parseBoolean(args.getString(KEY_TRIAL_LAUNCH));
+
+        if (mSimplePerfCmd != null && mSimplePerfAppOnly) {
+            Log.w(TAG, String.format("Passing both %s and %s is not supported, ignoring %s",
+                KEY_SIMPLEPERF_CMD, KEY_SIMPLEPERF_APP));
+        }
     }
 
     private boolean hasLeanback(Context context) {
@@ -465,17 +522,17 @@
         }
     }
 
-    private long startApp(String appName, boolean forceStopBeforeLaunch, String launchReason)
-            throws NameNotFoundException, RemoteException {
+    private AppLaunchResult startApp(String appName, boolean forceStopBeforeLaunch,
+            String launchReason) throws NameNotFoundException, RemoteException {
         Log.i(TAG, "Starting " + appName);
 
         Intent startIntent = mNameToIntent.get(appName);
         if (startIntent == null) {
             Log.w(TAG, "App does not exist: " + appName);
             mResult.putString(mNameToResultKey.get(appName), "App does not exist");
-            return -1L;
+            return new AppLaunchResult();
         }
-        AppLaunchRunnable runnable = new AppLaunchRunnable(startIntent, forceStopBeforeLaunch ,
+        AppLaunchRunnable runnable = new AppLaunchRunnable(startIntent, forceStopBeforeLaunch,
                 launchReason);
         Thread t = new Thread(runnable);
         t.start();
@@ -518,22 +575,23 @@
         }
     }
 
-    private void closeApp(String appName, boolean forceStopApp) {
+    private void startHomeIntent() {
         Intent homeIntent = new Intent(Intent.ACTION_MAIN);
         homeIntent.addCategory(Intent.CATEGORY_HOME);
         homeIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
                 | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
         getInstrumentation().getContext().startActivity(homeIntent);
         sleep(POST_LAUNCH_IDLE_TIMEOUT);
-        if (forceStopApp) {
-            Intent startIntent = mNameToIntent.get(appName);
-            if (startIntent != null) {
-                String packageName = startIntent.getComponent().getPackageName();
-                try {
-                    mAm.forceStopPackage(packageName, UserHandle.USER_CURRENT);
-                } catch (RemoteException e) {
-                    Log.w(TAG, "Error closing app", e);
-                }
+    }
+
+    private void closeApp(String appName) {
+        Intent startIntent = mNameToIntent.get(appName);
+        if (startIntent != null) {
+            String packageName = startIntent.getComponent().getPackageName();
+            try {
+                mAm.forceStopPackage(packageName, UserHandle.USER_CURRENT);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Error closing app", e);
             }
         }
     }
@@ -569,10 +627,12 @@
 
     private class LaunchOrder {
         private String mApp;
+        private String mCompilerFilter;
         private String mLaunchReason;
 
-        LaunchOrder(String app,String launchReason){
+        LaunchOrder(String app, String compilerFilter, String launchReason){
             mApp = app;
+            mCompilerFilter = compilerFilter;
             mLaunchReason = launchReason;
         }
 
@@ -584,6 +644,10 @@
             mApp = app;
         }
 
+        public String getCompilerFilter() {
+            return mCompilerFilter;
+        }
+
         public String getLaunchReason() {
             return mLaunchReason;
         }
@@ -593,9 +657,31 @@
         }
     }
 
+    private class AppLaunchResult {
+        long mLaunchTime;
+        long mCpuCycles;
+        long mMajorFaults;
+
+        AppLaunchResult() {
+            mLaunchTime = -1L;
+            mCpuCycles = -1L;
+            mMajorFaults = -1L;
+        }
+
+        AppLaunchResult(String launchTime, String cpuCycles, String majorFaults) {
+            try {
+                mLaunchTime = Long.parseLong(launchTime, 10);
+                mCpuCycles = Long.parseLong(cpuCycles, 10);
+                mMajorFaults = Long.parseLong(majorFaults, 10);
+            } catch (NumberFormatException e) {
+                Log.e(TAG, "Error parsing result", e);
+            }
+        }
+    }
+
     private class AppLaunchRunnable implements Runnable {
         private Intent mLaunchIntent;
-        private Long mResult;
+        private AppLaunchResult mLaunchResult;
         private boolean mForceStopBeforeLaunch;
         private String mLaunchReason;
 
@@ -604,14 +690,15 @@
             mLaunchIntent = intent;
             mForceStopBeforeLaunch = forceStopBeforeLaunch;
             mLaunchReason = launchReason;
-            mResult = -1L;
+            mLaunchResult = new AppLaunchResult();
         }
 
-        public Long getResult() {
-            return mResult;
+        public AppLaunchResult getResult() {
+            return mLaunchResult;
         }
 
         public void run() {
+            File launchFile = null;
             try {
                 String packageName = mLaunchIntent.getComponent().getPackageName();
                 String componentName = mLaunchIntent.getComponent().flattenToShortString();
@@ -619,17 +706,38 @@
                     mAm.forceStopPackage(packageName, UserHandle.USER_CURRENT);
                 }
                 String launchCmd = String.format("%s %s", APP_LAUNCH_CMD, componentName);
-                if (null != mSimplePerfCmd) {
+                if (mSimplePerfAppOnly) {
+                    try {
+                        // executeShellCommand cannot handle shell specific actions, like '&'.
+                        // Therefore, we create a file containing the command and make that
+                        // the command to launch.
+                        launchFile = File.createTempFile(LAUNCH_SCRIPT_NAME, ".sh");
+                        launchFile.setExecutable(true);
+                        try (FileOutputStream stream = new FileOutputStream(launchFile);
+                             BufferedWriter writer =
+                                new BufferedWriter(new OutputStreamWriter(stream))) {
+                            String cmd = String.format(SIMPLEPERF_APP_CMD, packageName, launchCmd);
+                            writer.write(cmd);
+                        }
+                        launchCmd = launchFile.getAbsolutePath();
+                    } catch (IOException e) {
+                        Log.w(TAG, "Error writing the launch command", e);
+                        return;
+                    }
+                } else if (null != mSimplePerfCmd) {
                     launchCmd = String.format("%s %s", mSimplePerfCmd, launchCmd);
                 }
                 Log.v(TAG, "Final launch cmd:" + launchCmd);
                 ParcelFileDescriptor parcelDesc = getInstrumentation().getUiAutomation()
                         .executeShellCommand(launchCmd);
-                mResult = Long.parseLong(parseLaunchTimeAndWrite(parcelDesc, String.format
-                        ("App Launch :%s %s",
-                                componentName, mLaunchReason)), 10);
+                mLaunchResult = parseLaunchTimeAndWrite(parcelDesc, String.format
+                        ("App Launch :%s %s", componentName, mLaunchReason));
             } catch (RemoteException e) {
                 Log.w(TAG, "Error launching app", e);
+            } finally {
+                if (launchFile != null) {
+                    launchFile.delete();
+                }
             }
         }
 
@@ -639,12 +747,14 @@
          * @param parcelDesc
          * @return
          */
-        private String parseLaunchTimeAndWrite(ParcelFileDescriptor parcelDesc, String headerInfo) {
+        private AppLaunchResult parseLaunchTimeAndWrite(ParcelFileDescriptor parcelDesc,
+                String headerInfo) {
             String launchTime = "-1";
+            String cpuCycles = "-1";
+            String majorFaults = "-1";
             boolean launchSuccess = false;
             try {
                 InputStream inputStream = new FileInputStream(parcelDesc.getFileDescriptor());
-                StringBuilder appLaunchOuput = new StringBuilder();
                 /* SAMPLE OUTPUT :
                 Starting: Intent { cmp=com.google.android.calculator/com.android.calculator2.Calculator }
                 Status: ok
@@ -653,6 +763,11 @@
                 TotalTime: 357
                 WaitTime: 377
                 Complete*/
+                /* WITH SIMPLEPERF :
+                Performance counter statistics,
+                6595722690,cpu-cycles,4.511040,GHz,(100%),
+                0,major-faults,0.000,/sec,(100%),
+                Total test time,1.462129,seconds,*/
                 BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(
                         inputStream));
                 String line = null;
@@ -669,6 +784,23 @@
                         String launchSplit[] = line.split(":");
                         launchTime = launchSplit[1].trim();
                     }
+
+                    if (mSimplePerfAppOnly) {
+                        // Parse simpleperf output.
+                        if (lineCount == 9) {
+                            if (!line.contains("cpu-cycles")) {
+                                Log.e(TAG, "Error in simpleperf output");
+                            } else {
+                                cpuCycles = line.split(",")[0].trim();
+                            }
+                        } else if (lineCount == 10) {
+                            if (!line.contains("major-faults")) {
+                                Log.e(TAG, "Error in simpleperf output");
+                            } else {
+                                majorFaults = line.split(",")[0].trim();
+                            }
+                        }
+                    }
                     mBufferedWriter.write(line);
                     mBufferedWriter.newLine();
                     lineCount++;
@@ -678,7 +810,7 @@
             } catch (IOException e) {
                 Log.w(TAG, "Error writing the launch file", e);
             }
-            return launchTime;
+            return new AppLaunchResult(launchTime, cpuCycles, majorFaults);
         }
 
     }
diff --git a/tests/AppLaunchWear/Android.mk b/tests/AppLaunchWear/Android.mk
new file mode 100644
index 0000000..ac123e7
--- /dev/null
+++ b/tests/AppLaunchWear/Android.mk
@@ -0,0 +1,21 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+# Only compile source java files in this apk.
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := AppLaunchWear
+
+LOCAL_CERTIFICATE := platform
+LOCAL_JAVA_LIBRARIES := android.test.base android.test.runner
+
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+
+LOCAL_COMPATIBILITY_SUITE := device-tests
+
+include $(BUILD_PACKAGE)
+
+# Use the following include to make our test apk.
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/AppLaunchWear/AndroidManifest.xml b/tests/AppLaunchWear/AndroidManifest.xml
new file mode 100644
index 0000000..7dfd7ba
--- /dev/null
+++ b/tests/AppLaunchWear/AndroidManifest.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.tests.applaunch"
+    android:sharedUserId="android.uid.system" >
+
+   <uses-permission android:name="android.permission.REAL_GET_TASKS" />
+   <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+
+   <uses-sdk
+        android:minSdkVersion="22"
+        android:targetSdkVersion="24" />
+
+    <instrumentation android:label="Measure app start up time"
+                     android:name="android.test.InstrumentationTestRunner"
+                     android:targetPackage="com.android.tests.applaunch" />
+
+    <application android:label="App Launch Test">
+        <uses-library android:name="android.test.runner" />
+    </application>
+</manifest>
diff --git a/tests/AppLaunchWear/src/com/android/tests/applaunch/AppLaunch.java b/tests/AppLaunchWear/src/com/android/tests/applaunch/AppLaunch.java
new file mode 100644
index 0000000..f32464b
--- /dev/null
+++ b/tests/AppLaunchWear/src/com/android/tests/applaunch/AppLaunch.java
@@ -0,0 +1,821 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.tests.applaunch;
+
+import android.accounts.Account;
+import android.accounts.AccountManager;
+import android.app.ActivityManager;
+import android.app.ActivityManager.ProcessErrorStateInfo;
+import android.app.IActivityManager;
+import android.app.UiAutomation;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ResolveInfo;
+import android.os.Bundle;
+import android.os.ParcelFileDescriptor;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.support.test.rule.logging.AtraceLogger;
+import android.test.InstrumentationTestCase;
+import android.test.InstrumentationTestRunner;
+import android.util.Log;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+/**
+ * This test is intended to measure the time it takes for the apps to start.
+ * Names of the applications are passed in command line, and the
+ * test starts each application, and reports the start up time in milliseconds.
+ * The instrumentation expects the following key to be passed on the command line:
+ * apps - A list of applications to start and their corresponding result keys
+ * in the following format:
+ * -e apps <app name>^<result key>|<app name>^<result key>
+ */
+public class AppLaunch extends InstrumentationTestCase {
+
+    private static final int JOIN_TIMEOUT = 10000;
+    private static final String TAG = AppLaunch.class.getSimpleName();
+
+    // optional parameter: comma separated list of required account types before proceeding
+    // with the app launch
+    private static final String KEY_REQUIRED_ACCOUNTS = "required_accounts";
+    private static final String KEY_APPS = "apps";
+    private static final String KEY_TRIAL_LAUNCH = "trial_launch";
+    private static final String KEY_LAUNCH_ITERATIONS = "launch_iterations";
+    private static final String KEY_LAUNCH_ORDER = "launch_order";
+    private static final String KEY_DROP_CACHE = "drop_cache";
+    private static final String KEY_SIMPLEPERF_CMD = "simpleperf_cmd";
+    private static final String KEY_SIMPLEPERF_APP = "simpleperf_app";
+    private static final String KEY_TRACE_ITERATIONS = "trace_iterations";
+    private static final String KEY_LAUNCH_DIRECTORY = "launch_directory";
+    private static final String KEY_TRACE_DIRECTORY = "trace_directory";
+    private static final String KEY_TRACE_CATEGORY = "trace_categories";
+    private static final String KEY_TRACE_BUFFERSIZE = "trace_bufferSize";
+    private static final String KEY_TRACE_DUMPINTERVAL = "tracedump_interval";
+    private static final String KEY_COMPILER_FILTERS = "compiler_filters";
+
+    private static final String SIMPLEPERF_APP_CMD =
+            "simpleperf --log fatal stat --csv -e cpu-cycles,major-faults --app %s & %s";
+    private static final String WEARABLE_ACTION_GOOGLE =
+            "com.google.android.wearable.action.GOOGLE";
+    private static final int INITIAL_LAUNCH_IDLE_TIMEOUT = 5000; // 5s to allow app to idle
+    private static final int POST_LAUNCH_IDLE_TIMEOUT = 750; // 750ms idle for non initial launches
+    private static final int BETWEEN_LAUNCH_SLEEP_TIMEOUT = 5000; // 5s between launching apps
+    private static final String LAUNCH_SUB_DIRECTORY = "launch_logs";
+    private static final String LAUNCH_FILE = "applaunch.txt";
+    private static final String TRACE_SUB_DIRECTORY = "atrace_logs";
+    private static final String DEFAULT_TRACE_CATEGORIES =
+            "sched,freq,gfx,view,dalvik,webview,input,wm,disk,am,wm";
+    private static final String DEFAULT_TRACE_BUFFER_SIZE = "20000";
+    private static final String DEFAULT_TRACE_DUMP_INTERVAL = "10";
+    private static final String TRIAL_LAUNCH = "TRIAL_LAUNCH";
+    private static final String DELIMITER = ",";
+    private static final String DROP_CACHE_SCRIPT = "/data/local/tmp/dropCache.sh";
+    private static final String APP_LAUNCH_CMD = "am start -W -n";
+    private static final String SUCCESS_MESSAGE = "Status: ok";
+    private static final String COMPILE_SUCCESS = "Success";
+    private static final String THIS_TIME = "ThisTime:";
+    private static final String LAUNCH_ITERATION = "LAUNCH_ITERATION - %d";
+    private static final String TRACE_ITERATION = "TRACE_ITERATION-%d";
+    private static final String LAUNCH_ITERATION_PREFIX = "LAUNCH_ITERATION";
+    private static final String TRACE_ITERATION_PREFIX = "TRACE_ITERATION";
+    private static final String LAUNCH_ORDER_CYCLIC = "cyclic";
+    private static final String LAUNCH_ORDER_SEQUENTIAL = "sequential";
+    private static final String COMPILE_CMD = "cmd package compile -f -m %s %s";
+    private static final String SPEED_PROFILE_FILTER = "speed-profile";
+    private static final String VERIFY_FILTER = "verify";
+    private static final String LAUNCH_SCRIPT_NAME = "appLaunch";
+    private static final String WEARABLE_HOME_PACKAGE = "com.google.android.wearable.app";
+
+    private Map<String, Intent> mNameToIntent;
+    private List<LaunchOrder> mLaunchOrderList = new ArrayList<LaunchOrder>();
+    private Map<String, String> mNameToResultKey;
+    private Map<String, Map<String, List<AppLaunchResult>>> mNameToLaunchTime;
+    private IActivityManager mAm;
+    private String mSimplePerfCmd = null;
+    private String mLaunchOrder = null;
+    private boolean mDropCache = false;
+    private int mLaunchIterations = 10;
+    private int mTraceLaunchCount = 0;
+    private String mTraceDirectoryStr = null;
+    private Bundle mResult = new Bundle();
+    private Set<String> mRequiredAccounts;
+    private boolean mTrialLaunch = false;
+    private BufferedWriter mBufferedWriter = null;
+    private boolean mSimplePerfAppOnly = false;
+    private String[] mCompilerFilters = null;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        getInstrumentation().getUiAutomation().setRotation(UiAutomation.ROTATION_FREEZE_0);
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        getInstrumentation().getUiAutomation().setRotation(UiAutomation.ROTATION_UNFREEZE);
+        super.tearDown();
+    }
+
+    private void addLaunchResult(LaunchOrder launch, AppLaunchResult result) {
+        mNameToLaunchTime.get(launch.getApp()).get(launch.getCompilerFilter()).add(result);
+    }
+
+    private boolean hasFailureOnFirstLaunch(LaunchOrder launch) {
+        List<AppLaunchResult> results =
+            mNameToLaunchTime.get(launch.getApp()).get(launch.getCompilerFilter());
+        return (results.size() > 0) && (results.get(0).mLaunchTime < 0);
+    }
+
+    public void testMeasureStartUpTime() throws RemoteException, NameNotFoundException,
+            IOException, InterruptedException {
+        InstrumentationTestRunner instrumentation =
+                (InstrumentationTestRunner)getInstrumentation();
+        Bundle args = instrumentation.getArguments();
+        mAm = ActivityManager.getService();
+        String launchDirectory = args.getString(KEY_LAUNCH_DIRECTORY);
+
+        createMappings();
+        parseArgs(args);
+        checkAccountSignIn();
+
+        // Root directory for applaunch file to log the app launch output
+        // Will be useful in case of simpleperf command is used
+        File launchRootDir = null;
+        if (null != launchDirectory && !launchDirectory.isEmpty()) {
+            launchRootDir = new File(launchDirectory);
+            if (!launchRootDir.exists() && !launchRootDir.mkdirs()) {
+                throw new IOException("Unable to create the destination directory");
+            }
+        }
+
+        try {
+            File launchSubDir = new File(launchRootDir, LAUNCH_SUB_DIRECTORY);
+
+            if (!launchSubDir.exists() && !launchSubDir.mkdirs()) {
+                throw new IOException("Unable to create the lauch file sub directory");
+            }
+            File file = new File(launchSubDir, LAUNCH_FILE);
+            FileOutputStream outputStream = new FileOutputStream(file);
+            mBufferedWriter = new BufferedWriter(new OutputStreamWriter(
+                    outputStream));
+
+            // Root directory for trace file during the launches
+            File rootTrace = null;
+            File rootTraceSubDir = null;
+            int traceBufferSize = 0;
+            int traceDumpInterval = 0;
+            Set<String> traceCategoriesSet = null;
+            if (null != mTraceDirectoryStr && !mTraceDirectoryStr.isEmpty()) {
+                rootTrace = new File(mTraceDirectoryStr);
+                if (!rootTrace.exists() && !rootTrace.mkdirs()) {
+                    throw new IOException("Unable to create the trace directory");
+                }
+                rootTraceSubDir = new File(rootTrace, TRACE_SUB_DIRECTORY);
+                if (!rootTraceSubDir.exists() && !rootTraceSubDir.mkdirs()) {
+                    throw new IOException("Unable to create the trace sub directory");
+                }
+                assertNotNull("Trace iteration parameter is mandatory",
+                        args.getString(KEY_TRACE_ITERATIONS));
+                mTraceLaunchCount = Integer.parseInt(args.getString(KEY_TRACE_ITERATIONS));
+                String traceCategoriesStr = args
+                        .getString(KEY_TRACE_CATEGORY, DEFAULT_TRACE_CATEGORIES);
+                traceBufferSize = Integer.parseInt(args.getString(KEY_TRACE_BUFFERSIZE,
+                        DEFAULT_TRACE_BUFFER_SIZE));
+                traceDumpInterval = Integer.parseInt(args.getString(KEY_TRACE_DUMPINTERVAL,
+                        DEFAULT_TRACE_DUMP_INTERVAL));
+                traceCategoriesSet = new HashSet<String>();
+                if (!traceCategoriesStr.isEmpty()) {
+                    String[] traceCategoriesSplit = traceCategoriesStr.split(DELIMITER);
+                    for (int i = 0; i < traceCategoriesSplit.length; i++) {
+                        traceCategoriesSet.add(traceCategoriesSplit[i]);
+                    }
+                }
+            }
+
+            // Get the app launch order based on launch order, trial launch,
+            // launch iterations and trace iterations
+            setLaunchOrder();
+
+            for (LaunchOrder launch : mLaunchOrderList) {
+                dropCache();
+                String appPkgName = mNameToIntent.get(launch.getApp())
+                        .getComponent().getPackageName();
+
+                // App launch times for trial launch will not be used for final
+                // launch time calculations.
+                if (launch.getLaunchReason().equals(TRIAL_LAUNCH)) {
+                    // In the "applaunch.txt" file, trail launches is referenced using
+                    // "TRIAL_LAUNCH"
+                    if (SPEED_PROFILE_FILTER.equals(launch.getCompilerFilter())) {
+                        assertTrue(String.format("Not able to compile the app : %s", appPkgName),
+                              compileApp(VERIFY_FILTER, appPkgName));
+                    } else if (launch.getCompilerFilter() != null) {
+                        assertTrue(String.format("Not able to compile the app : %s", appPkgName),
+                              compileApp(launch.getCompilerFilter(), appPkgName));
+                    }
+                    // We only need to run a trial for the speed-profile filter, but we always
+                    // run one for "applaunch.txt" consistency.
+                    AppLaunchResult launchResult =
+                        startApp(launch.getApp(), true, launch.getLaunchReason());
+                    if (launchResult.mLaunchTime < 0) {
+                        addLaunchResult(launch, new AppLaunchResult());
+                        // simply pass the app if launch isn't successful
+                        // error should have already been logged by startApp
+                        continue;
+                    }
+                    sleep(INITIAL_LAUNCH_IDLE_TIMEOUT);
+                    if (SPEED_PROFILE_FILTER.equals(launch.getCompilerFilter())) {
+                        // Send SIGUSR1 to force dumping a profile.
+                        String sendSignalCommand =
+                            String.format("killall -s SIGUSR1 %s", appPkgName);
+                        getInstrumentation().getUiAutomation().executeShellCommand(
+                            sendSignalCommand);
+                        assertTrue(String.format("Not able to compile the app : %s", appPkgName),
+                              compileApp(launch.getCompilerFilter(), appPkgName));
+                    }
+                }
+
+                // App launch times used for final calculation
+                else if (launch.getLaunchReason().contains(LAUNCH_ITERATION_PREFIX)) {
+                    AppLaunchResult launchResults = null;
+                    if (hasFailureOnFirstLaunch(launch)) {
+                        // skip if the app has failures while launched first
+                        continue;
+                    }
+                    // In the "applaunch.txt" file app launches are referenced using
+                    // "LAUNCH_ITERATION - ITERATION NUM"
+                    if (appPkgName.contains(WEARABLE_HOME_PACKAGE)) {
+                        launchResults = startApp(launch.getApp(), false, launch.getLaunchReason());
+                    } else {
+                        launchResults = startApp(launch.getApp(), true, launch.getLaunchReason());
+                    }
+                    if (launchResults.mLaunchTime < 0) {
+                        addLaunchResult(launch, new AppLaunchResult());
+                        // if it fails once, skip the rest of the launches
+                        continue;
+                    } else {
+                        addLaunchResult(launch, launchResults);
+                    }
+                    sleep(POST_LAUNCH_IDLE_TIMEOUT);
+                }
+
+                // App launch times for trace launch will not be used for final
+                // launch time calculations.
+                else if (launch.getLaunchReason().contains(TRACE_ITERATION_PREFIX)) {
+                    AtraceLogger atraceLogger = AtraceLogger
+                            .getAtraceLoggerInstance(getInstrumentation());
+                    // Start the trace
+                    try {
+                        atraceLogger.atraceStart(traceCategoriesSet, traceBufferSize,
+                                traceDumpInterval, rootTraceSubDir,
+                                String.format("%s-%s", launch.getApp(), launch.getLaunchReason()));
+                        startApp(launch.getApp(), true, launch.getLaunchReason());
+                        sleep(POST_LAUNCH_IDLE_TIMEOUT);
+                    } finally {
+                        // Stop the trace
+                        atraceLogger.atraceStop();
+                    }
+                }
+                closeApp(launch.getApp(), true);
+                sleep(BETWEEN_LAUNCH_SLEEP_TIMEOUT);
+            }
+        } finally {
+            if (null != mBufferedWriter) {
+                mBufferedWriter.close();
+            }
+        }
+
+        for (String app : mNameToResultKey.keySet()) {
+            for (String compilerFilter : mCompilerFilters) {
+                StringBuilder launchTimes = new StringBuilder();
+                StringBuilder cpuCycles = new StringBuilder();
+                StringBuilder majorFaults = new StringBuilder();
+                for (AppLaunchResult result : mNameToLaunchTime.get(app).get(compilerFilter)) {
+                    launchTimes.append(result.mLaunchTime);
+                    launchTimes.append(",");
+                    if (mSimplePerfAppOnly) {
+                        cpuCycles.append(result.mCpuCycles);
+                        cpuCycles.append(",");
+                        majorFaults.append(result.mMajorFaults);
+                        majorFaults.append(",");
+                    }
+                }
+                String filterName = (compilerFilter == null) ? "" : ("-" + compilerFilter);
+                mResult.putString(mNameToResultKey.get(app) + filterName, launchTimes.toString());
+                if (mSimplePerfAppOnly) {
+                    mResult.putString(mNameToResultKey.get(app) + filterName + "-cpuCycles",
+                        cpuCycles.toString());
+                    mResult.putString(mNameToResultKey.get(app) + filterName + "-majorFaults",
+                        majorFaults.toString());
+                }
+            }
+        }
+        instrumentation.sendStatus(0, mResult);
+    }
+
+    /**
+     * Compile the app package using compilerFilter and return true or false
+     * based on status of the compilation command.
+     */
+    private boolean compileApp(String compilerFilter, String appPkgName) throws IOException {
+        try (ParcelFileDescriptor result = getInstrumentation().getUiAutomation().
+                executeShellCommand(String.format(COMPILE_CMD, compilerFilter, appPkgName));
+                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(
+                        new FileInputStream(result.getFileDescriptor())))) {
+            String line;
+            while ((line = bufferedReader.readLine()) != null) {
+                if (line.contains(COMPILE_SUCCESS)) {
+                    return true;
+                }
+            }
+            return false;
+        }
+    }
+
+    /**
+     * If launch order is "cyclic" then apps will be launched one after the
+     * other for each iteration count.
+     * If launch order is "sequential" then each app will be launched for given number
+     * iterations at once before launching the other apps.
+     */
+    private void setLaunchOrder() {
+        if (LAUNCH_ORDER_CYCLIC.equalsIgnoreCase(mLaunchOrder)) {
+            for (String compilerFilter : mCompilerFilters) {
+                if (mTrialLaunch) {
+                    for (String app : mNameToResultKey.keySet()) {
+                        mLaunchOrderList.add(new LaunchOrder(app, compilerFilter, TRIAL_LAUNCH));
+                    }
+                }
+                for (int launchCount = 0; launchCount < mLaunchIterations; launchCount++) {
+                    for (String app : mNameToResultKey.keySet()) {
+                        mLaunchOrderList.add(new LaunchOrder(app, compilerFilter,
+                                  String.format(LAUNCH_ITERATION, launchCount)));
+                    }
+                }
+                if (mTraceDirectoryStr != null && !mTraceDirectoryStr.isEmpty()) {
+                    for (int traceCount = 0; traceCount < mTraceLaunchCount; traceCount++) {
+                        for (String app : mNameToResultKey.keySet()) {
+                            mLaunchOrderList.add(new LaunchOrder(app, compilerFilter,
+                                      String.format(TRACE_ITERATION, traceCount)));
+                        }
+                    }
+                }
+            }
+        } else if (LAUNCH_ORDER_SEQUENTIAL.equalsIgnoreCase(mLaunchOrder)) {
+            for (String compilerFilter : mCompilerFilters) {
+                for (String app : mNameToResultKey.keySet()) {
+                    if (mTrialLaunch) {
+                        mLaunchOrderList.add(new LaunchOrder(app, compilerFilter, TRIAL_LAUNCH));
+                    }
+                    for (int launchCount = 0; launchCount < mLaunchIterations; launchCount++) {
+                        mLaunchOrderList.add(new LaunchOrder(app, compilerFilter,
+                                String.format(LAUNCH_ITERATION, launchCount)));
+                    }
+                    if (mTraceDirectoryStr != null && !mTraceDirectoryStr.isEmpty()) {
+                        for (int traceCount = 0; traceCount < mTraceLaunchCount; traceCount++) {
+                            mLaunchOrderList.add(new LaunchOrder(app, compilerFilter,
+                                    String.format(TRACE_ITERATION, traceCount)));
+                        }
+                    }
+                }
+            }
+        } else {
+            assertTrue("Launch order is not valid parameter", false);
+        }
+    }
+
+    private void dropCache() {
+        if (mDropCache) {
+            assertNotNull("Issue in dropping the cache",
+                    getInstrumentation().getUiAutomation()
+                            .executeShellCommand(DROP_CACHE_SCRIPT));
+        }
+    }
+
+    private void parseArgs(Bundle args) {
+        mNameToResultKey = new LinkedHashMap<String, String>();
+        mNameToLaunchTime = new HashMap<>();
+        String launchIterations = args.getString(KEY_LAUNCH_ITERATIONS);
+        if (launchIterations != null) {
+            mLaunchIterations = Integer.parseInt(launchIterations);
+        }
+        String appList = args.getString(KEY_APPS);
+        if (appList == null)
+            return;
+
+        String appNames[] = appList.split("\\|");
+        for (String pair : appNames) {
+            String[] parts = pair.split("\\^");
+            if (parts.length != 2) {
+                Log.e(TAG, "The apps key is incorrectly formatted");
+                fail();
+            }
+
+            mNameToResultKey.put(parts[0], parts[1]);
+            mNameToLaunchTime.put(parts[0], null);
+        }
+        String requiredAccounts = args.getString(KEY_REQUIRED_ACCOUNTS);
+        if (requiredAccounts != null) {
+            mRequiredAccounts = new HashSet<String>();
+            for (String accountType : requiredAccounts.split(",")) {
+                mRequiredAccounts.add(accountType);
+            }
+        }
+
+        String compilerFilterList = args.getString(KEY_COMPILER_FILTERS);
+        if (compilerFilterList != null) {
+            // If a compiler filter is passed, we make a trial launch to force compilation
+            // of the apps.
+            mTrialLaunch = true;
+            mCompilerFilters = compilerFilterList.split("\\|");
+        } else {
+            // Just pass a null compiler filter to use the current state of the app.
+            mCompilerFilters = new String[1];
+        }
+
+        // Pre-populate the results map to avoid null checks.
+        for (String app : mNameToLaunchTime.keySet()) {
+            HashMap<String, List<AppLaunchResult>> map = new HashMap<>();
+            mNameToLaunchTime.put(app, map);
+            for (String compilerFilter : mCompilerFilters) {
+                map.put(compilerFilter, new ArrayList<>());
+            }
+        }
+
+        mTraceDirectoryStr = args.getString(KEY_TRACE_DIRECTORY);
+        mDropCache = Boolean.parseBoolean(args.getString(KEY_DROP_CACHE));
+        mSimplePerfCmd = args.getString(KEY_SIMPLEPERF_CMD);
+        mLaunchOrder = args.getString(KEY_LAUNCH_ORDER, LAUNCH_ORDER_CYCLIC);
+        mSimplePerfAppOnly = Boolean.parseBoolean(args.getString(KEY_SIMPLEPERF_APP));
+        mTrialLaunch = mTrialLaunch || Boolean.parseBoolean(args.getString(KEY_TRIAL_LAUNCH));
+
+        if (mSimplePerfCmd != null && mSimplePerfAppOnly) {
+            Log.w(TAG, String.format("Passing both %s and %s is not supported, ignoring %s",
+                KEY_SIMPLEPERF_CMD, KEY_SIMPLEPERF_APP));
+        }
+    }
+
+    private boolean hasLeanback(Context context) {
+        return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK);
+    }
+
+    private void createMappings() {
+        mNameToIntent = new LinkedHashMap<String, Intent>();
+
+        PackageManager pm = getInstrumentation().getContext()
+                .getPackageManager();
+        Intent intentToResolve = new Intent(Intent.ACTION_MAIN);
+        intentToResolve.addCategory(hasLeanback(getInstrumentation().getContext()) ?
+                Intent.CATEGORY_LEANBACK_LAUNCHER :
+                Intent.CATEGORY_LAUNCHER);
+        List<ResolveInfo> ris = pm.queryIntentActivities(intentToResolve, 0);
+        resolveLoop(ris, intentToResolve, pm);
+        // For Wear
+        intentToResolve = new Intent(WEARABLE_ACTION_GOOGLE);
+        ris = pm.queryIntentActivities(intentToResolve, 0);
+        resolveLoop(ris, intentToResolve, pm);
+    }
+
+    private void resolveLoop(List<ResolveInfo> ris, Intent intentToResolve, PackageManager pm) {
+        if (ris == null || ris.isEmpty()) {
+            Log.i(TAG, "Could not find any apps");
+        } else {
+            for (ResolveInfo ri : ris) {
+                Intent startIntent = new Intent(intentToResolve);
+                startIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+                        | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
+                startIntent.setClassName(ri.activityInfo.packageName,
+                        ri.activityInfo.name);
+                String appName = ri.loadLabel(pm).toString();
+                if (appName != null) {
+                    // Support launching intent using package name or app name
+                    mNameToIntent.put(ri.activityInfo.packageName, startIntent);
+                    mNameToIntent.put(appName, startIntent);
+                }
+            }
+        }
+    }
+
+    private AppLaunchResult startApp(String appName, boolean forceStopBeforeLaunch,
+            String launchReason) throws NameNotFoundException, RemoteException {
+        Log.i(TAG, "Starting " + appName);
+
+        Intent startIntent = mNameToIntent.get(appName);
+        if (startIntent == null) {
+            Log.w(TAG, "App does not exist: " + appName);
+            mResult.putString(mNameToResultKey.get(appName), "App does not exist");
+            return new AppLaunchResult();
+        }
+        AppLaunchRunnable runnable = new AppLaunchRunnable(startIntent, forceStopBeforeLaunch,
+                launchReason);
+        Thread t = new Thread(runnable);
+        t.start();
+        try {
+            t.join(JOIN_TIMEOUT);
+        } catch (InterruptedException e) {
+            // ignore
+        }
+        return runnable.getResult();
+    }
+
+    private void checkAccountSignIn() {
+        // ensure that the device has the required account types before starting test
+        // e.g. device must have a valid Google account sign in to measure a meaningful launch time
+        // for Gmail
+        if (mRequiredAccounts == null || mRequiredAccounts.isEmpty()) {
+            return;
+        }
+        final AccountManager am =
+                (AccountManager) getInstrumentation().getTargetContext().getSystemService(
+                        Context.ACCOUNT_SERVICE);
+        Account[] accounts = am.getAccounts();
+        // use set here in case device has multiple accounts of the same type
+        Set<String> foundAccounts = new HashSet<String>();
+        for (Account account : accounts) {
+            if (mRequiredAccounts.contains(account.type)) {
+                foundAccounts.add(account.type);
+            }
+        }
+        // check if account type matches, if not, fail test with message on what account types
+        // are missing
+        if (mRequiredAccounts.size() != foundAccounts.size()) {
+            mRequiredAccounts.removeAll(foundAccounts);
+            StringBuilder sb = new StringBuilder("Device missing these accounts:");
+            for (String account : mRequiredAccounts) {
+                sb.append(' ');
+                sb.append(account);
+            }
+            fail(sb.toString());
+        }
+    }
+
+    private void closeApp(String appName, boolean forceStopApp) {
+        Intent homeIntent = new Intent(Intent.ACTION_MAIN);
+        homeIntent.addCategory(Intent.CATEGORY_HOME);
+        homeIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+                | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
+        getInstrumentation().getContext().startActivity(homeIntent);
+        sleep(POST_LAUNCH_IDLE_TIMEOUT);
+        if (forceStopApp) {
+            Intent startIntent = mNameToIntent.get(appName);
+            if (startIntent != null) {
+                String packageName = startIntent.getComponent().getPackageName();
+                try {
+                    mAm.forceStopPackage(packageName, UserHandle.USER_CURRENT);
+                } catch (RemoteException e) {
+                    Log.w(TAG, "Error closing app", e);
+                }
+            }
+        }
+    }
+
+    private void sleep(int time) {
+        try {
+            Thread.sleep(time);
+        } catch (InterruptedException e) {
+            // ignore
+        }
+    }
+
+    private void reportError(String appName, String processName) {
+        ActivityManager am = (ActivityManager) getInstrumentation()
+                .getContext().getSystemService(Context.ACTIVITY_SERVICE);
+        List<ProcessErrorStateInfo> crashes = am.getProcessesInErrorState();
+        if (crashes != null) {
+            for (ProcessErrorStateInfo crash : crashes) {
+                if (!crash.processName.equals(processName))
+                    continue;
+
+                Log.w(TAG, appName + " crashed: " + crash.shortMsg);
+                mResult.putString(mNameToResultKey.get(appName), crash.shortMsg);
+                return;
+            }
+        }
+
+        mResult.putString(mNameToResultKey.get(appName),
+                "Crashed for unknown reason");
+        Log.w(TAG, appName
+                + " not found in process list, most likely it is crashed");
+    }
+
+    private class LaunchOrder {
+        private String mApp;
+        private String mCompilerFilter;
+        private String mLaunchReason;
+
+        LaunchOrder(String app, String compilerFilter, String launchReason){
+            mApp = app;
+            mCompilerFilter = compilerFilter;
+            mLaunchReason = launchReason;
+        }
+
+        public String getApp() {
+            return mApp;
+        }
+
+        public void setApp(String app) {
+            mApp = app;
+        }
+
+        public String getCompilerFilter() {
+            return mCompilerFilter;
+        }
+
+        public String getLaunchReason() {
+            return mLaunchReason;
+        }
+
+        public void setLaunchReason(String launchReason) {
+            mLaunchReason = launchReason;
+        }
+    }
+
+    private class AppLaunchResult {
+        long mLaunchTime;
+        long mCpuCycles;
+        long mMajorFaults;
+
+        AppLaunchResult() {
+            mLaunchTime = -1L;
+            mCpuCycles = -1L;
+            mMajorFaults = -1L;
+        }
+
+        AppLaunchResult(String launchTime, String cpuCycles, String majorFaults) {
+            try {
+                mLaunchTime = Long.parseLong(launchTime, 10);
+                mCpuCycles = Long.parseLong(cpuCycles, 10);
+                mMajorFaults = Long.parseLong(majorFaults, 10);
+            } catch (NumberFormatException e) {
+                Log.e(TAG, "Error parsing result", e);
+            }
+        }
+    }
+
+    private class AppLaunchRunnable implements Runnable {
+        private Intent mLaunchIntent;
+        private AppLaunchResult mLaunchResult;
+        private boolean mForceStopBeforeLaunch;
+        private String mLaunchReason;
+
+        public AppLaunchRunnable(Intent intent, boolean forceStopBeforeLaunch,
+                String launchReason) {
+            mLaunchIntent = intent;
+            mForceStopBeforeLaunch = forceStopBeforeLaunch;
+            mLaunchReason = launchReason;
+            mLaunchResult = new AppLaunchResult();
+        }
+
+        public AppLaunchResult getResult() {
+            return mLaunchResult;
+        }
+
+        public void run() {
+            File launchFile = null;
+            try {
+                String packageName = mLaunchIntent.getComponent().getPackageName();
+                String componentName = mLaunchIntent.getComponent().flattenToShortString();
+                if (mForceStopBeforeLaunch) {
+                    mAm.forceStopPackage(packageName, UserHandle.USER_CURRENT);
+                }
+                String launchCmd = String.format("%s %s", APP_LAUNCH_CMD, componentName);
+                if (mSimplePerfAppOnly) {
+                    try {
+                        // executeShellCommand cannot handle shell specific actions, like '&'.
+                        // Therefore, we create a file containing the command and make that
+                        // the command to launch.
+                        launchFile = File.createTempFile(LAUNCH_SCRIPT_NAME, ".sh");
+                        launchFile.setExecutable(true);
+                        try (FileOutputStream stream = new FileOutputStream(launchFile);
+                             BufferedWriter writer =
+                                new BufferedWriter(new OutputStreamWriter(stream))) {
+                            String cmd = String.format(SIMPLEPERF_APP_CMD, packageName, launchCmd);
+                            writer.write(cmd);
+                        }
+                        launchCmd = launchFile.getAbsolutePath();
+                    } catch (IOException e) {
+                        Log.w(TAG, "Error writing the launch command", e);
+                        return;
+                    }
+                } else if (null != mSimplePerfCmd) {
+                    launchCmd = String.format("%s %s", mSimplePerfCmd, launchCmd);
+                }
+                Log.v(TAG, "Final launch cmd:" + launchCmd);
+                ParcelFileDescriptor parcelDesc = getInstrumentation().getUiAutomation()
+                        .executeShellCommand(launchCmd);
+                mLaunchResult = parseLaunchTimeAndWrite(parcelDesc, String.format
+                        ("App Launch :%s %s", componentName, mLaunchReason));
+            } catch (RemoteException e) {
+                Log.w(TAG, "Error launching app", e);
+            } finally {
+                if (launchFile != null) {
+                    launchFile.delete();
+                }
+            }
+        }
+
+        /**
+         * Method to parse the launch time info and write the result to file
+         *
+         * @param parcelDesc
+         * @return
+         */
+        private AppLaunchResult parseLaunchTimeAndWrite(ParcelFileDescriptor parcelDesc,
+                String headerInfo) {
+            String launchTime = "-1";
+            String cpuCycles = "-1";
+            String majorFaults = "-1";
+            boolean launchSuccess = false;
+            try {
+                InputStream inputStream = new FileInputStream(parcelDesc.getFileDescriptor());
+                /* SAMPLE OUTPUT :
+                Starting: Intent { cmp=com.google.android.calculator/com.android.calculator2.Calculator }
+                Status: ok
+                Activity: com.google.android.calculator/com.android.calculator2.Calculator
+                ThisTime: 357
+                TotalTime: 357
+                WaitTime: 377
+                Complete*/
+                /* WITH SIMPLEPERF :
+                Performance counter statistics,
+                6595722690,cpu-cycles,4.511040,GHz,(100%),
+                0,major-faults,0.000,/sec,(100%),
+                Total test time,1.462129,seconds,*/
+                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(
+                        inputStream));
+                String line = null;
+                int lineCount = 1;
+                mBufferedWriter.newLine();
+                mBufferedWriter.write(headerInfo);
+                mBufferedWriter.newLine();
+                while ((line = bufferedReader.readLine()) != null) {
+                    if (lineCount == 2 && line.contains(SUCCESS_MESSAGE)) {
+                        launchSuccess = true;
+                    }
+                    // Parse TotalTime which is the launch time
+                    if (launchSuccess && lineCount == 5) {
+                        String launchSplit[] = line.split(":");
+                        launchTime = launchSplit[1].trim();
+                    }
+
+                    if (mSimplePerfAppOnly) {
+                        // Parse simpleperf output.
+                        if (lineCount == 9) {
+                            if (!line.contains("cpu-cycles")) {
+                                Log.e(TAG, "Error in simpleperf output");
+                            } else {
+                                cpuCycles = line.split(",")[0].trim();
+                            }
+                        } else if (lineCount == 10) {
+                            if (!line.contains("major-faults")) {
+                                Log.e(TAG, "Error in simpleperf output");
+                            } else {
+                                majorFaults = line.split(",")[0].trim();
+                            }
+                        }
+                    }
+                    mBufferedWriter.write(line);
+                    mBufferedWriter.newLine();
+                    lineCount++;
+                }
+                mBufferedWriter.flush();
+                inputStream.close();
+            } catch (IOException e) {
+                Log.w(TAG, "Error writing the launch file", e);
+            }
+            return new AppLaunchResult(launchTime, cpuCycles, majorFaults);
+        }
+
+    }
+}
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/Internal/src/com/android/internal/colorextraction/types/TonalTest.java b/tests/Internal/src/com/android/internal/colorextraction/types/TonalTest.java
index d46fff4..a7d5ae8 100644
--- a/tests/Internal/src/com/android/internal/colorextraction/types/TonalTest.java
+++ b/tests/Internal/src/com/android/internal/colorextraction/types/TonalTest.java
@@ -99,6 +99,21 @@
     }
 
     @Test
+    public void tonal_rangeTest() {
+        Tonal.ConfigParser config = new Tonal.ConfigParser(InstrumentationRegistry.getContext());
+        for (Tonal.TonalPalette palette : config.getTonalPalettes()) {
+            assertTrue("minHue should be >= to 0.", palette.minHue >= 0);
+            assertTrue("maxHue should be <= to 360.", palette.maxHue <= 360);
+
+            assertTrue("S should be >= to 0.", palette.s[0] >= 0);
+            assertTrue("S should be <= to 1.", palette.s[1] <= 1);
+
+            assertTrue("L should be >= to 0.", palette.l[0] >= 0);
+            assertTrue("L should be <= to 1.", palette.l[1] <= 1);
+        }
+    }
+
+    @Test
     public void tonal_blacklistTest() {
         // Make sure that palette generation will fail.
         final Tonal tonal = new Tonal(InstrumentationRegistry.getContext());
diff --git a/tests/JankBench/Android.mk b/tests/JankBench/Android.mk
index 12568a0..291ba78 100644
--- a/tests/JankBench/Android.mk
+++ b/tests/JankBench/Android.mk
@@ -19,7 +19,7 @@
 
 
 LOCAL_STATIC_ANDROID_LIBRARIES := \
-    android-support-design \
+    $(ANDROID_SUPPORT_DESIGN_TARGETS) \
     android-support-v4 \
     android-support-v7-appcompat \
     android-support-v7-cardview \
diff --git a/tests/UiBench/Android.mk b/tests/UiBench/Android.mk
index 60327e5..c8e6c20 100644
--- a/tests/UiBench/Android.mk
+++ b/tests/UiBench/Android.mk
@@ -15,7 +15,7 @@
 LOCAL_USE_AAPT2 := true
 
 LOCAL_STATIC_ANDROID_LIBRARIES := \
-    android-support-design \
+    $(ANDROID_SUPPORT_DESIGN_TARGETS) \
     android-support-v4 \
     android-support-v7-appcompat \
     android-support-v7-cardview \
diff --git a/tests/net/java/android/net/ConnectivityManagerTest.java b/tests/net/java/android/net/ConnectivityManagerTest.java
index cc792cc..03a617c 100644
--- a/tests/net/java/android/net/ConnectivityManagerTest.java
+++ b/tests/net/java/android/net/ConnectivityManagerTest.java
@@ -38,6 +38,7 @@
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.anyBoolean;
 import static org.mockito.Mockito.anyInt;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.timeout;
@@ -217,7 +218,8 @@
 
         // callback triggers
         captor.getValue().send(makeMessage(request, ConnectivityManager.CALLBACK_AVAILABLE));
-        verify(callback, timeout(500).times(1)).onAvailable(any());
+        verify(callback, timeout(500).times(1)).onAvailable(any(Network.class),
+                any(NetworkCapabilities.class), any(LinkProperties.class));
 
         // unregister callback
         manager.unregisterNetworkCallback(callback);
@@ -244,7 +246,8 @@
 
         // callback triggers
         captor.getValue().send(makeMessage(req1, ConnectivityManager.CALLBACK_AVAILABLE));
-        verify(callback, timeout(100).times(1)).onAvailable(any());
+        verify(callback, timeout(100).times(1)).onAvailable(any(Network.class),
+                any(NetworkCapabilities.class), any(LinkProperties.class));
 
         // unregister callback
         manager.unregisterNetworkCallback(callback);
@@ -335,6 +338,10 @@
     static Message makeMessage(NetworkRequest req, int messageType) {
         Bundle bundle = new Bundle();
         bundle.putParcelable(NetworkRequest.class.getSimpleName(), req);
+        // Pass default objects as we don't care which get passed here
+        bundle.putParcelable(Network.class.getSimpleName(), new Network(1));
+        bundle.putParcelable(NetworkCapabilities.class.getSimpleName(), new NetworkCapabilities());
+        bundle.putParcelable(LinkProperties.class.getSimpleName(), new LinkProperties());
         Message msg = Message.obtain();
         msg.what = messageType;
         msg.setData(bundle);
diff --git a/tests/net/java/android/net/IpSecConfigTest.java b/tests/net/java/android/net/IpSecConfigTest.java
index f6c5532..f186ee5 100644
--- a/tests/net/java/android/net/IpSecConfigTest.java
+++ b/tests/net/java/android/net/IpSecConfigTest.java
@@ -17,6 +17,7 @@
 package android.net;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
@@ -48,18 +49,12 @@
         assertEquals(IpSecManager.INVALID_RESOURCE_ID, c.getSpiResourceId());
     }
 
-    @Test
-    public void testParcelUnparcel() throws Exception {
-        assertParcelingIsLossless(new IpSecConfig());
-
+    private IpSecConfig getSampleConfig() {
         IpSecConfig c = new IpSecConfig();
         c.setMode(IpSecTransform.MODE_TUNNEL);
         c.setSourceAddress("0.0.0.0");
         c.setDestinationAddress("1.2.3.4");
-        c.setEncapType(android.system.OsConstants.UDP_ENCAP_ESPINUDP);
-        c.setEncapSocketResourceId(7);
-        c.setEncapRemotePort(22);
-        c.setNattKeepaliveInterval(42);
+        c.setSpiResourceId(1984);
         c.setEncryption(
                 new IpSecAlgorithm(
                         IpSecAlgorithm.CRYPT_AES_CBC,
@@ -68,7 +63,37 @@
                 new IpSecAlgorithm(
                         IpSecAlgorithm.AUTH_HMAC_MD5,
                         new byte[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF, 0}));
-        c.setSpiResourceId(1984);
+        c.setAuthenticatedEncryption(
+                new IpSecAlgorithm(
+                        IpSecAlgorithm.AUTH_CRYPT_AES_GCM,
+                        new byte[] {
+                            1, 2, 3, 4, 5, 6, 7, 8, 9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF, 0, 1, 2, 3, 4
+                        },
+                        128));
+        c.setEncapType(android.system.OsConstants.UDP_ENCAP_ESPINUDP);
+        c.setEncapSocketResourceId(7);
+        c.setEncapRemotePort(22);
+        c.setNattKeepaliveInterval(42);
+        c.setMarkValue(12);
+        c.setMarkMask(23);
+
+        return c;
+    }
+
+    @Test
+    public void testCopyConstructor() {
+        IpSecConfig original = getSampleConfig();
+        IpSecConfig copy = new IpSecConfig(original);
+
+        assertTrue(IpSecConfig.equals(original, copy));
+        assertFalse(original == copy);
+    }
+
+    @Test
+    public void testParcelUnparcel() throws Exception {
+        assertParcelingIsLossless(new IpSecConfig());
+
+        IpSecConfig c = getSampleConfig();
         assertParcelingIsLossless(c);
     }
 
diff --git a/tests/net/java/android/net/IpSecTransformTest.java b/tests/net/java/android/net/IpSecTransformTest.java
new file mode 100644
index 0000000..ffd1f06
--- /dev/null
+++ b/tests/net/java/android/net/IpSecTransformTest.java
@@ -0,0 +1,62 @@
+/*
+ * 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.net;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import android.support.test.filters.SmallTest;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Unit tests for {@link IpSecTransform}. */
+@SmallTest
+@RunWith(JUnit4.class)
+public class IpSecTransformTest {
+
+    @Test
+    public void testCreateTransformCopiesConfig() {
+        // Create a config with a few parameters to make sure it's not empty
+        IpSecConfig config = new IpSecConfig();
+        config.setSourceAddress("0.0.0.0");
+        config.setDestinationAddress("1.2.3.4");
+        config.setSpiResourceId(1984);
+
+        IpSecTransform preModification = new IpSecTransform(null, config);
+
+        config.setSpiResourceId(1985);
+        IpSecTransform postModification = new IpSecTransform(null, config);
+
+        assertFalse(IpSecTransform.equals(preModification, postModification));
+    }
+
+    @Test
+    public void testCreateTransformsWithSameConfigEqual() {
+        // Create a config with a few parameters to make sure it's not empty
+        IpSecConfig config = new IpSecConfig();
+        config.setSourceAddress("0.0.0.0");
+        config.setDestinationAddress("1.2.3.4");
+        config.setSpiResourceId(1984);
+
+        IpSecTransform config1 = new IpSecTransform(null, config);
+        IpSecTransform config2 = new IpSecTransform(null, config);
+
+        assertTrue(IpSecTransform.equals(config1, config2));
+    }
+}
diff --git a/tests/net/java/android/net/MacAddressTest.java b/tests/net/java/android/net/MacAddressTest.java
index 9aad413..04266c5 100644
--- a/tests/net/java/android/net/MacAddressTest.java
+++ b/tests/net/java/android/net/MacAddressTest.java
@@ -172,7 +172,7 @@
         final int iterations = 1000;
         final String expectedAndroidOui = "da:a1:19";
         for (int i = 0; i < iterations; i++) {
-            MacAddress mac = MacAddress.createRandomUnicastAddress();
+            MacAddress mac = MacAddress.createRandomUnicastAddressWithGoogleBase();
             String stringRepr = mac.toString();
 
             assertTrue(stringRepr + " expected to be a locally assigned address",
@@ -195,6 +195,15 @@
             assertTrue(stringRepr + " expected to begin with " + expectedLocalOui,
                     stringRepr.startsWith(expectedLocalOui));
         }
+
+        for (int i = 0; i < iterations; i++) {
+            MacAddress mac = MacAddress.createRandomUnicastAddress();
+            String stringRepr = mac.toString();
+
+            assertTrue(stringRepr + " expected to be a locally assigned address",
+                    mac.isLocallyAssigned());
+            assertEquals(MacAddress.TYPE_UNICAST, mac.getAddressType());
+        }
     }
 
     @Test
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 6e643a3..24639e9 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -35,6 +35,7 @@
 import static android.net.NetworkCapabilities.NET_CAPABILITY_MMS;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_RCS;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_SUPL;
@@ -318,6 +319,7 @@
 
     // This test has an inherent race condition in it, and cannot be enabled for continuous testing
     // or presubmit tests. It is kept for manual runs and documentation purposes.
+    @Ignore
     public void verifyThatNotWaitingForIdleCausesRaceConditions() {
         // Bring up a network that we can use to send messages to ConnectivityService.
         ConditionVariable cv = waitForConnectivityBroadcasts(1);
@@ -527,6 +529,11 @@
             mNetworkAgent.sendNetworkInfo(mNetworkInfo);
         }
 
+        public void resume() {
+            mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null);
+            mNetworkAgent.sendNetworkInfo(mNetworkInfo);
+        }
+
         public void disconnect() {
             mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, null);
             mNetworkAgent.sendNetworkInfo(mNetworkInfo);
@@ -568,6 +575,10 @@
             assertTrue(mNetworkStatusReceived.block(TIMEOUT_MS));
             return mRedirectUrl;
         }
+
+        public NetworkCapabilities getNetworkCapabilities() {
+            return mNetworkCapabilities;
+        }
     }
 
     /**
@@ -1272,6 +1283,7 @@
         NETWORK_CAPABILITIES,
         LINK_PROPERTIES,
         SUSPENDED,
+        RESUMED,
         LOSING,
         LOST,
         UNAVAILABLE
@@ -1343,6 +1355,11 @@
         }
 
         @Override
+        public void onNetworkResumed(Network network) {
+            setLastCallback(CallbackState.RESUMED, network, null);
+        }
+
+        @Override
         public void onLosing(Network network, int maxMsToLive) {
             setLastCallback(CallbackState.LOSING, network, maxMsToLive /* autoboxed int */);
         }
@@ -2458,16 +2475,31 @@
 
         // Suspend the network.
         mCellNetworkAgent.suspend();
+        cellNetworkCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_SUSPENDED,
+                mCellNetworkAgent);
         cellNetworkCallback.expectCallback(CallbackState.SUSPENDED, mCellNetworkAgent);
         cellNetworkCallback.assertNoCallback();
 
         // Register a garden variety default network request.
-        final TestNetworkCallback dfltNetworkCallback = new TestNetworkCallback();
+        TestNetworkCallback dfltNetworkCallback = new TestNetworkCallback();
         mCm.registerDefaultNetworkCallback(dfltNetworkCallback);
         // We should get onAvailable(), onCapabilitiesChanged(), onLinkPropertiesChanged(),
         // as well as onNetworkSuspended() in rapid succession.
         dfltNetworkCallback.expectAvailableAndSuspendedCallbacks(mCellNetworkAgent, true);
         dfltNetworkCallback.assertNoCallback();
+        mCm.unregisterNetworkCallback(dfltNetworkCallback);
+
+        mCellNetworkAgent.resume();
+        cellNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_SUSPENDED,
+                mCellNetworkAgent);
+        cellNetworkCallback.expectCallback(CallbackState.RESUMED, mCellNetworkAgent);
+        cellNetworkCallback.assertNoCallback();
+
+        dfltNetworkCallback = new TestNetworkCallback();
+        mCm.registerDefaultNetworkCallback(dfltNetworkCallback);
+        // This time onNetworkSuspended should not be called.
+        dfltNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
+        dfltNetworkCallback.assertNoCallback();
 
         mCm.unregisterNetworkCallback(dfltNetworkCallback);
         mCm.unregisterNetworkCallback(cellNetworkCallback);
@@ -3681,8 +3713,7 @@
         vpnNetworkCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
 
         genericNetworkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, vpnNetworkAgent);
-        vpnNetworkCallback.expectCapabilitiesLike(
-                nc -> nc.appliesToUid(uid) && !nc.appliesToUid(uid + 1), vpnNetworkAgent);
+        vpnNetworkCallback.expectCapabilitiesLike(nc -> null == nc.getUids(), vpnNetworkAgent);
 
         ranges.clear();
         vpnNetworkAgent.setUids(ranges);
diff --git a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
index 0f26edb..b1b05e8 100644
--- a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
+++ b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
@@ -87,12 +87,11 @@
 import android.os.Message;
 import android.os.Messenger;
 import android.os.PowerManager;
+import android.os.SimpleClock;
 import android.support.test.InstrumentationRegistry;
-import android.support.test.runner.AndroidJUnit4;
 import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
 import android.telephony.TelephonyManager;
-import android.util.Log;
-import android.util.TrustedTime;
 
 import com.android.internal.net.VpnInfo;
 import com.android.internal.util.test.BroadcastInterceptingContext;
@@ -111,6 +110,8 @@
 import org.mockito.MockitoAnnotations;
 
 import java.io.File;
+import java.time.Clock;
+import java.time.ZoneOffset;
 import java.util.Objects;
 
 /**
@@ -155,7 +156,6 @@
     private File mStatsDir;
 
     private @Mock INetworkManagementService mNetManager;
-    private @Mock TrustedTime mTime;
     private @Mock NetworkStatsSettings mSettings;
     private @Mock IConnectivityManager mConnManager;
     private @Mock IBinder mBinder;
@@ -167,6 +167,13 @@
     private INetworkStatsSession mSession;
     private INetworkManagementEventObserver mNetworkObserver;
 
+    private final Clock mClock = new SimpleClock(ZoneOffset.UTC) {
+        @Override
+        public long millis() {
+            return currentTimeMillis();
+        }
+    };
+
     @Before
     public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
@@ -184,7 +191,7 @@
                 powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
 
         mService = new NetworkStatsService(
-                mServiceContext, mNetManager, mAlarmManager, wakeLock, mTime,
+                mServiceContext, mNetManager, mAlarmManager, wakeLock, mClock,
                 TelephonyManager.getDefault(), mSettings, new NetworkStatsObservers(),
                 mStatsDir, getBaseDir(mStatsDir));
         mHandlerThread = new HandlerThread("HandlerThread");
@@ -196,7 +203,6 @@
 
         mElapsedRealtime = 0L;
 
-        expectCurrentTime();
         expectDefaultSettings();
         expectNetworkStatsUidDetail(buildEmptyStats());
         expectSystemReady();
@@ -221,7 +227,6 @@
         mStatsDir = null;
 
         mNetManager = null;
-        mTime = null;
         mSettings = null;
         mConnManager = null;
 
@@ -233,7 +238,6 @@
     public void testNetworkStatsWifi() throws Exception {
         // pretend that wifi network comes online; service should ask about full
         // network state, and poll any existing interfaces before updating.
-        expectCurrentTime();
         expectDefaultSettings();
         expectNetworkState(buildWifiState());
         expectNetworkStatsSummary(buildEmptyStats());
@@ -248,7 +252,6 @@
 
         // modify some number on wifi, and trigger poll event
         incrementCurrentTime(HOUR_IN_MILLIS);
-        expectCurrentTime();
         expectDefaultSettings();
         expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1)
                 .addIfaceValues(TEST_IFACE, 1024L, 1L, 2048L, 2L));
@@ -262,7 +265,6 @@
         // and bump forward again, with counters going higher. this is
         // important, since polling should correctly subtract last snapshot.
         incrementCurrentTime(DAY_IN_MILLIS);
-        expectCurrentTime();
         expectDefaultSettings();
         expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1)
                 .addIfaceValues(TEST_IFACE, 4096L, 4L, 8192L, 8L));
@@ -280,7 +282,6 @@
 
         // pretend that wifi network comes online; service should ask about full
         // network state, and poll any existing interfaces before updating.
-        expectCurrentTime();
         expectDefaultSettings();
         expectNetworkState(buildWifiState());
         expectNetworkStatsSummary(buildEmptyStats());
@@ -295,7 +296,6 @@
 
         // modify some number on wifi, and trigger poll event
         incrementCurrentTime(HOUR_IN_MILLIS);
-        expectCurrentTime();
         expectDefaultSettings();
         expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1)
                 .addIfaceValues(TEST_IFACE, 1024L, 8L, 2048L, 16L));
@@ -324,13 +324,11 @@
 
         // graceful shutdown system, which should trigger persist of stats, and
         // clear any values in memory.
-        expectCurrentTime();
         expectDefaultSettings();
         mServiceContext.sendBroadcast(new Intent(Intent.ACTION_SHUTDOWN));
         assertStatsFilesExist(true);
 
         // boot through serviceReady() again
-        expectCurrentTime();
         expectDefaultSettings();
         expectNetworkStatsUidDetail(buildEmptyStats());
         expectSystemReady();
@@ -358,7 +356,6 @@
 
         // pretend that wifi network comes online; service should ask about full
         // network state, and poll any existing interfaces before updating.
-        expectCurrentTime();
         expectSettings(0L, HOUR_IN_MILLIS, WEEK_IN_MILLIS);
         expectNetworkState(buildWifiState());
         expectNetworkStatsSummary(buildEmptyStats());
@@ -370,7 +367,6 @@
 
         // modify some number on wifi, and trigger poll event
         incrementCurrentTime(2 * HOUR_IN_MILLIS);
-        expectCurrentTime();
         expectSettings(0L, HOUR_IN_MILLIS, WEEK_IN_MILLIS);
         expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1)
                 .addIfaceValues(TEST_IFACE, 512L, 4L, 512L, 4L));
@@ -386,7 +382,6 @@
 
         // now change bucket duration setting and trigger another poll with
         // exact same values, which should resize existing buckets.
-        expectCurrentTime();
         expectSettings(0L, 30 * MINUTE_IN_MILLIS, WEEK_IN_MILLIS);
         expectNetworkStatsSummary(buildEmptyStats());
         expectNetworkStatsUidDetail(buildEmptyStats());
@@ -403,7 +398,6 @@
     @Test
     public void testUidStatsAcrossNetworks() throws Exception {
         // pretend first mobile network comes online
-        expectCurrentTime();
         expectDefaultSettings();
         expectNetworkState(buildMobile3gState(IMSI_1));
         expectNetworkStatsSummary(buildEmptyStats());
@@ -415,7 +409,6 @@
 
         // create some traffic on first network
         incrementCurrentTime(HOUR_IN_MILLIS);
-        expectCurrentTime();
         expectDefaultSettings();
         expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1)
                 .addIfaceValues(TEST_IFACE, 2048L, 16L, 512L, 4L));
@@ -437,7 +430,6 @@
         // now switch networks; this also tests that we're okay with interfaces
         // disappearing, to verify we don't count backwards.
         incrementCurrentTime(HOUR_IN_MILLIS);
-        expectCurrentTime();
         expectDefaultSettings();
         expectNetworkState(buildMobile3gState(IMSI_2));
         expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1)
@@ -454,7 +446,6 @@
 
         // create traffic on second network
         incrementCurrentTime(HOUR_IN_MILLIS);
-        expectCurrentTime();
         expectDefaultSettings();
         expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1)
                 .addIfaceValues(TEST_IFACE, 2176L, 17L, 1536L, 12L));
@@ -483,7 +474,6 @@
     @Test
     public void testUidRemovedIsMoved() throws Exception {
         // pretend that network comes online
-        expectCurrentTime();
         expectDefaultSettings();
         expectNetworkState(buildWifiState());
         expectNetworkStatsSummary(buildEmptyStats());
@@ -495,7 +485,6 @@
 
         // create some traffic
         incrementCurrentTime(HOUR_IN_MILLIS);
-        expectCurrentTime();
         expectDefaultSettings();
         expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1)
                 .addIfaceValues(TEST_IFACE, 4128L, 258L, 544L, 34L));
@@ -517,7 +506,6 @@
 
         // now pretend two UIDs are uninstalled, which should migrate stats to
         // special "removed" bucket.
-        expectCurrentTime();
         expectDefaultSettings();
         expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1)
                 .addIfaceValues(TEST_IFACE, 4128L, 258L, 544L, 34L));
@@ -545,7 +533,6 @@
     @Test
     public void testUid3g4gCombinedByTemplate() throws Exception {
         // pretend that network comes online
-        expectCurrentTime();
         expectDefaultSettings();
         expectNetworkState(buildMobile3gState(IMSI_1));
         expectNetworkStatsSummary(buildEmptyStats());
@@ -557,7 +544,6 @@
 
         // create some traffic
         incrementCurrentTime(HOUR_IN_MILLIS);
-        expectCurrentTime();
         expectDefaultSettings();
         expectNetworkStatsSummary(buildEmptyStats());
         expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1)
@@ -573,7 +559,6 @@
 
         // now switch over to 4g network
         incrementCurrentTime(HOUR_IN_MILLIS);
-        expectCurrentTime();
         expectDefaultSettings();
         expectNetworkState(buildMobile4gState(TEST_IFACE2));
         expectNetworkStatsSummary(buildEmptyStats());
@@ -588,7 +573,6 @@
 
         // create traffic on second network
         incrementCurrentTime(HOUR_IN_MILLIS);
-        expectCurrentTime();
         expectDefaultSettings();
         expectNetworkStatsSummary(buildEmptyStats());
         expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1)
@@ -607,7 +591,6 @@
     @Test
     public void testSummaryForAllUid() throws Exception {
         // pretend that network comes online
-        expectCurrentTime();
         expectDefaultSettings();
         expectNetworkState(buildWifiState());
         expectNetworkStatsSummary(buildEmptyStats());
@@ -619,7 +602,6 @@
 
         // create some traffic for two apps
         incrementCurrentTime(HOUR_IN_MILLIS);
-        expectCurrentTime();
         expectDefaultSettings();
         expectNetworkStatsSummary(buildEmptyStats());
         expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1)
@@ -637,7 +619,6 @@
 
         // now create more traffic in next hour, but only for one app
         incrementCurrentTime(HOUR_IN_MILLIS);
-        expectCurrentTime();
         expectDefaultSettings();
         expectNetworkStatsSummary(buildEmptyStats());
         expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1)
@@ -669,7 +650,6 @@
     @Test
     public void testForegroundBackground() throws Exception {
         // pretend that network comes online
-        expectCurrentTime();
         expectDefaultSettings();
         expectNetworkState(buildWifiState());
         expectNetworkStatsSummary(buildEmptyStats());
@@ -681,7 +661,6 @@
 
         // create some initial traffic
         incrementCurrentTime(HOUR_IN_MILLIS);
-        expectCurrentTime();
         expectDefaultSettings();
         expectNetworkStatsSummary(buildEmptyStats());
         expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1)
@@ -697,7 +676,6 @@
 
         // now switch to foreground
         incrementCurrentTime(HOUR_IN_MILLIS);
-        expectCurrentTime();
         expectDefaultSettings();
         expectNetworkStatsSummary(buildEmptyStats());
         expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1)
@@ -730,7 +708,6 @@
     @Test
     public void testMetered() throws Exception {
         // pretend that network comes online
-        expectCurrentTime();
         expectDefaultSettings();
         expectNetworkState(buildWifiState(true /* isMetered */));
         expectNetworkStatsSummary(buildEmptyStats());
@@ -742,7 +719,6 @@
 
         // create some initial traffic
         incrementCurrentTime(HOUR_IN_MILLIS);
-        expectCurrentTime();
         expectDefaultSettings();
         expectNetworkStatsSummary(buildEmptyStats());
         // Note that all traffic from NetworkManagementService is tagged as METERED_NO, ROAMING_NO
@@ -772,7 +748,6 @@
     @Test
     public void testRoaming() throws Exception {
         // pretend that network comes online
-        expectCurrentTime();
         expectDefaultSettings();
         expectNetworkState(buildMobile3gState(IMSI_1, true /* isRoaming */));
         expectNetworkStatsSummary(buildEmptyStats());
@@ -784,7 +759,6 @@
 
         // Create some traffic
         incrementCurrentTime(HOUR_IN_MILLIS);
-        expectCurrentTime();
         expectDefaultSettings();
         expectNetworkStatsSummary(buildEmptyStats());
         // Note that all traffic from NetworkManagementService is tagged as METERED_NO and
@@ -813,7 +787,6 @@
     @Test
     public void testTethering() throws Exception {
         // pretend first mobile network comes online
-        expectCurrentTime();
         expectDefaultSettings();
         expectNetworkState(buildMobile3gState(IMSI_1));
         expectNetworkStatsSummary(buildEmptyStats());
@@ -825,7 +798,6 @@
 
         // create some tethering traffic
         incrementCurrentTime(HOUR_IN_MILLIS);
-        expectCurrentTime();
         expectDefaultSettings();
 
         // Traffic seen by kernel counters (includes software tethering).
@@ -858,7 +830,6 @@
     public void testRegisterUsageCallback() throws Exception {
         // pretend that wifi network comes online; service should ask about full
         // network state, and poll any existing interfaces before updating.
-        expectCurrentTime();
         expectDefaultSettings();
         expectNetworkState(buildWifiState());
         expectNetworkStatsSummary(buildEmptyStats());
@@ -880,7 +851,6 @@
         Messenger messenger = new Messenger(latchedHandler);
 
         // Force poll
-        expectCurrentTime();
         expectDefaultSettings();
         expectNetworkStatsSummary(buildEmptyStats());
         expectNetworkStatsUidDetail(buildEmptyStats());
@@ -909,7 +879,6 @@
         // modify some number on wifi, and trigger poll event
         // not enough traffic to call data usage callback
         incrementCurrentTime(HOUR_IN_MILLIS);
-        expectCurrentTime();
         expectDefaultSettings();
         expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1)
                 .addIfaceValues(TEST_IFACE, 1024L, 1L, 2048L, 2L));
@@ -925,7 +894,6 @@
         // and bump forward again, with counters going higher. this is
         // important, since it will trigger the data usage callback
         incrementCurrentTime(DAY_IN_MILLIS);
-        expectCurrentTime();
         expectDefaultSettings();
         expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1)
                 .addIfaceValues(TEST_IFACE, 4096000L, 4L, 8192000L, 8L));
@@ -1068,7 +1036,6 @@
     private void expectSettings(long persistBytes, long bucketDuration, long deleteAge)
             throws Exception {
         when(mSettings.getPollInterval()).thenReturn(HOUR_IN_MILLIS);
-        when(mSettings.getTimeCacheMaxAge()).thenReturn(DAY_IN_MILLIS);
         when(mSettings.getSampleEnabled()).thenReturn(true);
 
         final Config config = new Config(bucketDuration, deleteAge, deleteAge);
@@ -1084,14 +1051,6 @@
         when(mSettings.getUidTagPersistBytes(anyLong())).thenReturn(MB_IN_BYTES);
     }
 
-    private void expectCurrentTime() throws Exception {
-        when(mTime.forceRefresh()).thenReturn(false);
-        when(mTime.hasCache()).thenReturn(true);
-        when(mTime.currentTimeMillis()).thenReturn(currentTimeMillis());
-        when(mTime.getCacheAge()).thenReturn(0L);
-        when(mTime.getCacheCertainty()).thenReturn(0L);
-    }
-
     private void expectBandwidthControlCheck() throws Exception {
         when(mNetManager.isBandwidthControlEnabled()).thenReturn(true);
     }
diff --git a/tests/testables/Android.mk b/tests/testables/Android.mk
index 4c4d2b4..f3cbac0 100644
--- a/tests/testables/Android.mk
+++ b/tests/testables/Android.mk
@@ -23,10 +23,9 @@
 
 LOCAL_SRC_FILES := $(call all-java-files-under,src)
 
-LOCAL_STATIC_JAVA_LIBRARIES := \
-    android-support-test
-
-LOCAL_JAVA_LIBRARIES := android.test.runner android.test.mock mockito-target-minus-junit4
+LOCAL_JAVA_LIBRARIES := android.test.runner android.test.mock \
+    android-support-test \
+    mockito-target-inline-minus-junit4
 
 include $(BUILD_STATIC_JAVA_LIBRARY)
 
diff --git a/tests/testables/src/android/testing/TestableContext.java b/tests/testables/src/android/testing/TestableContext.java
index ffe7219..cf84c79 100644
--- a/tests/testables/src/android/testing/TestableContext.java
+++ b/tests/testables/src/android/testing/TestableContext.java
@@ -83,6 +83,7 @@
                 .acquireContentProviderClient(Settings.AUTHORITY);
         mSettingsProvider = TestableSettingsProvider.getFakeSettingsProvider(settings);
         mTestableContentResolver.addProvider(Settings.AUTHORITY, mSettingsProvider);
+        mSettingsProvider.clearValuesAndCheck(TestableContext.this);
         mReceiver = check != null ? check.getTracker("receiver") : null;
         mService = check != null ? check.getTracker("service") : null;
         mComponent = check != null ? check.getTracker("component") : null;
diff --git a/tests/testables/src/android/testing/TestableSettingsProvider.java b/tests/testables/src/android/testing/TestableSettingsProvider.java
index 5f2a224..b158476 100644
--- a/tests/testables/src/android/testing/TestableSettingsProvider.java
+++ b/tests/testables/src/android/testing/TestableSettingsProvider.java
@@ -36,7 +36,7 @@
 public class TestableSettingsProvider extends MockContentProvider {
 
     private static final String TAG = "TestableSettingsProvider";
-    private static final boolean DEBUG = true;
+    private static final boolean DEBUG = false;
     private static final String MY_UNIQUE_KEY = "Key_" + TestableSettingsProvider.class.getName();
     private static TestableSettingsProvider sInstance;
 
@@ -54,6 +54,9 @@
         mValues.put(key("secure", MY_UNIQUE_KEY, userId), MY_UNIQUE_KEY);
         mValues.put(key("system", MY_UNIQUE_KEY, userId), MY_UNIQUE_KEY);
 
+        Settings.Global.clearProviderForTest();
+        Settings.Secure.clearProviderForTest();
+        Settings.System.clearProviderForTest();
         // Verify that if any test is using TestableContext, they all have the correct settings
         // provider.
         assertEquals("Incorrect settings provider, test using incorrect Context?", MY_UNIQUE_KEY,
diff --git a/tests/testables/tests/Android.mk b/tests/testables/tests/Android.mk
index 6e20d797..f9b3ce4 100644
--- a/tests/testables/tests/Android.mk
+++ b/tests/testables/tests/Android.mk
@@ -27,9 +27,15 @@
 
 LOCAL_STATIC_JAVA_LIBRARIES := \
     android-support-test \
-    mockito-target-minus-junit4 \
+    mockito-target-inline-minus-junit4 \
 	testables
 
+LOCAL_MULTILIB := both
+
+LOCAL_JNI_SHARED_LIBRARIES := \
+    libdexmakerjvmtiagent \
+    libmultiplejvmtiagentsinterferenceagent
+
 LOCAL_JAVA_LIBRARIES := android.test.runner android.test.base android.test.mock
 
 LOCAL_CERTIFICATE := platform
diff --git a/tests/testables/tests/AndroidManifest.xml b/tests/testables/tests/AndroidManifest.xml
index 6435ad9..61f0be6 100644
--- a/tests/testables/tests/AndroidManifest.xml
+++ b/tests/testables/tests/AndroidManifest.xml
@@ -21,7 +21,7 @@
     <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
     <uses-permission android:name="android.permission.MANAGE_USERS" />
 
-    <application>
+    <application android:debuggable="true">
         <uses-library android:name="android.test.runner" />
     </application>
 
diff --git a/tests/utils/testutils/java/android/os/test/TestLooper.java b/tests/utils/testutils/java/android/os/test/TestLooper.java
index e8ceb4a..a49eda3 100644
--- a/tests/utils/testutils/java/android/os/test/TestLooper.java
+++ b/tests/utils/testutils/java/android/os/test/TestLooper.java
@@ -18,6 +18,8 @@
 
 import static org.junit.Assert.assertTrue;
 
+import android.os.Handler;
+import android.os.HandlerExecutor;
 import android.os.Looper;
 import android.os.Message;
 import android.os.MessageQueue;
@@ -28,6 +30,7 @@
 import java.lang.reflect.Field;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
+import java.util.concurrent.Executor;
 
 /**
  * Creates a looper whose message queue can be manipulated
@@ -83,6 +86,10 @@
         return mLooper;
     }
 
+    public Executor getNewExecutor() {
+        return new HandlerExecutor(new Handler(getLooper()));
+    }
+
     private Message getMessageLinkedList() {
         try {
             MessageQueue queue = mLooper.getQueue();
diff --git a/tests/utils/testutils/java/android/os/test/TestLooperTest.java b/tests/utils/testutils/java/android/os/test/TestLooperTest.java
index 40d83b5..c72e20c 100644
--- a/tests/utils/testutils/java/android/os/test/TestLooperTest.java
+++ b/tests/utils/testutils/java/android/os/test/TestLooperTest.java
@@ -21,6 +21,7 @@
 import static org.junit.Assert.assertTrue;
 import static org.mockito.Matchers.any;
 import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
 
@@ -37,6 +38,8 @@
 import org.mockito.InOrder;
 import org.mockito.MockitoAnnotations;
 
+import java.util.concurrent.Executor;
+
 /**
  * Test TestLooperAbstractTime which provides control over "time". Note that
  * real-time is being used as well. Therefore small time increments are NOT
@@ -48,6 +51,7 @@
     private TestLooper mTestLooper;
     private Handler mHandler;
     private Handler mHandlerSpy;
+    private Executor mExecutor;
 
     @Rule
     public ErrorCollector collector = new ErrorCollector();
@@ -59,6 +63,7 @@
         mTestLooper = new TestLooper();
         mHandler = new Handler(mTestLooper.getLooper());
         mHandlerSpy = spy(mHandler);
+        mExecutor = mTestLooper.getNewExecutor();
     }
 
     /**
@@ -93,6 +98,32 @@
     }
 
     /**
+     * Basic test of the Executor with no time stamps: dispatch 4 executables, check that all 4
+     * executed in correct order.
+     */
+    @Test
+    public void testNoTimeMovementExecutor() {
+        final Runnable runnableA = mock(Runnable.class);
+        final Runnable runnableB = mock(Runnable.class);
+        final Runnable runnableC = mock(Runnable.class);
+
+        InOrder inOrder = inOrder(runnableA, runnableB, runnableC);
+
+        mExecutor.execute(runnableA);
+        mExecutor.execute(runnableB);
+        mExecutor.execute(runnableA);
+        mExecutor.execute(runnableC);
+        mTestLooper.dispatchAll();
+
+        inOrder.verify(runnableA).run();
+        inOrder.verify(runnableB).run();
+        inOrder.verify(runnableA).run();
+        inOrder.verify(runnableC).run();
+
+        inOrder.verifyNoMoreInteractions();
+    }
+
+    /**
      * Test message sequence: A, B, C@5K, A@10K. Don't move time.
      * <p>
      * Expected: only get A, B
diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp
index 669afe1..734a5ab 100644
--- a/tools/aapt/ResourceTable.cpp
+++ b/tools/aapt/ResourceTable.cpp
@@ -4848,6 +4848,7 @@
     const String16 pathInterpolator16("pathInterpolator");
     const String16 objectAnimator16("objectAnimator");
     const String16 gradient16("gradient");
+    const String16 animatedSelector16("animated-selector");
 
     const int minSdk = getMinSdkVersion(bundle);
     if (minSdk >= SDK_LOLLIPOP_MR1) {
@@ -4876,7 +4877,8 @@
                     node->getElementName() == animatedVector16 ||
                     node->getElementName() == objectAnimator16 ||
                     node->getElementName() == pathInterpolator16 ||
-                    node->getElementName() == gradient16)) {
+                    node->getElementName() == gradient16 ||
+                    node->getElementName() == animatedSelector16)) {
             // We were told not to version vector tags, so skip the children here.
             continue;
         }
diff --git a/tools/aapt2/Debug.cpp b/tools/aapt2/Debug.cpp
index 5831875..f064cb1 100644
--- a/tools/aapt2/Debug.cpp
+++ b/tools/aapt2/Debug.cpp
@@ -414,59 +414,78 @@
  public:
   using xml::ConstVisitor::Visit;
 
+  XmlPrinter(Printer* printer) : printer_(printer) {
+  }
+
   void Visit(const xml::Element* el) override {
-    const size_t previous_size = prefix_.size();
-
     for (const xml::NamespaceDecl& decl : el->namespace_decls) {
-      std::cerr << prefix_ << "N: " << decl.prefix << "=" << decl.uri
-                << " (line=" << decl.line_number << ")\n";
-      prefix_ += "  ";
+      printer_->Println(StringPrintf("N: %s=%s (line=%zu)", decl.prefix.c_str(), decl.uri.c_str(),
+                                     decl.line_number));
+      printer_->Indent();
     }
 
-    std::cerr << prefix_ << "E: ";
+    printer_->Print("E: ");
     if (!el->namespace_uri.empty()) {
-      std::cerr << el->namespace_uri << ":";
+      printer_->Print(el->namespace_uri);
+      printer_->Print(":");
     }
-    std::cerr << el->name << " (line=" << el->line_number << ")\n";
+    printer_->Println(StringPrintf("%s (line=%zu)", el->name.c_str(), el->line_number));
+    printer_->Indent();
 
     for (const xml::Attribute& attr : el->attributes) {
-      std::cerr << prefix_ << "  A: ";
+      printer_->Print("A: ");
       if (!attr.namespace_uri.empty()) {
-        std::cerr << attr.namespace_uri << ":";
+        printer_->Print(attr.namespace_uri);
+        printer_->Print(":");
       }
-      std::cerr << attr.name;
+      printer_->Print(attr.name);
 
       if (attr.compiled_attribute) {
-        std::cerr << "(" << attr.compiled_attribute.value().id.value_or_default(ResourceId(0x0))
-                  << ")";
+        printer_->Print("(");
+        printer_->Print(
+            attr.compiled_attribute.value().id.value_or_default(ResourceId(0)).to_string());
+        printer_->Print(")");
       }
-      std::cerr << "=";
+      printer_->Print("=");
       if (attr.compiled_value != nullptr) {
-        std::cerr << *attr.compiled_value;
+        attr.compiled_value->PrettyPrint(printer_);
       } else {
-        std::cerr << attr.value;
+        printer_->Print("\"");
+        printer_->Print(attr.value);
+        printer_->Print("\"");
       }
-      std::cerr << "\n";
+
+      if (!attr.value.empty()) {
+        printer_->Print(" (Raw: \"");
+        printer_->Print(attr.value);
+        printer_->Print("\")");
+      }
+      printer_->Println();
     }
 
-    prefix_ += "  ";
+    printer_->Indent();
     xml::ConstVisitor::Visit(el);
-    prefix_.resize(previous_size);
+    printer_->Undent();
+    printer_->Undent();
+
+    for (size_t i = 0; i < el->namespace_decls.size(); i++) {
+      printer_->Undent();
+    }
   }
 
   void Visit(const xml::Text* text) override {
-    std::cerr << prefix_ << "T: '" << text->text << "'\n";
+    printer_->Println(StringPrintf("T: '%s'", text->text.c_str()));
   }
 
  private:
-  std::string prefix_;
+  Printer* printer_;
 };
 
 }  // namespace
 
-void Debug::DumpXml(const xml::XmlResource& doc) {
-  XmlPrinter printer;
-  doc.root->Accept(&printer);
+void Debug::DumpXml(const xml::XmlResource& doc, Printer* printer) {
+  XmlPrinter xml_visitor(printer);
+  doc.root->Accept(&xml_visitor);
 }
 
 }  // namespace aapt
diff --git a/tools/aapt2/Debug.h b/tools/aapt2/Debug.h
index 6209a04..382707e 100644
--- a/tools/aapt2/Debug.h
+++ b/tools/aapt2/Debug.h
@@ -37,7 +37,7 @@
                          text::Printer* printer);
   static void PrintStyleGraph(ResourceTable* table, const ResourceName& target_style);
   static void DumpHex(const void* data, size_t len);
-  static void DumpXml(const xml::XmlResource& doc);
+  static void DumpXml(const xml::XmlResource& doc, text::Printer* printer);
 };
 
 }  // namespace aapt
diff --git a/tools/aapt2/LoadedApk.cpp b/tools/aapt2/LoadedApk.cpp
index 20a9f41..ac28227 100644
--- a/tools/aapt2/LoadedApk.cpp
+++ b/tools/aapt2/LoadedApk.cpp
@@ -222,7 +222,9 @@
 
     } else if (manifest != nullptr && path == "AndroidManifest.xml") {
       BigBuffer buffer(8192);
-      XmlFlattener xml_flattener(&buffer, {});
+      XmlFlattenerOptions xml_flattener_options;
+      xml_flattener_options.use_utf16 = true;
+      XmlFlattener xml_flattener(&buffer, xml_flattener_options);
       if (!xml_flattener.Consume(context, manifest)) {
         context->GetDiagnostics()->Error(DiagMessage(path) << "flattening failed");
         return false;
diff --git a/tools/aapt2/ResourceUtils.cpp b/tools/aapt2/ResourceUtils.cpp
index 02ac86c..628466d 100644
--- a/tools/aapt2/ResourceUtils.cpp
+++ b/tools/aapt2/ResourceUtils.cpp
@@ -520,6 +520,10 @@
   return util::make_unique<BinaryPrimitive>(value);
 }
 
+std::unique_ptr<BinaryPrimitive> MakeInt(uint32_t val) {
+  return util::make_unique<BinaryPrimitive>(android::Res_value::TYPE_INT_DEC, val);
+}
+
 std::unique_ptr<BinaryPrimitive> TryParseFloat(const StringPiece& str) {
   std::u16string str16 = util::Utf8ToUtf16(util::TrimWhitespace(str));
   android::Res_value value;
diff --git a/tools/aapt2/ResourceUtils.h b/tools/aapt2/ResourceUtils.h
index 36f6c2b..f83d49e 100644
--- a/tools/aapt2/ResourceUtils.h
+++ b/tools/aapt2/ResourceUtils.h
@@ -165,6 +165,9 @@
  */
 std::unique_ptr<BinaryPrimitive> TryParseInt(const android::StringPiece& str);
 
+// Returns an integer BinaryPrimitive.
+std::unique_ptr<BinaryPrimitive> MakeInt(uint32_t value);
+
 /*
  * Returns a BinaryPrimitve object representing a floating point number
  * (float, dimension, etc) if the string was parsed as one.
diff --git a/tools/aapt2/ResourceValues.cpp b/tools/aapt2/ResourceValues.cpp
index 77cee06..6f213e1 100644
--- a/tools/aapt2/ResourceValues.cpp
+++ b/tools/aapt2/ResourceValues.cpp
@@ -369,6 +369,19 @@
 
 void FileReference::Print(std::ostream* out) const {
   *out << "(file) " << *path;
+  switch (type) {
+    case ResourceFile::Type::kBinaryXml:
+      *out << " type=XML";
+      break;
+    case ResourceFile::Type::kProtoXml:
+      *out << " type=protoXML";
+      break;
+    case ResourceFile::Type::kPng:
+      *out << " type=PNG";
+      break;
+    default:
+      break;
+  }
 }
 
 BinaryPrimitive::BinaryPrimitive(const android::Res_value& val) : value(val) {
diff --git a/tools/aapt2/cmd/Convert.cpp b/tools/aapt2/cmd/Convert.cpp
index d80307c..7f956c5 100644
--- a/tools/aapt2/cmd/Convert.cpp
+++ b/tools/aapt2/cmd/Convert.cpp
@@ -139,6 +139,7 @@
     BigBuffer buffer(4096);
     XmlFlattenerOptions options = {};
     options.use_utf16 = utf16;
+    options.keep_raw_values = true;
     XmlFlattener flattener(&buffer, options);
     if (!flattener.Consume(context_, xml)) {
       return false;
diff --git a/tools/aapt2/cmd/Dump.cpp b/tools/aapt2/cmd/Dump.cpp
index 3d2fb55..8e7e5e5 100644
--- a/tools/aapt2/cmd/Dump.cpp
+++ b/tools/aapt2/cmd/Dump.cpp
@@ -38,6 +38,13 @@
 
 namespace aapt {
 
+struct DumpOptions {
+  DebugPrintTableOptions print_options;
+
+  // The path to a file within an APK to dump.
+  Maybe<std::string> file_to_dump_path;
+};
+
 static const char* ResourceFileTypeToString(const ResourceFile::Type& type) {
   switch (type) {
     case ResourceFile::Type::kPng:
@@ -69,8 +76,52 @@
   printer->Println(StringPrintf("Data:     offset=%" PRIi64 " length=%zd", offset, len));
 }
 
+static bool DumpXmlFile(IAaptContext* context, io::IFile* file, bool proto,
+                        text::Printer* printer) {
+  std::unique_ptr<xml::XmlResource> doc;
+  if (proto) {
+    std::unique_ptr<io::InputStream> in = file->OpenInputStream();
+    if (in == nullptr) {
+      context->GetDiagnostics()->Error(DiagMessage() << "failed to open file");
+      return false;
+    }
+
+    io::ZeroCopyInputAdaptor adaptor(in.get());
+    pb::XmlNode pb_node;
+    if (!pb_node.ParseFromZeroCopyStream(&adaptor)) {
+      context->GetDiagnostics()->Error(DiagMessage() << "failed to parse file as proto XML");
+      return false;
+    }
+
+    std::string err;
+    doc = DeserializeXmlResourceFromPb(pb_node, &err);
+    if (doc == nullptr) {
+      context->GetDiagnostics()->Error(DiagMessage() << "failed to deserialize proto XML");
+      return false;
+    }
+    printer->Println("Proto XML");
+  } else {
+    std::unique_ptr<io::IData> data = file->OpenAsData();
+    if (data == nullptr) {
+      context->GetDiagnostics()->Error(DiagMessage() << "failed to open file");
+      return false;
+    }
+
+    std::string err;
+    doc = xml::Inflate(data->data(), data->size(), &err);
+    if (doc == nullptr) {
+      context->GetDiagnostics()->Error(DiagMessage() << "failed to parse file as binary XML");
+      return false;
+    }
+    printer->Println("Binary XML");
+  }
+
+  Debug::DumpXml(*doc, printer);
+  return true;
+}
+
 static bool TryDumpFile(IAaptContext* context, const std::string& file_path,
-                        const DebugPrintTableOptions& print_options) {
+                        const DumpOptions& options) {
   // Use a smaller buffer so that there is less latency for dumping to stdout.
   constexpr size_t kStdOutBufferSize = 1024u;
   io::FileOutputStream fout(STDOUT_FILENO, kStdOutBufferSize);
@@ -80,7 +131,10 @@
   std::unique_ptr<io::ZipFileCollection> zip = io::ZipFileCollection::Create(file_path, &err);
   if (zip) {
     ResourceTable table;
+    bool proto = false;
     if (io::IFile* file = zip->FindFile("resources.pb")) {
+      proto = true;
+
       std::unique_ptr<io::IData> data = file->OpenAsData();
       if (data == nullptr) {
         context->GetDiagnostics()->Error(DiagMessage(file_path) << "failed to open resources.pb");
@@ -98,8 +152,6 @@
                                          << "failed to parse table: " << err);
         return false;
       }
-
-      printer.Println("Proto APK");
     } else if (io::IFile* file = zip->FindFile("resources.arsc")) {
       std::unique_ptr<io::IData> data = file->OpenAsData();
       if (!data) {
@@ -112,12 +164,26 @@
       if (!parser.Parse()) {
         return false;
       }
-
-      printer.Println("Binary APK");
     }
 
-    Debug::PrintTable(table, print_options, &printer);
-    return true;
+    if (!options.file_to_dump_path) {
+      if (proto) {
+        printer.Println("Proto APK");
+      } else {
+        printer.Println("Binary APK");
+      }
+      Debug::PrintTable(table, options.print_options, &printer);
+      return true;
+    }
+
+    io::IFile* file = zip->FindFile(options.file_to_dump_path.value());
+    if (file == nullptr) {
+      context->GetDiagnostics()->Error(DiagMessage(file_path)
+                                       << "file '" << options.file_to_dump_path.value()
+                                       << "' not found in APK");
+      return false;
+    }
+    return DumpXmlFile(context, file, proto, &printer);
   }
 
   err.clear();
@@ -159,7 +225,7 @@
       }
 
       printer.Indent();
-      Debug::PrintTable(table, print_options, &printer);
+      Debug::PrintTable(table, options.print_options, &printer);
       printer.Undent();
     } else if (entry->Type() == ContainerEntryType::kResFile) {
       printer.Println("kResFile");
@@ -243,10 +309,13 @@
 int Dump(const std::vector<StringPiece>& args) {
   bool verbose = false;
   bool no_values = false;
+  DumpOptions options;
   Flags flags = Flags()
                     .OptionalSwitch("--no-values",
                                     "Suppresses output of values when displaying resource tables.",
                                     &no_values)
+                    .OptionalFlag("--file", "Dumps the specified file from the APK passed as arg.",
+                                  &options.file_to_dump_path)
                     .OptionalSwitch("-v", "increase verbosity of output", &verbose);
   if (!flags.Parse("aapt2 dump", args, &std::cerr)) {
     return 1;
@@ -255,11 +324,10 @@
   DumpContext context;
   context.SetVerbose(verbose);
 
-  DebugPrintTableOptions dump_table_options;
-  dump_table_options.show_sources = true;
-  dump_table_options.show_values = !no_values;
+  options.print_options.show_sources = true;
+  options.print_options.show_values = !no_values;
   for (const std::string& arg : flags.GetArgs()) {
-    if (!TryDumpFile(&context, arg, dump_table_options)) {
+    if (!TryDumpFile(&context, arg, options)) {
       return 1;
     }
   }
diff --git a/tools/aapt2/cmd/Link.cpp b/tools/aapt2/cmd/Link.cpp
index c9e272c..12ab883 100644
--- a/tools/aapt2/cmd/Link.cpp
+++ b/tools/aapt2/cmd/Link.cpp
@@ -450,7 +450,7 @@
 
 static bool IsVectorElement(const std::string& name) {
   return name == "vector" || name == "animated-vector" || name == "pathInterpolator" ||
-         name == "objectAnimator" || name == "gradient";
+         name == "objectAnimator" || name == "gradient" || name == "animated-selector";
 }
 
 template <typename T>
@@ -514,6 +514,17 @@
   return xml_compat_versioner.Process(context_, doc, api_range);
 }
 
+ResourceFile::Type XmlFileTypeForOutputFormat(OutputFormat format) {
+  switch (format) {
+    case OutputFormat::kApk:
+      return ResourceFile::Type::kBinaryXml;
+    case OutputFormat::kProto:
+      return ResourceFile::Type::kProtoXml;
+  }
+  LOG_ALWAYS_FATAL("unreachable");
+  return ResourceFile::Type::kUnknown;
+}
+
 bool ResourceFileFlattener::Flatten(ResourceTable* table, IArchiveWriter* archive_writer) {
   bool error = false;
   std::map<std::pair<ConfigDescription, StringPiece>, FileOperation> config_sorted_files;
@@ -587,6 +598,9 @@
               }
             }
 
+            // Update the type that this file will be written as.
+            file_ref->type = XmlFileTypeForOutputFormat(options_.output_format);
+
             file_op.xml_to_flatten->file.config = config_value->config;
             file_op.xml_to_flatten->file.source = file_ref->GetSource();
             file_op.xml_to_flatten->file.name = ResourceName(pkg->name, type->type, entry->name);
@@ -625,12 +639,16 @@
                                                  << config << "' -> '" << doc->file.config << "'");
               }
 
-              dst_path =
-                  ResourceUtils::BuildResourceFileName(doc->file, context_->GetNameMangler());
-              bool result =
-                  table->AddFileReferenceMangled(doc->file.name, doc->file.config, doc->file.source,
-                                                 dst_path, nullptr, context_->GetDiagnostics());
-              if (!result) {
+              const ResourceFile& file = doc->file;
+              dst_path = ResourceUtils::BuildResourceFileName(file, context_->GetNameMangler());
+
+              std::unique_ptr<FileReference> file_ref =
+                  util::make_unique<FileReference>(table->string_pool.MakeRef(dst_path));
+              file_ref->SetSource(doc->file.source);
+              // Update the output format of this XML file.
+              file_ref->type = XmlFileTypeForOutputFormat(options_.output_format);
+              if (!table->AddResourceMangled(file.name, file.config, {}, std::move(file_ref),
+                                             context_->GetDiagnostics())) {
                 return false;
               }
             }
@@ -1446,6 +1464,13 @@
 
     ContainerReaderEntry* entry;
     ContainerReader reader(input_stream.get());
+
+    if (reader.HadError()) {
+      context_->GetDiagnostics()->Error(DiagMessage(src)
+                                        << "failed to read file: " << reader.GetError());
+      return false;
+    }
+
     while ((entry = reader.Next()) != nullptr) {
       if (entry->Type() == ContainerEntryType::kResTable) {
         pb::ResourceTable pb_table;
diff --git a/tools/aapt2/configuration/ConfigurationParser.cpp b/tools/aapt2/configuration/ConfigurationParser.cpp
index eabeb47..902334b 100644
--- a/tools/aapt2/configuration/ConfigurationParser.cpp
+++ b/tools/aapt2/configuration/ConfigurationParser.cpp
@@ -20,6 +20,7 @@
 #include <functional>
 #include <map>
 #include <memory>
+#include <string>
 #include <utility>
 
 #include "android-base/file.h"
@@ -93,6 +94,7 @@
 };
 NoopDiagnostics noop_;
 
+/** Returns the value of the label attribute for a given element. */
 std::string GetLabel(const Element* element, IDiagnostics* diag) {
   std::string label;
   for (const auto& attr : element->attributes) {
@@ -108,6 +110,18 @@
   return label;
 }
 
+/** Returns the value of the version-code-order attribute for a given element. */
+Maybe<int32_t> GetVersionCodeOrder(const Element* element, IDiagnostics* diag) {
+  const xml::Attribute* version = element->FindAttribute("", "version-code-order");
+  if (version == nullptr) {
+    std::string label = GetLabel(element, diag);
+    diag->Error(DiagMessage() << "No version-code-order found for element '" << element->name
+                              << "' with label '" << label << "'");
+    return {};
+  }
+  return std::stoi(version->value);
+}
+
 /** XML node visitor that removes all of the namespace URIs from the node and all children. */
 class NamespaceVisitor : public xml::Visitor {
  public:
@@ -437,26 +451,37 @@
   // Convert from a parsed configuration to a list of artifacts for processing.
   const std::string& apk_name = file::GetFilename(apk_path).to_string();
   std::vector<OutputArtifact> output_artifacts;
-  bool has_errors = false;
 
   PostProcessingConfiguration& config = maybe_config.value();
-  config.SortArtifacts();
 
+  bool valid = true;
   int version = 1;
+
   for (const ConfiguredArtifact& artifact : config.artifacts) {
     Maybe<OutputArtifact> output_artifact = ToOutputArtifact(artifact, apk_name, config, diag_);
     if (!output_artifact) {
       // Defer return an error condition so that all errors are reported.
-      has_errors = true;
+      valid = false;
     } else {
       output_artifact.value().version = version++;
       output_artifacts.push_back(std::move(output_artifact.value()));
     }
   }
 
-  if (has_errors) {
+  if (!config.ValidateVersionCodeOrdering(diag_)) {
+    diag_->Error(DiagMessage() << "could not validate post processing configuration");
+    valid = false;
+  }
+
+  if (valid) {
+    // Sorting artifacts requires that all references are valid as it uses them to determine order.
+    config.SortArtifacts();
+  }
+
+  if (!valid) {
     return {};
   }
+
   return {output_artifacts};
 }
 
@@ -509,8 +534,15 @@
     return false;
   }
 
-  auto& group = GetOrCreateGroup(label, &config->abi_groups);
   bool valid = true;
+  OrderedEntry<Abi>& entry = config->abi_groups[label];
+  Maybe<int32_t> order = GetVersionCodeOrder(root_element, diag);
+  if (!order) {
+    valid = false;
+  } else {
+    entry.order = order.value();
+  }
+  auto& group = entry.entry;
 
   // Special case for empty abi-group tag. Label will be used as the ABI.
   if (root_element->GetChildElements().empty()) {
@@ -519,7 +551,7 @@
       return false;
     }
     group.push_back(abi->second);
-    return true;
+    return valid;
   }
 
   for (auto* child : root_element->GetChildElements()) {
@@ -553,8 +585,15 @@
     return false;
   }
 
-  auto& group = GetOrCreateGroup(label, &config->screen_density_groups);
   bool valid = true;
+  OrderedEntry<ConfigDescription>& entry = config->screen_density_groups[label];
+  Maybe<int32_t> order = GetVersionCodeOrder(root_element, diag);
+  if (!order) {
+    valid = false;
+  } else {
+    entry.order = order.value();
+  }
+  auto& group = entry.entry;
 
   // Special case for empty screen-density-group tag. Label will be used as the screen density.
   if (root_element->GetChildElements().empty()) {
@@ -613,8 +652,15 @@
     return false;
   }
 
-  auto& group = GetOrCreateGroup(label, &config->locale_groups);
   bool valid = true;
+  OrderedEntry<ConfigDescription>& entry = config->locale_groups[label];
+  Maybe<int32_t> order = GetVersionCodeOrder(root_element, diag);
+  if (!order) {
+    valid = false;
+  } else {
+    entry.order = order.value();
+  }
+  auto& group = entry.entry;
 
   // Special case to auto insert a locale for an empty group. Label will be used for locale.
   if (root_element->GetChildElements().empty()) {
@@ -728,8 +774,15 @@
     return false;
   }
 
-  auto& group = GetOrCreateGroup(label, &config->gl_texture_groups);
   bool valid = true;
+  OrderedEntry<GlTexture>& entry = config->gl_texture_groups[label];
+  Maybe<int32_t> order = GetVersionCodeOrder(root_element, diag);
+  if (!order) {
+    valid = false;
+  } else {
+    entry.order = order.value();
+  }
+  auto& group = entry.entry;
 
   GlTexture result;
   for (auto* child : root_element->GetChildElements()) {
@@ -771,8 +824,15 @@
     return false;
   }
 
-  auto& group = GetOrCreateGroup(label, &config->device_feature_groups);
   bool valid = true;
+  OrderedEntry<DeviceFeature>& entry = config->device_feature_groups[label];
+  Maybe<int32_t> order = GetVersionCodeOrder(root_element, diag);
+  if (!order) {
+    valid = false;
+  } else {
+    entry.order = order.value();
+  }
+  auto& group = entry.entry;
 
   for (auto* child : root_element->GetChildElements()) {
     if (child->name != "supports-feature") {
diff --git a/tools/aapt2/configuration/ConfigurationParser.internal.h b/tools/aapt2/configuration/ConfigurationParser.internal.h
index a583057..f071a69 100644
--- a/tools/aapt2/configuration/ConfigurationParser.internal.h
+++ b/tools/aapt2/configuration/ConfigurationParser.internal.h
@@ -33,18 +33,31 @@
 
 template <typename T>
 struct OrderedEntry {
-  size_t order;
+  int32_t order;
   std::vector<T> entry;
 };
 
-/** A mapping of group labels to group of configuration items. */
-template <class T>
-using Group = std::unordered_map<std::string, OrderedEntry<T>>;
-
 /** A mapping of group label to a single configuration item. */
 template <class T>
 using Entry = std::unordered_map<std::string, T>;
 
+/** A mapping of group labels to group of configuration items. */
+template <class T>
+using Group = Entry<OrderedEntry<T>>;
+
+template<typename T>
+bool IsGroupValid(const Group<T>& group, const std::string& name, IDiagnostics* diag) {
+  std::set<int32_t> orders;
+  for (const auto& p : group) {
+    orders.insert(p.second.order);
+  }
+  bool valid = orders.size() == group.size();
+  if (!valid) {
+    diag->Error(DiagMessage() << name << " have overlapping version-code-order attributes");
+  }
+  return valid;
+}
+
 /** Retrieves an entry from the provided Group, creating a new instance if one does not exist. */
 template <typename T>
 std::vector<T>& GetOrCreateGroup(std::string label, Group<T>* group) {
@@ -93,7 +106,7 @@
 
  private:
   template <typename T>
-  inline size_t GetGroupOrder(const Group<T>& groups, const Maybe<std::string>& label) {
+  inline size_t GetGroupOrder(const Entry<T>& groups, const Maybe<std::string>& label) {
     if (!label) {
       return std::numeric_limits<size_t>::max();
     }
@@ -141,6 +154,15 @@
   Group<GlTexture> gl_texture_groups;
   Entry<AndroidSdk> android_sdks;
 
+  bool ValidateVersionCodeOrdering(IDiagnostics* diag) {
+    bool valid = IsGroupValid(abi_groups, "abi-groups", diag);
+    valid &= IsGroupValid(screen_density_groups, "screen-density-groups", diag);
+    valid &= IsGroupValid(locale_groups, "locale-groups", diag);
+    valid &= IsGroupValid(device_feature_groups, "device-feature-groups", diag);
+    valid &= IsGroupValid(gl_texture_groups, "gl-texture-groups", diag);
+    return valid;
+  }
+
   /**
    * Sorts the configured artifacts based on the ordering of the groups in the configuration file.
    * The only exception to this rule is Android SDK versions. Larger SDK versions will have a larger
diff --git a/tools/aapt2/configuration/ConfigurationParser_test.cpp b/tools/aapt2/configuration/ConfigurationParser_test.cpp
index 0329846..febbb2e 100644
--- a/tools/aapt2/configuration/ConfigurationParser_test.cpp
+++ b/tools/aapt2/configuration/ConfigurationParser_test.cpp
@@ -82,22 +82,22 @@
 constexpr const char* kValidConfig = R"(<?xml version="1.0" encoding="utf-8" ?>
 <post-process xmlns="http://schemas.android.com/tools/aapt">
   <abi-groups>
-    <abi-group label="arm">
-      <abi>armeabi-v7a</abi>
-      <abi>arm64-v8a</abi>
-    </abi-group>
-    <abi-group label="other">
+    <abi-group label="other" version-code-order="2">
       <abi>x86</abi>
       <abi>mips</abi>
     </abi-group>
+    <abi-group label="arm" version-code-order="1">
+      <abi>armeabi-v7a</abi>
+      <abi>arm64-v8a</abi>
+    </abi-group>
   </abi-groups>
   <screen-density-groups>
-    <screen-density-group label="large">
+    <screen-density-group label="large" version-code-order="2">
       <screen-density>xhdpi</screen-density>
       <screen-density>xxhdpi</screen-density>
       <screen-density>xxxhdpi</screen-density>
     </screen-density-group>
-    <screen-density-group label="alldpi">
+    <screen-density-group label="alldpi" version-code-order="1">
       <screen-density>ldpi</screen-density>
       <screen-density>mdpi</screen-density>
       <screen-density>hdpi</screen-density>
@@ -107,17 +107,20 @@
     </screen-density-group>
   </screen-density-groups>
   <locale-groups>
-    <locale-group label="europe">
+    <locale-group label="europe" version-code-order="1">
       <locale>en</locale>
       <locale>es</locale>
       <locale>fr</locale>
       <locale>de</locale>
     </locale-group>
-    <locale-group label="north-america">
+    <locale-group label="north-america" version-code-order="2">
       <locale>en</locale>
       <locale>es-rMX</locale>
       <locale>fr-rCA</locale>
     </locale-group>
+    <locale-group label="all" version-code-order="-1">
+      <locale />
+    </locale-group>
   </locale-groups>
   <android-sdks>
     <android-sdk
@@ -131,14 +134,14 @@
     </android-sdk>
   </android-sdks>
   <gl-texture-groups>
-    <gl-texture-group label="dxt1">
+    <gl-texture-group label="dxt1" version-code-order="2">
       <gl-texture name="GL_EXT_texture_compression_dxt1">
         <texture-path>assets/dxt1/*</texture-path>
       </gl-texture>
     </gl-texture-group>
   </gl-texture-groups>
   <device-feature-groups>
-    <device-feature-group label="low-latency">
+    <device-feature-group label="low-latency" version-code-order="2">
       <supports-feature>android.hardware.audio.low_latency</supports-feature>
     </device-feature-group>
   </device-feature-groups>
@@ -188,19 +191,22 @@
 
   auto& arm = config.abi_groups["arm"];
   auto& other = config.abi_groups["other"];
-  EXPECT_EQ(arm.order, 1ul);
-  EXPECT_EQ(other.order, 2ul);
+  EXPECT_EQ(arm.order, 1);
+  EXPECT_EQ(other.order, 2);
 
   auto& large = config.screen_density_groups["large"];
   auto& alldpi = config.screen_density_groups["alldpi"];
-  EXPECT_EQ(large.order, 1ul);
-  EXPECT_EQ(alldpi.order, 2ul);
+  EXPECT_EQ(large.order, 2);
+  EXPECT_EQ(alldpi.order, 1);
 
   auto& north_america = config.locale_groups["north-america"];
   auto& europe = config.locale_groups["europe"];
+  auto& all = config.locale_groups["all"];
   // Checked in reverse to make sure access order does not matter.
-  EXPECT_EQ(north_america.order, 2ul);
-  EXPECT_EQ(europe.order, 1ul);
+  EXPECT_EQ(north_america.order, 2);
+  EXPECT_EQ(europe.order, 1);
+  EXPECT_EQ(all.order, -1);
+  EXPECT_EQ(3ul, config.locale_groups.size());
 }
 
 TEST_F(ConfigurationParserTest, ValidateFile) {
@@ -392,7 +398,7 @@
 
 TEST_F(ConfigurationParserTest, AbiGroupAction) {
   static constexpr const char* xml = R"xml(
-    <abi-group label="arm">
+    <abi-group label="arm"  version-code-order="2">
       <!-- First comment. -->
       <abi>
         armeabi-v7a
@@ -415,7 +421,8 @@
 }
 
 TEST_F(ConfigurationParserTest, AbiGroupAction_EmptyGroup) {
-  static constexpr const char* xml = R"xml(<abi-group label="arm64-v8a"/>)xml";
+  static constexpr const char* xml =
+      R"xml(<abi-group label="arm64-v8a" version-code-order="3"/>)xml";
 
   auto doc = test::BuildXmlDom(xml);
 
@@ -426,12 +433,23 @@
   EXPECT_THAT(config.abi_groups, SizeIs(1ul));
   ASSERT_EQ(1u, config.abi_groups.count("arm64-v8a"));
 
-  auto& out = config.abi_groups["arm64-v8a"].entry;
-  ASSERT_THAT(out, ElementsAre(Abi::kArm64V8a));
+  auto& out = config.abi_groups["arm64-v8a"];
+  ASSERT_THAT(out.entry, ElementsAre(Abi::kArm64V8a));
+  EXPECT_EQ(3, out.order);
+}
+
+TEST_F(ConfigurationParserTest, AbiGroupAction_EmptyGroup_NoOrder) {
+  static constexpr const char* xml = R"xml(<abi-group label="arm64-v8a"/>)xml";
+
+  auto doc = test::BuildXmlDom(xml);
+
+  PostProcessingConfiguration config;
+  bool ok = AbiGroupTagHandler(&config, NodeCast<Element>(doc.get()->root.get()), &diag_);
+  ASSERT_FALSE(ok);
 }
 
 TEST_F(ConfigurationParserTest, AbiGroupAction_InvalidEmptyGroup) {
-  static constexpr const char* xml = R"xml(<abi-group label="arm"/>)xml";
+  static constexpr const char* xml = R"xml(<abi-group label="arm" order="2"/>)xml";
 
   auto doc = test::BuildXmlDom(xml);
 
@@ -442,7 +460,7 @@
 
 TEST_F(ConfigurationParserTest, ScreenDensityGroupAction) {
   static constexpr const char* xml = R"xml(
-    <screen-density-group label="large">
+    <screen-density-group label="large" version-code-order="2">
       <screen-density>xhdpi</screen-density>
       <screen-density>
         xxhdpi
@@ -471,7 +489,8 @@
 }
 
 TEST_F(ConfigurationParserTest, ScreenDensityGroupAction_EmtpyGroup) {
-  static constexpr const char* xml = R"xml(<screen-density-group label="xhdpi"/>)xml";
+  static constexpr const char* xml =
+      R"xml(<screen-density-group label="xhdpi" version-code-order="4"/>)xml";
 
   auto doc = test::BuildXmlDom(xml);
 
@@ -485,8 +504,19 @@
   ConfigDescription xhdpi;
   xhdpi.density = ResTable_config::DENSITY_XHIGH;
 
-  auto& out = config.screen_density_groups["xhdpi"].entry;
-  ASSERT_THAT(out, ElementsAre(xhdpi));
+  auto& out = config.screen_density_groups["xhdpi"];
+  EXPECT_THAT(out.entry, ElementsAre(xhdpi));
+  EXPECT_EQ(4, out.order);
+}
+
+TEST_F(ConfigurationParserTest, ScreenDensityGroupAction_EmtpyGroup_NoVersion) {
+  static constexpr const char* xml = R"xml(<screen-density-group label="xhdpi"/>)xml";
+
+  auto doc = test::BuildXmlDom(xml);
+
+  PostProcessingConfiguration config;
+  bool ok = ScreenDensityGroupTagHandler(&config, NodeCast<Element>(doc.get()->root.get()), &diag_);
+  ASSERT_FALSE(ok);
 }
 
 TEST_F(ConfigurationParserTest, ScreenDensityGroupAction_InvalidEmtpyGroup) {
@@ -501,7 +531,7 @@
 
 TEST_F(ConfigurationParserTest, LocaleGroupAction) {
   static constexpr const char* xml = R"xml(
-    <locale-group label="europe">
+    <locale-group label="europe" version-code-order="2">
       <locale>en</locale>
       <locale>es</locale>
       <locale>fr</locale>
@@ -528,7 +558,7 @@
 }
 
 TEST_F(ConfigurationParserTest, LocaleGroupAction_EmtpyGroup) {
-  static constexpr const char* xml = R"xml(<locale-group label="en"/>)xml";
+  static constexpr const char* xml = R"xml(<locale-group label="en" version-code-order="6"/>)xml";
 
   auto doc = test::BuildXmlDom(xml);
 
@@ -539,11 +569,22 @@
   ASSERT_EQ(1ul, config.locale_groups.size());
   ASSERT_EQ(1u, config.locale_groups.count("en"));
 
-  const auto& out = config.locale_groups["en"].entry;
+  const auto& out = config.locale_groups["en"];
 
   ConfigDescription en = test::ParseConfigOrDie("en");
 
-  ASSERT_THAT(out, ElementsAre(en));
+  EXPECT_THAT(out.entry, ElementsAre(en));
+  EXPECT_EQ(6, out.order);
+}
+
+TEST_F(ConfigurationParserTest, LocaleGroupAction_EmtpyGroup_NoOrder) {
+  static constexpr const char* xml = R"xml(<locale-group label="en"/>)xml";
+
+  auto doc = test::BuildXmlDom(xml);
+
+  PostProcessingConfiguration config;
+  bool ok = LocaleGroupTagHandler(&config, NodeCast<Element>(doc.get()->root.get()), &diag_);
+  ASSERT_FALSE(ok);
 }
 
 TEST_F(ConfigurationParserTest, LocaleGroupAction_InvalidEmtpyGroup) {
@@ -695,7 +736,7 @@
 
 TEST_F(ConfigurationParserTest, GlTextureGroupAction) {
   static constexpr const char* xml = R"xml(
-    <gl-texture-group label="dxt1">
+    <gl-texture-group label="dxt1" version-code-order="2">
       <gl-texture name="GL_EXT_texture_compression_dxt1">
         <texture-path>assets/dxt1/main/*</texture-path>
         <texture-path>
@@ -726,7 +767,7 @@
 
 TEST_F(ConfigurationParserTest, DeviceFeatureGroupAction) {
   static constexpr const char* xml = R"xml(
-    <device-feature-group label="low-latency">
+    <device-feature-group label="low-latency" version-code-order="2">
       <supports-feature>android.hardware.audio.low_latency</supports-feature>
       <supports-feature>
         android.hardware.audio.pro
@@ -749,6 +790,30 @@
   ASSERT_THAT(out, ElementsAre(low_latency, pro));
 }
 
+TEST_F(ConfigurationParserTest, Group_Valid) {
+  Group<int32_t> group;
+  group["item1"].order = 1;
+  group["item2"].order = 2;
+  group["item3"].order = 3;
+  group["item4"].order = 4;
+  group["item5"].order = 5;
+  group["item6"].order = 6;
+
+  EXPECT_TRUE(IsGroupValid(group, "test", &diag_));
+}
+
+TEST_F(ConfigurationParserTest, Group_OverlappingOrder) {
+  Group<int32_t> group;
+  group["item1"].order = 1;
+  group["item2"].order = 2;
+  group["item3"].order = 3;
+  group["item4"].order = 2;
+  group["item5"].order = 5;
+  group["item6"].order = 1;
+
+  EXPECT_FALSE(IsGroupValid(group, "test", &diag_));
+}
+
 // Artifact name parser test cases.
 
 TEST(ArtifactTest, Simple) {
diff --git a/tools/aapt2/configuration/aapt2.xsd b/tools/aapt2/configuration/aapt2.xsd
index fb2f49b..a28e28b 100644
--- a/tools/aapt2/configuration/aapt2.xsd
+++ b/tools/aapt2/configuration/aapt2.xsd
@@ -81,6 +81,7 @@
       <xsd:element name="gl-texture" type="gl-texture" maxOccurs="unbounded"/>
     </xsd:sequence>
     <xsd:attribute name="label" type="xsd:string"/>
+    <xsd:attribute name="version-code-order" type="xsd:unsignedInt" use="required"/>
   </xsd:complexType>
 
   <xsd:complexType name="gl-texture">
@@ -95,6 +96,7 @@
       <xsd:element name="supports-feature" type="xsd:string" maxOccurs="unbounded"/>
     </xsd:sequence>
     <xsd:attribute name="label" type="xsd:string"/>
+    <xsd:attribute name="version-code-order" type="xsd:unsignedInt" use="required"/>
   </xsd:complexType>
 
   <xsd:complexType name="abi-group">
@@ -102,6 +104,7 @@
       <xsd:element name="abi" type="abi-name" maxOccurs="unbounded"/>
     </xsd:sequence>
     <xsd:attribute name="label" type="xsd:string"/>
+    <xsd:attribute name="version-code-order" type="xsd:unsignedInt" use="required"/>
   </xsd:complexType>
 
   <xsd:simpleType name="abi-name">
@@ -122,6 +125,7 @@
       <xsd:element name="screen-density" type="screen-density" maxOccurs="unbounded"/>
     </xsd:sequence>
     <xsd:attribute name="label" type="xsd:string"/>
+    <xsd:attribute name="version-code-order" type="xsd:unsignedInt" use="required"/>
   </xsd:complexType>
 
   <xsd:simpleType name="screen-density">
@@ -158,6 +162,7 @@
       <xsd:element name="locale" type="locale" maxOccurs="unbounded"/>
     </xsd:sequence>
     <xsd:attribute name="label" type="xsd:string"/>
+    <xsd:attribute name="version-code-order" type="xsd:unsignedInt" use="required"/>
   </xsd:complexType>
 
   <xsd:complexType name="locale">
diff --git a/tools/aapt2/configuration/example/config.xml b/tools/aapt2/configuration/example/config.xml
index d8aba09..e6db2a0 100644
--- a/tools/aapt2/configuration/example/config.xml
+++ b/tools/aapt2/configuration/example/config.xml
@@ -36,25 +36,19 @@
   </android-sdks>
 
   <abi-groups>
-    <abi-group label="arm">
+    <abi-group label="arm" version-code-order="1">
       <abi>armeabi-v7a</abi>
       <abi>arm64-v8a</abi>
     </abi-group>
 
-    <abi-group label="other">
+    <abi-group label="other" version-code-order="2">
       <abi>x86</abi>
       <abi>mips</abi>
     </abi-group>
   </abi-groups>
 
   <screen-density-groups>
-    <screen-density-group label="large">
-      <screen-density>xhdpi</screen-density>
-      <screen-density>xxhdpi</screen-density>
-      <screen-density>xxxhdpi</screen-density>
-    </screen-density-group>
-
-    <screen-density-group label="alldpi">
+    <screen-density-group label="alldpi" version-code-order="1">
       <screen-density>ldpi</screen-density>
       <screen-density>mdpi</screen-density>
       <screen-density>hdpi</screen-density>
@@ -62,29 +56,35 @@
       <screen-density>xxhdpi</screen-density>
       <screen-density>xxxhdpi</screen-density>
     </screen-density-group>
+
+    <screen-density-group label="large" version-code-order="2">
+      <screen-density>xhdpi</screen-density>
+      <screen-density>xxhdpi</screen-density>
+      <screen-density>xxxhdpi</screen-density>
+    </screen-density-group>
   </screen-density-groups>
 
   <locale-groups>
-    <locale-group label="europe">
+    <locale-group label="europe" version-code-order="1">
       <locale lang="en"/>
       <locale lang="es"/>
       <locale lang="fr"/>
       <locale lang="de" compressed="true"/>
     </locale-group>
 
-    <locale-group label="north-america">
+    <locale-group label="north-america" version-code-order="2">
       <locale lang="en"/>
       <locale lang="es" region="MX"/>
       <locale lang="fr" region="CA" compressed="true"/>
     </locale-group>
 
-    <locale-group label="all">
+    <locale-group label="all" version-code-order="0">
       <locale compressed="true"/>
     </locale-group>
   </locale-groups>
 
   <gl-texture-groups>
-    <gl-texture-group label="dxt1">
+    <gl-texture-group label="dxt1" version-code-order="1">
       <gl-texture name="GL_EXT_texture_compression_dxt1">
         <texture-path>assets/dxt1/*</texture-path>
       </gl-texture>
@@ -92,7 +92,7 @@
   </gl-texture-groups>
 
   <device-feature-groups>
-    <device-feature-group label="low-latency">
+    <device-feature-group label="low-latency" version-code-order="1">
       <supports-feature>android.hardware.audio.low_latency</supports-feature>
     </device-feature-group>
   </device-feature-groups>
diff --git a/tools/aapt2/link/XmlCompatVersioner_test.cpp b/tools/aapt2/link/XmlCompatVersioner_test.cpp
index 1ed4536..a98ab0f 100644
--- a/tools/aapt2/link/XmlCompatVersioner_test.cpp
+++ b/tools/aapt2/link/XmlCompatVersioner_test.cpp
@@ -23,6 +23,7 @@
 using ::testing::Eq;
 using ::testing::IsNull;
 using ::testing::NotNull;
+using ::testing::Pointee;
 using ::testing::SizeIs;
 
 namespace aapt {
@@ -287,13 +288,13 @@
   ASSERT_THAT(attr, NotNull());
   ASSERT_THAT(attr->compiled_value, NotNull());
   ASSERT_TRUE(attr->compiled_attribute);
-  ASSERT_THAT(*attr->compiled_value, ValueEq(padding_horizontal_value));
+  ASSERT_THAT(attr->compiled_value, Pointee(ValueEq(padding_horizontal_value)));
 
   attr = el->FindAttribute(xml::kSchemaAndroid, "paddingRight");
   ASSERT_THAT(attr, NotNull());
   ASSERT_THAT(attr->compiled_value, NotNull());
   ASSERT_TRUE(attr->compiled_attribute);
-  ASSERT_THAT(*attr->compiled_value, ValueEq(padding_horizontal_value));
+  ASSERT_THAT(attr->compiled_value, Pointee(ValueEq(padding_horizontal_value)));
 
   EXPECT_THAT(versioned_docs[1]->file.config.sdkVersion, Eq(SDK_LOLLIPOP_MR1));
   el = versioned_docs[1]->root.get();
@@ -302,21 +303,20 @@
 
   attr = el->FindAttribute(xml::kSchemaAndroid, "paddingHorizontal");
   ASSERT_THAT(attr, NotNull());
-  ASSERT_THAT(attr->compiled_value, NotNull());
   ASSERT_TRUE(attr->compiled_attribute);
-  ASSERT_THAT(*attr->compiled_value, ValueEq(padding_horizontal_value));
+  ASSERT_THAT(attr->compiled_value, Pointee(ValueEq(padding_horizontal_value)));
 
   attr = el->FindAttribute(xml::kSchemaAndroid, "paddingLeft");
   ASSERT_THAT(attr, NotNull());
   ASSERT_THAT(attr->compiled_value, NotNull());
   ASSERT_TRUE(attr->compiled_attribute);
-  ASSERT_THAT(*attr->compiled_value, ValueEq(padding_horizontal_value));
+  ASSERT_THAT(attr->compiled_value, Pointee(ValueEq(padding_horizontal_value)));
 
   attr = el->FindAttribute(xml::kSchemaAndroid, "paddingRight");
   ASSERT_THAT(attr, NotNull());
   ASSERT_THAT(attr->compiled_value, NotNull());
   ASSERT_TRUE(attr->compiled_attribute);
-  ASSERT_THAT(*attr->compiled_value, ValueEq(padding_horizontal_value));
+  ASSERT_THAT(attr->compiled_value, Pointee(ValueEq(padding_horizontal_value)));
 }
 
 }  // namespace aapt
diff --git a/tools/aapt2/optimize/MultiApkGenerator.cpp b/tools/aapt2/optimize/MultiApkGenerator.cpp
index 991faad..588b331 100644
--- a/tools/aapt2/optimize/MultiApkGenerator.cpp
+++ b/tools/aapt2/optimize/MultiApkGenerator.cpp
@@ -322,22 +322,56 @@
       std::unique_ptr<xml::Element> new_screens_el = util::make_unique<xml::Element>();
       new_screens_el->name = "compatible-screens";
       screens_el = new_screens_el.get();
-      manifest_el->InsertChild(0, std::move(new_screens_el));
+      manifest_el->AppendChild(std::move(new_screens_el));
     } else {
       // clear out the old element.
       screens_el->GetChildElements().clear();
     }
 
     for (const auto& density : artifact.screen_densities) {
-      std::unique_ptr<xml::Element> screen_el = util::make_unique<xml::Element>();
-      screen_el->name = "screen";
-      const char* density_str = density.toString().string();
-      screen_el->attributes.push_back(xml::Attribute{kSchemaAndroid, "screenDensity", density_str});
-      screens_el->AppendChild(std::move(screen_el));
+      AddScreens(density, screens_el);
     }
   }
 
   return true;
 }
 
+/**
+ * Adds a screen element with both screenSize and screenDensity set. Since we only know the density
+ * we add it for all screen sizes.
+ *
+ * This requires the resource IDs for the attributes from the framework library. Since these IDs are
+ * a part of the public API (and in public.xml) we hard code the values.
+ *
+ * The excert from the framework is as follows:
+ *    <public type="attr" name="screenSize" id="0x010102ca" />
+ *    <public type="attr" name="screenDensity" id="0x010102cb" />
+ */
+void MultiApkGenerator::AddScreens(const ConfigDescription& config, xml::Element* parent) {
+  // Hard coded integer representation of the supported screen sizes:
+  //  small   = 200
+  //  normal  = 300
+  //  large   = 400
+  //  xlarge  = 500
+  constexpr const uint32_t kScreenSizes[4] = {200, 300, 400, 500,};
+  constexpr const uint32_t kScreenSizeResourceId = 0x010102ca;
+  constexpr const uint32_t kScreenDensityResourceId = 0x010102cb;
+
+  for (uint32_t screen_size : kScreenSizes) {
+    std::unique_ptr<xml::Element> screen = util::make_unique<xml::Element>();
+    screen->name = "screen";
+
+    xml::Attribute* size = screen->FindOrCreateAttribute(kSchemaAndroid, "screenSize");
+    size->compiled_attribute = xml::AaptAttribute(Attribute(), {kScreenSizeResourceId});
+    size->compiled_value = ResourceUtils::MakeInt(screen_size);
+
+    xml::Attribute* density = screen->FindOrCreateAttribute(kSchemaAndroid, "screenDensity");
+    density->compiled_attribute = xml::AaptAttribute(Attribute(), {kScreenDensityResourceId});
+    density->compiled_value = ResourceUtils::MakeInt(config.density);
+
+
+    parent->AppendChild(std::move(screen));
+  }
+}
+
 }  // namespace aapt
diff --git a/tools/aapt2/optimize/MultiApkGenerator.h b/tools/aapt2/optimize/MultiApkGenerator.h
index 19f64cc..c858879 100644
--- a/tools/aapt2/optimize/MultiApkGenerator.h
+++ b/tools/aapt2/optimize/MultiApkGenerator.h
@@ -63,6 +63,11 @@
   bool UpdateManifest(const configuration::OutputArtifact& artifact,
                       std::unique_ptr<xml::XmlResource>* updated_manifest, IDiagnostics* diag);
 
+  /**
+   * Adds the <screen> elements to the parent node for the provided density configuration.
+   */
+  void AddScreens(const ConfigDescription& config, xml::Element* parent);
+
   LoadedApk* apk_;
   IAaptContext* context_;
 };
diff --git a/tools/aapt2/test/Common.h b/tools/aapt2/test/Common.h
index 4e318a9..aca161a 100644
--- a/tools/aapt2/test/Common.h
+++ b/tools/aapt2/test/Common.h
@@ -146,97 +146,70 @@
   return android::StringPiece16(arg) == a;
 }
 
-class ValueEq {
+template <typename T>
+class ValueEqImpl : public ::testing::MatcherInterface<T> {
  public:
-  template <typename arg_type>
-  class BaseImpl : public ::testing::MatcherInterface<arg_type> {
-    BaseImpl(const BaseImpl&) = default;
-
-    void DescribeTo(::std::ostream* os) const override {
-      *os << "is equal to " << *expected_;
-    }
-
-    void DescribeNegationTo(::std::ostream* os) const override {
-      *os << "is not equal to " << *expected_;
-    }
-
-   protected:
-    BaseImpl(const Value* expected) : expected_(expected) {
-    }
-
-    const Value* expected_;
-  };
-
-  template <typename T, bool>
-  class Impl {};
-
-  template <typename T>
-  class Impl<T, false> : public ::testing::MatcherInterface<T> {
-   public:
-    explicit Impl(const Value* expected) : expected_(expected) {
-    }
-
-    bool MatchAndExplain(T x, ::testing::MatchResultListener* listener) const override {
-      return expected_->Equals(&x);
-    }
-
-    void DescribeTo(::std::ostream* os) const override {
-      *os << "is equal to " << *expected_;
-    }
-
-    void DescribeNegationTo(::std::ostream* os) const override {
-      *os << "is not equal to " << *expected_;
-    }
-
-   private:
-    DISALLOW_COPY_AND_ASSIGN(Impl);
-
-    const Value* expected_;
-  };
-
-  template <typename T>
-  class Impl<T, true> : public ::testing::MatcherInterface<T> {
-   public:
-    explicit Impl(const Value* expected) : expected_(expected) {
-    }
-
-    bool MatchAndExplain(T x, ::testing::MatchResultListener* listener) const override {
-      return expected_->Equals(x);
-    }
-
-    void DescribeTo(::std::ostream* os) const override {
-      *os << "is equal to " << *expected_;
-    }
-
-    void DescribeNegationTo(::std::ostream* os) const override {
-      *os << "is not equal to " << *expected_;
-    }
-
-   private:
-    DISALLOW_COPY_AND_ASSIGN(Impl);
-
-    const Value* expected_;
-  };
-
-  ValueEq(const Value& expected) : expected_(&expected) {
+  explicit ValueEqImpl(const Value* expected) : expected_(expected) {
   }
-  ValueEq(const Value* expected) : expected_(expected) {
-  }
-  ValueEq(const ValueEq&) = default;
 
-  template <typename T>
-  operator ::testing::Matcher<T>() const {
-    return ::testing::Matcher<T>(new Impl<T, std::is_pointer<T>::value>(expected_));
+  bool MatchAndExplain(T x, ::testing::MatchResultListener* listener) const override {
+    return expected_->Equals(&x);
+  }
+
+  void DescribeTo(::std::ostream* os) const override {
+    *os << "is equal to " << *expected_;
+  }
+
+  void DescribeNegationTo(::std::ostream* os) const override {
+    *os << "is not equal to " << *expected_;
   }
 
  private:
+  DISALLOW_COPY_AND_ASSIGN(ValueEqImpl);
+
   const Value* expected_;
 };
 
-// MATCHER_P(ValueEq, a,
-//          std::string(negation ? "isn't" : "is") + " equal to " + ::testing::PrintToString(a)) {
-//  return arg.Equals(&a);
-//}
+template <typename TValue>
+class ValueEqMatcher {
+ public:
+  ValueEqMatcher(TValue expected) : expected_(std::move(expected)) {
+  }
+
+  template <typename T>
+  operator ::testing::Matcher<T>() const {
+    return ::testing::Matcher<T>(new ValueEqImpl<T>(&expected_));
+  }
+
+ private:
+  TValue expected_;
+};
+
+template <typename TValue>
+class ValueEqPointerMatcher {
+ public:
+  ValueEqPointerMatcher(const TValue* expected) : expected_(expected) {
+  }
+
+  template <typename T>
+  operator ::testing::Matcher<T>() const {
+    return ::testing::Matcher<T>(new ValueEqImpl<T>(expected_));
+  }
+
+ private:
+  const TValue* expected_;
+};
+
+template <typename TValue,
+          typename = typename std::enable_if<!std::is_pointer<TValue>::value, void>::type>
+inline ValueEqMatcher<TValue> ValueEq(TValue value) {
+  return ValueEqMatcher<TValue>(std::move(value));
+}
+
+template <typename TValue>
+inline ValueEqPointerMatcher<TValue> ValueEq(const TValue* value) {
+  return ValueEqPointerMatcher<TValue>(value);
+}
 
 MATCHER_P(StrValueEq, a,
           std::string(negation ? "isn't" : "is") + " equal to " + ::testing::PrintToString(a)) {
diff --git a/tools/aapt2/xml/XmlDom.cpp b/tools/aapt2/xml/XmlDom.cpp
index fddb6b8..7b748ce 100644
--- a/tools/aapt2/xml/XmlDom.cpp
+++ b/tools/aapt2/xml/XmlDom.cpp
@@ -244,14 +244,13 @@
       str16 = parser->getAttributeStringValue(i, &len);
       if (str16) {
         attr.value = util::Utf16ToUtf8(StringPiece16(str16, len));
-      } else {
-        android::Res_value res_value;
-        if (parser->getAttributeValue(i, &res_value) > 0) {
-          attr.compiled_value = ResourceUtils::ParseBinaryResValue(
-              ResourceType::kAnim, {}, parser->getStrings(), res_value, out_pool);
-        }
       }
 
+      android::Res_value res_value;
+      if (parser->getAttributeValue(i, &res_value) > 0) {
+        attr.compiled_value = ResourceUtils::ParseBinaryResValue(
+            ResourceType::kAnim, {}, parser->getStrings(), res_value, out_pool);
+      }
 
       el->attributes.push_back(std::move(attr));
     }
diff --git a/tools/aapt2/xml/XmlDom_test.cpp b/tools/aapt2/xml/XmlDom_test.cpp
index e5012d6..486b53a 100644
--- a/tools/aapt2/xml/XmlDom_test.cpp
+++ b/tools/aapt2/xml/XmlDom_test.cpp
@@ -23,8 +23,10 @@
 #include "test/Test.h"
 
 using ::aapt::io::StringInputStream;
+using ::aapt::test::ValueEq;
 using ::testing::Eq;
 using ::testing::NotNull;
+using ::testing::Pointee;
 using ::testing::SizeIs;
 using ::testing::StrEq;
 
@@ -59,6 +61,16 @@
   doc->root->name = "Layout";
   doc->root->line_number = 2u;
 
+  xml::Attribute attr;
+  attr.name = "text";
+  attr.namespace_uri = kSchemaAndroid;
+  attr.compiled_attribute = AaptAttribute(
+      aapt::Attribute(android::ResTable_map::TYPE_REFERENCE | android::ResTable_map::TYPE_STRING),
+      ResourceId(0x01010001u));
+  attr.value = "@string/foo";
+  attr.compiled_value = test::BuildReference("string/foo", ResourceId(0x7f010000u));
+  doc->root->attributes.push_back(std::move(attr));
+
   NamespaceDecl decl;
   decl.uri = kSchemaAndroid;
   decl.prefix = "android";
@@ -66,7 +78,9 @@
   doc->root->namespace_decls.push_back(decl);
 
   BigBuffer buffer(4096);
-  XmlFlattener flattener(&buffer, {});
+  XmlFlattenerOptions options;
+  options.keep_raw_values = true;
+  XmlFlattener flattener(&buffer, options);
   ASSERT_TRUE(flattener.Consume(context.get(), doc.get()));
 
   auto block = util::Copy(buffer);
@@ -75,6 +89,21 @@
 
   EXPECT_THAT(new_doc->root->name, StrEq("Layout"));
   EXPECT_THAT(new_doc->root->line_number, Eq(2u));
+
+  ASSERT_THAT(new_doc->root->attributes, SizeIs(1u));
+  EXPECT_THAT(new_doc->root->attributes[0].name, StrEq("text"));
+  EXPECT_THAT(new_doc->root->attributes[0].namespace_uri, StrEq(kSchemaAndroid));
+
+  // We only check that the resource ID was preserved. There is no where to encode the types that
+  // the Attribute accepts (eg: string|reference).
+  ASSERT_TRUE(new_doc->root->attributes[0].compiled_attribute);
+  EXPECT_THAT(new_doc->root->attributes[0].compiled_attribute.value().id,
+              Eq(make_value(ResourceId(0x01010001u))));
+
+  EXPECT_THAT(new_doc->root->attributes[0].value, StrEq("@string/foo"));
+  EXPECT_THAT(new_doc->root->attributes[0].compiled_value,
+              Pointee(ValueEq(Reference(ResourceId(0x7f010000u)))));
+
   ASSERT_THAT(new_doc->root->namespace_decls, SizeIs(1u));
   EXPECT_THAT(new_doc->root->namespace_decls[0].uri, StrEq(kSchemaAndroid));
   EXPECT_THAT(new_doc->root->namespace_decls[0].prefix, StrEq("android"));
diff --git a/tools/apilint/apilint.py b/tools/apilint/apilint.py
index 399b0c6..26248e5 100644
--- a/tools/apilint/apilint.py
+++ b/tools/apilint/apilint.py
@@ -309,6 +309,8 @@
         warn(clazz, None, "S1", "Class names with acronyms should be Mtp not MTP")
     if re.match("[^A-Z]", clazz.name):
         error(clazz, None, "S1", "Class must start with uppercase char")
+    if clazz.name.endswith("Impl"):
+        error(clazz, None, None, "Don't expose your implementation details")
 
 
 def verify_method_names(clazz):
@@ -1291,6 +1293,44 @@
             warn(clazz, m, None, "Unexpected tense; probably meant 'enabled'")
 
 
+def verify_icu(clazz):
+    """Verifies that richer ICU replacements are used."""
+    better = {
+        "java.util.TimeZone": "android.icu.util.TimeZone",
+        "java.util.Calendar": "android.icu.util.Calendar",
+        "java.util.Locale": "android.icu.util.ULocale",
+        "java.util.ResourceBundle": "android.icu.util.UResourceBundle",
+        "java.util.SimpleTimeZone": "android.icu.util.SimpleTimeZone",
+        "java.util.StringTokenizer": "android.icu.util.StringTokenizer",
+        "java.util.GregorianCalendar": "android.icu.util.GregorianCalendar",
+        "java.lang.Character": "android.icu.lang.UCharacter",
+        "java.text.BreakIterator": "android.icu.text.BreakIterator",
+        "java.text.Collator": "android.icu.text.Collator",
+        "java.text.DecimalFormatSymbols": "android.icu.text.DecimalFormatSymbols",
+        "java.text.NumberFormat": "android.icu.text.NumberFormat",
+        "java.text.DateFormatSymbols": "android.icu.text.DateFormatSymbols",
+        "java.text.DateFormat": "android.icu.text.DateFormat",
+        "java.text.SimpleDateFormat": "android.icu.text.SimpleDateFormat",
+        "java.text.MessageFormat": "android.icu.text.MessageFormat",
+        "java.text.DecimalFormat": "android.icu.text.DecimalFormat",
+    }
+
+    for m in clazz.ctors + clazz.methods:
+        types = []
+        types.extend(m.typ)
+        types.extend(m.args)
+        for arg in types:
+            if arg in better:
+                warn(clazz, m, None, "Type %s should be replaced with richer ICU type %s" % (arg, better[arg]))
+
+
+def verify_clone(clazz):
+    """Verify that clone() isn't implemented; see EJ page 61."""
+    for m in clazz.methods:
+        if m.name == "clone":
+            error(clazz, m, None, "Provide an explicit copy constructor instead of implementing clone()")
+
+
 def examine_clazz(clazz):
     """Find all style issues in the given class."""
 
@@ -1352,6 +1392,8 @@
     verify_params(clazz)
     verify_services(clazz)
     verify_tense(clazz)
+    verify_icu(clazz)
+    verify_clone(clazz)
 
 
 def examine_stream(stream):
diff --git a/tools/sdkparcelables/src/com/android/sdkparcelables/AncestorCollector.kt b/tools/sdkparcelables/src/com/android/sdkparcelables/AncestorCollector.kt
index f278aec..d75aea5 100644
--- a/tools/sdkparcelables/src/com/android/sdkparcelables/AncestorCollector.kt
+++ b/tools/sdkparcelables/src/com/android/sdkparcelables/AncestorCollector.kt
@@ -1,3 +1,19 @@
+/*
+ * 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.sdkparcelables
 
 import org.objectweb.asm.ClassVisitor
@@ -25,4 +41,4 @@
 
         super.visit(version, access, name, signature, superName, interfaces)
     }
-}
\ No newline at end of file
+}
diff --git a/tools/sdkparcelables/src/com/android/sdkparcelables/Main.kt b/tools/sdkparcelables/src/com/android/sdkparcelables/Main.kt
index 3e9d92c..22e8d78 100644
--- a/tools/sdkparcelables/src/com/android/sdkparcelables/Main.kt
+++ b/tools/sdkparcelables/src/com/android/sdkparcelables/Main.kt
@@ -1,3 +1,19 @@
+/*
+ * 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.sdkparcelables
 
 import org.objectweb.asm.ClassReader
@@ -53,4 +69,4 @@
 fun usage() {
     System.err.println("Usage: <input jar> <output aidl>")
     kotlin.system.exitProcess(1)
-}
\ No newline at end of file
+}
diff --git a/tools/sdkparcelables/src/com/android/sdkparcelables/ParcelableDetector.kt b/tools/sdkparcelables/src/com/android/sdkparcelables/ParcelableDetector.kt
index 620f798..45027b5 100644
--- a/tools/sdkparcelables/src/com/android/sdkparcelables/ParcelableDetector.kt
+++ b/tools/sdkparcelables/src/com/android/sdkparcelables/ParcelableDetector.kt
@@ -1,3 +1,19 @@
+/*
+ * 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.sdkparcelables
 
 /** A class that uses an ancestor map to find all classes that
@@ -11,6 +27,8 @@
             impl.build()
             return impl.parcelables
         }
+
+        const val PARCELABLE_CLASS = "android/os/Parcelable"
     }
 
     private class Impl(val ancestors: Map<String, Ancestors>) {
@@ -19,7 +37,7 @@
 
         fun build() {
             val classList = ancestors.keys
-            classList.filterTo(parcelables, this::isParcelable)
+            classList.filterTo(parcelables, { (it != PARCELABLE_CLASS) && isParcelable(it) })
             parcelables.sort()
         }
 
@@ -28,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 edfc825..f08173d 100644
--- a/tools/sdkparcelables/tests/com/android/sdkparcelables/ParcelableDetectorTest.kt
+++ b/tools/sdkparcelables/tests/com/android/sdkparcelables/ParcelableDetectorTest.kt
@@ -1,3 +1,19 @@
+/*
+ * 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.sdkparcelables
 
 import junit.framework.TestCase.assertEquals
@@ -12,7 +28,7 @@
 
         val parcelables = ParcelableDetector.ancestorsToParcelables(ancestorMap)
 
-        assertEquals(parcelables, listOf("android/os/Parcelable", "android/test/Parcelable"))
+        assertEquals(parcelables, listOf("android/test/Parcelable"))
     }
 
     @Test
@@ -23,7 +39,7 @@
 
         val parcelables = ParcelableDetector.ancestorsToParcelables(ancestorMap)
 
-        assertEquals(parcelables, listOf("android/os/Parcelable", "android/test/Parcelable"))
+        assertEquals(parcelables, listOf("android/test/Parcelable"))
     }
 
     @Test
@@ -35,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
@@ -47,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/tools/stats_log_api_gen/Android.bp b/tools/stats_log_api_gen/Android.bp
index e301eb1..dc2ed43 100644
--- a/tools/stats_log_api_gen/Android.bp
+++ b/tools/stats_log_api_gen/Android.bp
@@ -102,6 +102,7 @@
     export_generated_headers: ["statslog.h"],
     shared_libs: [
         "liblog",
+        "libutils",
     ],
 }
 
diff --git a/tools/stats_log_api_gen/main.cpp b/tools/stats_log_api_gen/main.cpp
index 3dbb503..f0628c0 100644
--- a/tools/stats_log_api_gen/main.cpp
+++ b/tools/stats_log_api_gen/main.cpp
@@ -105,6 +105,7 @@
     fprintf(out, "#include <log/log_event_list.h>\n");
     fprintf(out, "#include <log/log.h>\n");
     fprintf(out, "#include <statslog.h>\n");
+    fprintf(out, "#include <utils/SystemClock.h>\n");
     fprintf(out, "\n");
 
     fprintf(out, "namespace android {\n");
@@ -145,6 +146,7 @@
         fprintf(out, "{\n");
         argIndex = 1;
         fprintf(out, "    android_log_event_list event(kStatsEventTag);\n");
+        fprintf(out, "    event << android::elapsedRealtimeNano();\n\n");
         fprintf(out, "    event << code;\n\n");
         for (vector<java_type_t>::const_iterator arg = signature->begin();
             arg != signature->end(); arg++) {
@@ -212,6 +214,7 @@
         fprintf(out, "{\n");
         argIndex = 1;
         fprintf(out, "    android_log_event_list event(kStatsEventTag);\n");
+        fprintf(out, "    event << android::elapsedRealtimeNano();\n\n");
         fprintf(out, "    event << code;\n\n");
         for (vector<java_type_t>::const_iterator arg = signature->begin();
             arg != signature->end(); arg++) {
diff --git a/wifi/OWNERS b/wifi/OWNERS
new file mode 100644
index 0000000..0efa464
--- /dev/null
+++ b/wifi/OWNERS
@@ -0,0 +1,5 @@
+set noparent
+
+etancohen@google.com
+satk@google.com
+silberst@google.com
diff --git a/wifi/java/android/net/wifi/IRttManager.aidl b/wifi/java/android/net/wifi/IRttManager.aidl
deleted file mode 100644
index 3831809..0000000
--- a/wifi/java/android/net/wifi/IRttManager.aidl
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.wifi;
-import android.os.Messenger;
-import android.net.wifi.RttManager;
-
-/**
- * {@hide}
- */
-interface IRttManager
-{
-    Messenger getMessenger(in IBinder binder, out int[] key);
-    RttManager.RttCapabilities getRttCapabilities();
-}
diff --git a/wifi/java/android/net/wifi/RttManager.java b/wifi/java/android/net/wifi/RttManager.java
index fe63aa1..b5273dd 100644
--- a/wifi/java/android/net/wifi/RttManager.java
+++ b/wifi/java/android/net/wifi/RttManager.java
@@ -12,9 +12,9 @@
 import android.net.wifi.rtt.RangingResult;
 import android.net.wifi.rtt.RangingResultCallback;
 import android.net.wifi.rtt.WifiRttManager;
-import android.os.Looper;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.os.SystemClock;
 import android.util.Log;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -24,6 +24,7 @@
 
 /** @hide */
 @SystemApi
+@Deprecated
 @SystemService(Context.WIFI_RTT_SERVICE)
 public class RttManager {
 
@@ -181,6 +182,7 @@
     /**
      * This class describe the RTT capability of the Hardware
      */
+    @Deprecated
     public static class RttCapabilities implements Parcelable {
         /** @deprecated It is not supported*/
         @Deprecated
@@ -314,12 +316,16 @@
              };
     }
 
+    /**
+     * This method is deprecated. Please use the {@link WifiRttManager} API.
+     */
     @RequiresPermission(Manifest.permission.LOCATION_HARDWARE)
     public RttCapabilities getRttCapabilities() {
         return mRttCapabilities;
     }
 
     /** specifies parameters for RTT request */
+    @Deprecated
     public static class RttParams {
         /**
          * type of destination device being ranged
@@ -502,6 +508,7 @@
     }
 
     /** pseudo-private class used to parcel arguments */
+    @Deprecated
     public static class ParcelableRttParams implements Parcelable {
 
         @NonNull
@@ -589,12 +596,14 @@
                 };
     }
 
+    @Deprecated
     public static class WifiInformationElement {
         /** Information Element ID 0xFF means element is invalid. */
         public byte id;
         public byte[] data;
     }
     /** specifies RTT results */
+    @Deprecated
     public static class RttResult {
         /** mac address of the device being ranged. */
         public String bssid;
@@ -746,6 +755,7 @@
 
 
     /** pseudo-private class used to parcel results. */
+    @Deprecated
     public static class ParcelableRttResults implements Parcelable {
 
         public RttResult mResults[];
@@ -838,8 +848,8 @@
                     }
                     dest.writeByte(result.LCR.id);
                     if (result.LCR.id != (byte) 0xFF) {
-                        dest.writeInt((byte) result.LCR.data.length);
-                        dest.writeByte(result.LCR.id);
+                        dest.writeByte((byte) result.LCR.data.length);
+                        dest.writeByteArray(result.LCR.data);
                     }
                     dest.writeByte(result.secure ? (byte) 1 : 0);
                 }
@@ -911,7 +921,7 @@
                 };
     }
 
-
+    @Deprecated
     public static interface RttListener {
         public void onSuccess(RttResult[] results);
         public void onFailure(int reason, String description);
@@ -919,52 +929,11 @@
     }
 
     /**
-     * A parcelable that contains rtt client information.
-     *
-     * @hide
-     */
-    public static class RttClient implements Parcelable {
-        // Package name of RttClient.
-        private final String mPackageName;
-
-        public RttClient(String packageName) {
-            mPackageName = packageName;
-        }
-
-        protected RttClient(Parcel in) {
-            mPackageName = in.readString();
-        }
-
-        public static final Creator<RttManager.RttClient> CREATOR =
-                new Creator<RttManager.RttClient>() {
-            @Override
-            public RttManager.RttClient createFromParcel(Parcel in) {
-                return new RttManager.RttClient(in);
-            }
-
-            @Override
-            public RttManager.RttClient[] newArray(int size) {
-                return new RttManager.RttClient[size];
-            }
-        };
-
-        @Override
-        public int describeContents() {
-            return 0;
-        }
-
-        @Override
-        public void writeToParcel(Parcel parcel, int i) {
-            parcel.writeString(mPackageName);
-        }
-
-        public String getPackageName() {
-            return mPackageName;
-        }
-    }
-
-    /**
      * Request to start an RTT ranging
+     * <p>
+     * This method is deprecated. Please use the
+     * {@link WifiRttManager#startRanging(RangingRequest, java.util.concurrent.Executor, RangingResultCallback)}
+     * API.
      *
      * @param params  -- RTT request Parameters
      * @param listener -- Call back to inform RTT result
@@ -1000,7 +969,9 @@
                     android.net.wifi.rtt.ResponderConfig.fromScanResult(reconstructed));
         }
         try {
-            mNewService.startRanging(builder.build(), new RangingResultCallback() {
+            mNewService.startRanging(builder.build(),
+                    mContext.getMainExecutor(),
+                    new RangingResultCallback() {
                 @Override
                 public void onRangingFailure(int code) {
                     int localCode = REASON_UNSPECIFIED;
@@ -1018,15 +989,20 @@
                         legacyResults[i] = new RttResult();
                         legacyResults[i].status = result.getStatus();
                         legacyResults[i].bssid = result.getMacAddress().toString();
-                        legacyResults[i].distance = result.getDistanceMm() / 10;
-                        legacyResults[i].distanceStandardDeviation =
-                                result.getDistanceStdDevMm() / 10;
-                        legacyResults[i].rssi = result.getRssi();
-                        legacyResults[i].ts = result.getRangingTimestampUs();
+                        if (result.getStatus() == RangingResult.STATUS_SUCCESS) {
+                            legacyResults[i].distance = result.getDistanceMm() / 10;
+                            legacyResults[i].distanceStandardDeviation =
+                                    result.getDistanceStdDevMm() / 10;
+                            legacyResults[i].rssi = result.getRssi() * -2;
+                            legacyResults[i].ts = result.getRangingTimestampMillis() * 1000;
+                        } else {
+                            // just in case legacy API needed some relatively real timestamp
+                            legacyResults[i].ts = SystemClock.elapsedRealtime() * 1000;
+                        }
                     }
                     listener.onSuccess(legacyResults);
                 }
-            }, null);
+            });
         } catch (IllegalArgumentException e) {
             Log.e(TAG, "startRanging: invalid arguments - " + e);
             listener.onFailure(REASON_INVALID_REQUEST, e.getMessage());
@@ -1036,6 +1012,10 @@
         }
     }
 
+    /**
+     * This method is deprecated and performs no function. Please use the {@link WifiRttManager}
+     * API.
+     */
     @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
     public void stopRanging(RttListener listener) {
         Log.e(TAG, "stopRanging: unsupported operation - nop");
@@ -1050,6 +1030,7 @@
      * The client can freely destroy or reuse the callback after {@link RttManager#disableResponder}
      * is called.
      */
+    @Deprecated
     public abstract static class ResponderCallback {
         /** Callback when responder is enabled. */
         public abstract void onResponderEnabled(ResponderConfig config);
@@ -1065,6 +1046,10 @@
      * Note calling this method with the same callback when the responder is already enabled won't
      * change the responder state, a cached {@link ResponderConfig} from the last enabling will be
      * returned through the callback.
+     * <p>
+     * This method is deprecated and will throw an {@link UnsupportedOperationException}
+     * exception. Please use the {@link WifiRttManager} API to perform a Wi-Fi Aware peer-to-peer
+     * ranging.
      *
      * @param callback Callback for responder enabling/disabling result.
      * @throws IllegalArgumentException If {@code callback} is null.
@@ -1081,6 +1066,10 @@
      * <p>
      * Calling this method when responder isn't enabled won't have any effect. The callback can be
      * reused for enabling responder after this method is called.
+     * <p>
+     * This method is deprecated and will throw an {@link UnsupportedOperationException}
+     * exception. Please use the {@link WifiRttManager} API to perform a Wi-Fi Aware peer-to-peer
+     * ranging.
      *
      * @param callback The same callback used for enabling responder.
      * @throws IllegalArgumentException If {@code callback} is null.
@@ -1097,6 +1086,7 @@
      *
      * @see ScanResult
      */
+    @Deprecated
     public static class ResponderConfig implements Parcelable {
 
         // TODO: make all fields final once we can get mac address from responder HAL APIs.
@@ -1202,8 +1192,8 @@
     /** @hide */
     public static final int CMD_OP_REG_BINDER           = BASE + 9;
 
-    private final Context mContext;
     private final WifiRttManager mNewService;
+    private final Context mContext;
     private RttCapabilities mRttCapabilities;
 
     /**
@@ -1211,17 +1201,15 @@
      * Applications will almost always want to use
      * {@link android.content.Context#getSystemService Context.getSystemService()} to retrieve
      * the standard {@link android.content.Context#WIFI_RTT_SERVICE Context.WIFI_RTT_SERVICE}.
-     * @param context the application context
-     * @param service the Binder interface
-     * @param looper Looper for running the callbacks.
+     * @param service the new WifiRttManager service
      *
      * @hide
      */
-    public RttManager(Context context, IRttManager service, Looper looper) {
+    public RttManager(Context context, WifiRttManager service) {
+        mNewService = service;
         mContext = context;
-        mNewService = (WifiRttManager) mContext.getSystemService(Context.WIFI_RTT_RANGING_SERVICE);
 
-        boolean rttSupported = mContext.getPackageManager().hasSystemFeature(
+        boolean rttSupported = context.getPackageManager().hasSystemFeature(
                 PackageManager.FEATURE_WIFI_RTT);
 
         mRttCapabilities = new RttCapabilities();
diff --git a/wifi/java/android/net/wifi/ScanResult.java b/wifi/java/android/net/wifi/ScanResult.java
index c46789c..8024bf0 100644
--- a/wifi/java/android/net/wifi/ScanResult.java
+++ b/wifi/java/android/net/wifi/ScanResult.java
@@ -273,27 +273,6 @@
     public RadioChainInfo[] radioChainInfos;
 
     /**
-     * @hide
-     * Update RSSI of the scan result
-     * @param previousRssi
-     * @param previousSeen
-     * @param maxAge
-     */
-    public void averageRssi(int previousRssi, long previousSeen, int maxAge) {
-
-        if (seen == 0) {
-            seen = System.currentTimeMillis();
-        }
-        long age = seen - previousSeen;
-
-        if (previousSeen > 0 && age > 0 && age < maxAge/2) {
-            // Average the RSSI with previously seen instances of this scan result
-            double alpha = 0.5 - (double) age / (double) maxAge;
-            level = (int) ((double) level * (1 - alpha) + (double) previousRssi * alpha);
-        }
-    }
-
-    /**
      * Status indicating the scan result does not correspond to a user's saved configuration
      * @hide
      * @removed
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index 7da2656..ddcf327 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -917,6 +917,9 @@
      * Does not guarantee that the returned address is valid for use.
      */
     public MacAddress getRandomizedMacAddress() {
+        if (mRandomizedMacAddress == null) {
+            mRandomizedMacAddress = MacAddress.ALL_ZEROS_ADDRESS;
+        }
         return mRandomizedMacAddress;
     }
 
@@ -1617,6 +1620,7 @@
         creatorUid = -1;
         shared = true;
         dtimInterval = 0;
+        mRandomizedMacAddress = MacAddress.ALL_ZEROS_ADDRESS;
     }
 
     /**
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 3396857..8ccccf4 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -99,35 +99,45 @@
     // Supplicant error codes:
     /**
      * The error code if there was a problem authenticating.
+     * @deprecated This is no longer supported.
      */
+    @Deprecated
     public static final int ERROR_AUTHENTICATING = 1;
 
     /**
      * The reason code if there is no error during authentication.
      * It could also imply that there no authentication in progress,
      * this reason code also serves as a reset value.
+     * @deprecated This is no longer supported.
      * @hide
      */
+    @Deprecated
     public static final int ERROR_AUTH_FAILURE_NONE = 0;
 
     /**
      * The reason code if there was a timeout authenticating.
+     * @deprecated This is no longer supported.
      * @hide
      */
+    @Deprecated
     public static final int ERROR_AUTH_FAILURE_TIMEOUT = 1;
 
     /**
      * The reason code if there was a wrong password while
      * authenticating.
+     * @deprecated This is no longer supported.
      * @hide
      */
+    @Deprecated
     public static final int ERROR_AUTH_FAILURE_WRONG_PSWD = 2;
 
     /**
      * The reason code if there was EAP failure while
      * authenticating.
+     * @deprecated This is no longer supported.
      * @hide
      */
+    @Deprecated
     public static final int ERROR_AUTH_FAILURE_EAP_FAILURE = 3;
 
     /**
@@ -565,8 +575,10 @@
      * to perform Wi-Fi operations) or the connection to the supplicant has been
      * lost. One extra provides the connection state as a boolean, where {@code true}
      * means CONNECTED.
+     * @deprecated This is no longer supported.
      * @see #EXTRA_SUPPLICANT_CONNECTED
      */
+    @Deprecated
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String SUPPLICANT_CONNECTION_CHANGE_ACTION =
         "android.net.wifi.supplicant.CONNECTION_CHANGE";
@@ -575,7 +587,9 @@
      * the supplicant daemon has been gained or lost. {@code true} means
      * a connection now exists.
      * Retrieve it with {@link android.content.Intent#getBooleanExtra(String,boolean)}.
+     * @deprecated This is no longer supported.
      */
+    @Deprecated
     public static final String EXTRA_SUPPLICANT_CONNECTED = "connected";
     /**
      * Broadcast intent action indicating that the state of Wi-Fi connectivity
@@ -612,7 +626,9 @@
      * the overall state of connectivity.
      * @see #EXTRA_NEW_STATE
      * @see #EXTRA_SUPPLICANT_ERROR
+     * @deprecated This is no longer supported.
      */
+    @Deprecated
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String SUPPLICANT_STATE_CHANGED_ACTION =
         "android.net.wifi.supplicant.STATE_CHANGE";
@@ -620,7 +636,9 @@
      * The lookup key for a {@link SupplicantState} describing the new state
      * Retrieve with
      * {@link android.content.Intent#getParcelableExtra(String)}.
+     * @deprecated This is no longer supported.
      */
+    @Deprecated
     public static final String EXTRA_NEW_STATE = "newState";
 
     /**
@@ -629,7 +647,9 @@
      * Retrieve with
      * {@link android.content.Intent#getIntExtra(String, int)}.
      * @see #ERROR_AUTHENTICATING
+     * @deprecated This is no longer supported.
      */
+    @Deprecated
     public static final String EXTRA_SUPPLICANT_ERROR = "supplicantError";
 
     /**
@@ -638,8 +658,10 @@
      * Retrieve with
      * {@link android.content.Intent#getIntExtra(String, int)}.
      * @see #ERROR_AUTH_FAILURE_#REASON_CODE
+     * @deprecated This is no longer supported.
      * @hide
      */
+    @Deprecated
     public static final String EXTRA_SUPPLICANT_ERROR_REASON = "supplicantErrorReason";
 
     /**
@@ -3636,8 +3658,10 @@
      * Restore state from the older version of back up data.
      * The old backup data was essentially a backup of wpa_supplicant.conf
      * and ipconfig.txt file.
+     * @deprecated this is no longer supported.
      * @hide
      */
+    @Deprecated
     public void restoreSupplicantBackupData(byte[] supplicantData, byte[] ipConfigData) {
         try {
             mService.restoreSupplicantBackupData(supplicantData, ipConfigData);
diff --git a/wifi/java/android/net/wifi/WpsInfo.java b/wifi/java/android/net/wifi/WpsInfo.java
index ae2e771..d12cce1 100644
--- a/wifi/java/android/net/wifi/WpsInfo.java
+++ b/wifi/java/android/net/wifi/WpsInfo.java
@@ -21,37 +21,58 @@
 
 /**
  * A class representing Wi-Fi Protected Setup
- *
+ * @deprecated This class is no longer supported.
  * {@see WifiP2pConfig}
  */
+@Deprecated
 public class WpsInfo implements Parcelable {
 
-    /** Push button configuration */
+    /** Push button configuration
+     * @deprecated This is no longer supported.*/
+    @Deprecated
     public static final int PBC     = 0;
-    /** Display pin method configuration - pin is generated and displayed on device */
+    /** Display pin method configuration - pin is generated and displayed on device
+     * @deprecated This is no longer supported.*/
+    @Deprecated
     public static final int DISPLAY = 1;
-    /** Keypad pin method configuration - pin is entered on device */
+    /** Keypad pin method configuration - pin is entered on device
+     * @deprecated This is no longer supported.*/
+    @Deprecated
     public static final int KEYPAD  = 2;
-    /** Label pin method configuration - pin is labelled on device */
+    /** Label pin method configuration - pin is labelled on device
+     * @deprecated This is no longer supported.*/
+    @Deprecated
     public static final int LABEL   = 3;
-    /** Invalid configuration */
+    /** Invalid configuration
+     * @deprecated This is no longer supported.*/
+    @Deprecated
     public static final int INVALID = 4;
 
-    /** Wi-Fi Protected Setup. www.wi-fi.org/wifi-protected-setup has details */
+    /** Wi-Fi Protected Setup. www.wi-fi.org/wifi-protected-setup has details
+     * @deprecated This is no longer supported.*/
+    @Deprecated
     public int setup;
 
-    /** Passed with pin method KEYPAD */
+    /** Passed with pin method KEYPAD
+     * @deprecated This is no longer supported.*/
+    @Deprecated
     public String BSSID;
 
-    /** Passed with pin method configuration */
+    /** Passed with pin method configuration
+     * @deprecated This is no longer supported.*/
+    @Deprecated
     public String pin;
 
+    /** @deprecated This API is no longer supported.*/
+    @Deprecated
     public WpsInfo() {
         setup = INVALID;
         BSSID = null;
         pin = null;
     }
 
+    /** @deprecated This API is no longer supported.*/
+    @Deprecated
     public String toString() {
         StringBuffer sbuf = new StringBuffer();
         sbuf.append(" setup: ").append(setup);
@@ -63,12 +84,16 @@
         return sbuf.toString();
     }
 
-    /** Implement the Parcelable interface */
+    /** Implement the Parcelable interface
+     * @deprecated This API is no longer supported.*/
+    @Deprecated
     public int describeContents() {
         return 0;
     }
 
-    /* Copy constructor */
+    /* Copy constructor
+    * @deprecated This API is no longer supported.*/
+    @Deprecated
     public WpsInfo(WpsInfo source) {
         if (source != null) {
             setup = source.setup;
@@ -77,16 +102,22 @@
         }
     }
 
-    /** Implement the Parcelable interface */
+    /** Implement the Parcelable interface
+     * @deprecated This API is no longer supported. */
+    @Deprecated
     public void writeToParcel(Parcel dest, int flags) {
         dest.writeInt(setup);
         dest.writeString(BSSID);
         dest.writeString(pin);
     }
 
-    /** Implement the Parcelable interface */
+    /** Implement the Parcelable interface
+     * @deprecated This API is no longer supported.*/
+    @Deprecated
     public static final Creator<WpsInfo> CREATOR =
         new Creator<WpsInfo>() {
+            /** @deprecated This API is nolonger supported.*/
+            @Deprecated
             public WpsInfo createFromParcel(Parcel in) {
                 WpsInfo config = new WpsInfo();
                 config.setup = in.readInt();
@@ -95,6 +126,8 @@
                 return config;
             }
 
+            /** @deprecated This API is nolonger supported.*/
+            @Deprecated
             public WpsInfo[] newArray(int size) {
                 return new WpsInfo[size];
             }
diff --git a/wifi/java/android/net/wifi/rtt/LocationCivic.java b/wifi/java/android/net/wifi/rtt/LocationCivic.java
deleted file mode 100644
index 610edb6..0000000
--- a/wifi/java/android/net/wifi/rtt/LocationCivic.java
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.wifi.rtt;
-
-import android.annotation.Nullable;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.util.Arrays;
-import java.util.Objects;
-
-/**
- * Location Civic Report (LCR).
- * <p>
- * The information matches the IEEE 802.11-2016 LCR report.
- * <p>
- * Note: depending on the mechanism by which this information is returned (i.e. the API which
- * returns an instance of this class) it is possibly Self Reported (by the peer). In such a case
- * the information is NOT validated - use with caution. Consider validating it with other sources
- * of information before using it.
- */
-public final class LocationCivic implements Parcelable {
-    private final byte[] mData;
-
-    /**
-     * Parse the raw LCR information element (byte array) and extract the LocationCivic structure.
-     *
-     * Note: any parsing errors or invalid/unexpected errors will result in a null being returned.
-     *
-     * @hide
-     */
-    @Nullable
-    public static LocationCivic parseInformationElement(byte id, byte[] data) {
-        // TODO
-        return null;
-    }
-
-    /** @hide */
-    public LocationCivic(byte[] data) {
-        mData = data;
-    }
-
-    /**
-     * Return the Location Civic data reported by the peer.
-     *
-     * @return An arbitrary location information.
-     */
-    public byte[] getData() {
-        return mData;
-    }
-
-    /** @hide */
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    /** @hide */
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        dest.writeByteArray(mData);
-    }
-
-    public static final Parcelable.Creator<LocationCivic> CREATOR =
-            new Parcelable.Creator<LocationCivic>() {
-                @Override
-                public LocationCivic[] newArray(int size) {
-                    return new LocationCivic[size];
-                }
-
-                @Override
-                public LocationCivic createFromParcel(Parcel in) {
-                    byte[] data = in.createByteArray();
-
-                    return new LocationCivic(data);
-                }
-            };
-
-    /** @hide */
-    @Override
-    public String toString() {
-        return new StringBuilder("LCR: data=").append(Arrays.toString(mData)).toString();
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) {
-            return true;
-        }
-
-        if (!(o instanceof LocationCivic)) {
-            return false;
-        }
-
-        LocationCivic lhs = (LocationCivic) o;
-
-        return Arrays.equals(mData, lhs.mData);
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(mData);
-    }
-}
diff --git a/wifi/java/android/net/wifi/rtt/LocationConfigurationInformation.java b/wifi/java/android/net/wifi/rtt/LocationConfigurationInformation.java
deleted file mode 100644
index 8aba56a..0000000
--- a/wifi/java/android/net/wifi/rtt/LocationConfigurationInformation.java
+++ /dev/null
@@ -1,272 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.wifi.rtt;
-
-import android.annotation.IntDef;
-import android.annotation.Nullable;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.Objects;
-
-/**
- * The Device Location Configuration Information (LCI) specifies the location information of a peer
- * device (e.g. an Access Point).
- * <p>
- * The information matches the IEEE 802.11-2016 LCI report (Location configuration information
- * report).
- * <p>
- * Note: depending on the mechanism by which this information is returned (i.e. the API which
- * returns an instance of this class) it is possibly Self Reported (by the peer). In such a case
- * the information is NOT validated - use with caution. Consider validating it with other sources
- * of information before using it.
- */
-public final class LocationConfigurationInformation implements Parcelable {
-    /** @hide */
-    @IntDef({
-            ALTITUDE_UNKNOWN, ALTITUDE_IN_METERS, ALTITUDE_IN_FLOORS })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface AltitudeTypes {
-    }
-
-    /**
-     * Define an Altitude Type returned by {@link #getAltitudeType()}. Indicates that the location
-     * does not specify an altitude or altitude uncertainty. The corresponding methods,
-     * {@link #getAltitude()} and {@link #getAltitudeUncertainty()} are not valid and will throw
-     * an exception.
-     */
-    public static final int ALTITUDE_UNKNOWN = 0;
-
-    /**
-     * Define an Altitude Type returned by {@link #getAltitudeType()}. Indicates that the location
-     * specifies the altitude and altitude uncertainty in meters. The corresponding methods,
-     * {@link #getAltitude()} and {@link #getAltitudeUncertainty()} return a valid value in meters.
-     */
-    public static final int ALTITUDE_IN_METERS = 1;
-
-    /**
-     * Define an Altitude Type returned by {@link #getAltitudeType()}. Indicates that the
-     * location specifies the altitude in floors, and does not specify an altitude uncertainty.
-     * The {@link #getAltitude()} method returns valid value in floors, and the
-     * {@link #getAltitudeUncertainty()} method is not valid and will throw an exception.
-     */
-    public static final int ALTITUDE_IN_FLOORS = 2;
-
-    private final double mLatitude;
-    private final double mLatitudeUncertainty;
-    private final double mLongitude;
-    private final double mLongitudeUncertainty;
-    private final int mAltitudeType;
-    private final double mAltitude;
-    private final double mAltitudeUncertainty;
-
-    /**
-     * Parse the raw LCI information element (byte array) and extract the
-     * LocationConfigurationInformation structure.
-     *
-     * Note: any parsing errors or invalid/unexpected errors will result in a null being returned.
-     *
-     * @hide
-     */
-    @Nullable
-    public static LocationConfigurationInformation parseInformationElement(byte id, byte[] data) {
-        // TODO
-        return null;
-    }
-
-    /** @hide */
-    public LocationConfigurationInformation(double latitude, double latitudeUncertainty,
-            double longitude, double longitudeUncertainty, @AltitudeTypes int altitudeType,
-            double altitude, double altitudeUncertainty) {
-        mLatitude = latitude;
-        mLatitudeUncertainty = latitudeUncertainty;
-        mLongitude = longitude;
-        mLongitudeUncertainty = longitudeUncertainty;
-        mAltitudeType = altitudeType;
-        mAltitude = altitude;
-        mAltitudeUncertainty = altitudeUncertainty;
-    }
-
-    /**
-     * Get latitude in degrees. Values are per WGS 84 reference system. Valid values are between
-     * -90 and 90.
-     *
-     * @return Latitude in degrees.
-     */
-    public double getLatitude() {
-        return mLatitude;
-    }
-
-    /**
-     * Get the uncertainty of the latitude {@link #getLatitude()} in degrees. A value of 0 indicates
-     * an unknown uncertainty.
-     *
-     * @return Uncertainty of the latitude in degrees.
-     */
-    public double getLatitudeUncertainty() {
-        return mLatitudeUncertainty;
-    }
-
-    /**
-     * Get longitude in degrees. Values are per WGS 84 reference system. Valid values are between
-     * -180 and 180.
-     *
-     * @return Longitude in degrees.
-     */
-    public double getLongitude() {
-        return mLongitude;
-    }
-
-    /**
-     * Get the uncertainty of the longitude {@link #getLongitude()} ()} in degrees.  A value of 0
-     * indicates an unknown uncertainty.
-     *
-     * @return Uncertainty of the longitude in degrees.
-     */
-    public double getLongitudeUncertainty() {
-        return mLongitudeUncertainty;
-    }
-
-    /**
-     * Specifies the type of the altitude measurement returned by {@link #getAltitude()} and
-     * {@link #getAltitudeUncertainty()}. The possible values are:
-     * <li>{@link #ALTITUDE_UNKNOWN}: The altitude and altitude uncertainty are not provided.
-     * <li>{@link #ALTITUDE_IN_METERS}: The altitude and altitude uncertainty are provided in
-     * meters. Values are per WGS 84 reference system.
-     * <li>{@link #ALTITUDE_IN_FLOORS}: The altitude is provided in floors, the altitude uncertainty
-     * is not provided.
-     *
-     * @return The type of the altitude and altitude uncertainty.
-     */
-    public @AltitudeTypes int getAltitudeType() {
-        return mAltitudeType;
-    }
-
-    /**
-     * The altitude is interpreted according to the {@link #getAltitudeType()}. The possible values
-     * are:
-     * <li>{@link #ALTITUDE_UNKNOWN}: The altitude is not provided - this method will throw an
-     * exception.
-     * <li>{@link #ALTITUDE_IN_METERS}: The altitude is provided in meters. Values are per WGS 84
-     * reference system.
-     * <li>{@link #ALTITUDE_IN_FLOORS}: The altitude is provided in floors.
-     *
-     * @return Altitude value whose meaning is specified by {@link #getAltitudeType()}.
-     */
-    public double getAltitude() {
-        if (mAltitudeType == ALTITUDE_UNKNOWN) {
-            throw new IllegalStateException(
-                    "getAltitude(): invoked on an invalid type: getAltitudeType()==UNKNOWN");
-        }
-        return mAltitude;
-    }
-
-    /**
-     * Only valid if the the {@link #getAltitudeType()} is equal to {@link #ALTITUDE_IN_METERS} -
-     * otherwise this method will throw an exception.
-     * <p>
-     * Get the uncertainty of the altitude {@link #getAltitude()} in meters.  A value of 0
-     * indicates an unknown uncertainty.
-     *
-     * @return Uncertainty of the altitude in meters.
-     */
-    public double getAltitudeUncertainty() {
-        if (mAltitudeType != ALTITUDE_IN_METERS) {
-            throw new IllegalStateException(
-                    "getAltitude(): invoked on an invalid type: getAltitudeType()!=IN_METERS");
-        }
-        return mAltitudeUncertainty;
-    }
-
-    /** @hide */
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    /** @hide */
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        dest.writeDouble(mLatitude);
-        dest.writeDouble(mLatitudeUncertainty);
-        dest.writeDouble(mLongitude);
-        dest.writeDouble(mLongitudeUncertainty);
-        dest.writeInt(mAltitudeType);
-        dest.writeDouble(mAltitude);
-        dest.writeDouble(mAltitudeUncertainty);
-    }
-
-    public static final Creator<LocationConfigurationInformation> CREATOR =
-            new Creator<LocationConfigurationInformation>() {
-        @Override
-        public LocationConfigurationInformation[] newArray(int size) {
-            return new LocationConfigurationInformation[size];
-        }
-
-        @Override
-        public LocationConfigurationInformation createFromParcel(Parcel in) {
-            double latitude = in.readDouble();
-            double latitudeUnc = in.readDouble();
-            double longitude = in.readDouble();
-            double longitudeUnc = in.readDouble();
-            int altitudeType = in.readInt();
-            double altitude = in.readDouble();
-            double altitudeUnc = in.readDouble();
-
-            return new LocationConfigurationInformation(latitude, latitudeUnc, longitude,
-                    longitudeUnc, altitudeType, altitude, altitudeUnc);
-        }
-    };
-
-    /** @hide */
-    @Override
-    public String toString() {
-        return new StringBuilder("LCI: latitude=").append(mLatitude).append(
-                ", latitudeUncertainty=").append(mLatitudeUncertainty).append(
-                ", longitude=").append(mLongitude).append(", longitudeUncertainty=").append(
-                mLongitudeUncertainty).append(", altitudeType=").append(mAltitudeType).append(
-                ", altitude=").append(mAltitude).append(", altitudeUncertainty=").append(
-                mAltitudeUncertainty).toString();
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) {
-            return true;
-        }
-
-        if (!(o instanceof LocationConfigurationInformation)) {
-            return false;
-        }
-
-        LocationConfigurationInformation lhs = (LocationConfigurationInformation) o;
-
-        return mLatitude == lhs.mLatitude && mLatitudeUncertainty == lhs.mLatitudeUncertainty
-                && mLongitude == lhs.mLongitude
-                && mLongitudeUncertainty == lhs.mLongitudeUncertainty
-                && mAltitudeType == lhs.mAltitudeType && mAltitude == lhs.mAltitude
-                && mAltitudeUncertainty == lhs.mAltitudeUncertainty;
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(mLatitude, mLatitudeUncertainty, mLongitude, mLongitudeUncertainty,
-                mAltitudeType, mAltitude, mAltitudeUncertainty);
-    }
-}
diff --git a/wifi/java/android/net/wifi/rtt/RangingRequest.java b/wifi/java/android/net/wifi/rtt/RangingRequest.java
index 32f21b9..339233b 100644
--- a/wifi/java/android/net/wifi/rtt/RangingRequest.java
+++ b/wifi/java/android/net/wifi/rtt/RangingRequest.java
@@ -37,7 +37,7 @@
  * Defines the ranging request to other devices. The ranging request is built using
  * {@link RangingRequest.Builder}.
  * A ranging request is executed using
- * {@link WifiRttManager#startRanging(RangingRequest, RangingResultCallback, Handler)}.
+ * {@link WifiRttManager#startRanging(RangingRequest, java.util.concurrent.Executor, RangingResultCallback)}.
  * <p>
  * The ranging request is a batch request - specifying a set of devices (specified using
  * {@link RangingRequest.Builder#addAccessPoint(ScanResult)} and
@@ -122,6 +122,11 @@
          * Add the device specified by the {@link ScanResult} to the list of devices with
          * which to measure range. The total number of peers added to a request cannot exceed the
          * limit specified by {@link #getMaxPeers()}.
+         * <p>
+         * Ranging may not be supported if the Access Point does not support IEEE 802.11mc. Use
+         * {@link ScanResult#is80211mcResponder()} to verify the Access Point's capabilities. If
+         * not supported the result status will be
+         * {@link RangingResult#STATUS_RESPONDER_DOES_NOT_SUPPORT_IEEE80211MC}.
          *
          * @param apInfo Information of an Access Point (AP) obtained in a Scan Result.
          * @return The builder to facilitate chaining
@@ -138,6 +143,11 @@
          * Add the devices specified by the {@link ScanResult}s to the list of devices with
          * which to measure range. The total number of peers added to a request cannot exceed the
          * limit specified by {@link #getMaxPeers()}.
+         * <p>
+         * Ranging may not be supported if the Access Point does not support IEEE 802.11mc. Use
+         * {@link ScanResult#is80211mcResponder()} to verify the Access Point's capabilities. If
+         * not supported the result status will be
+         * {@link RangingResult#STATUS_RESPONDER_DOES_NOT_SUPPORT_IEEE80211MC}.
          *
          * @param apInfos Information of an Access Points (APs) obtained in a Scan Result.
          * @return The builder to facilitate chaining
@@ -156,14 +166,18 @@
         /**
          * Add the device specified by the {@code peerMacAddress} to the list of devices with
          * which to measure range.
-         *
+         * <p>
          * The MAC address may be obtained out-of-band from a peer Wi-Fi Aware device. A Wi-Fi
          * Aware device may obtain its MAC address using the {@link IdentityChangedListener}
          * provided to
          * {@link WifiAwareManager#attach(AttachCallback, IdentityChangedListener, Handler)}.
-         *
-         * * Note: in order to use this API the device must support Wi-Fi Aware
-         * {@link android.net.wifi.aware}.
+         * <p>
+         * Note: in order to use this API the device must support Wi-Fi Aware
+         * {@link android.net.wifi.aware}. The peer device which is being ranged to must be
+         * configured to publish a service (with any name) with:
+         * <li>Type {@link android.net.wifi.aware.PublishConfig#PUBLISH_TYPE_UNSOLICITED}.
+         * <li>Ranging enabled
+         * {@link android.net.wifi.aware.PublishConfig.Builder#setRangingEnabled(boolean)}.
          *
          * @param peerMacAddress The MAC address of the Wi-Fi Aware peer.
          * @return The builder, to facilitate chaining {@code builder.setXXX(..).setXXX(..)}.
@@ -179,12 +193,16 @@
         /**
          * Add a device specified by a {@link PeerHandle} to the list of devices with which to
          * measure range.
-         *
+         * <p>
          * The {@link PeerHandle} may be obtained as part of the Wi-Fi Aware discovery process. E.g.
          * using {@link DiscoverySessionCallback#onServiceDiscovered(PeerHandle, byte[], List)}.
-         *
+         * <p>
          * Note: in order to use this API the device must support Wi-Fi Aware
-         * {@link android.net.wifi.aware}.
+         * {@link android.net.wifi.aware}. The peer device which is being ranged to must be
+         * configured to publish a service (with any name) with:
+         * <li>Type {@link android.net.wifi.aware.PublishConfig#PUBLISH_TYPE_UNSOLICITED}.
+         * <li>Ranging enabled
+         * {@link android.net.wifi.aware.PublishConfig.Builder#setRangingEnabled(boolean)}.
          *
          * @param peerHandle The peer handler of the peer Wi-Fi Aware device.
          * @return The builder, to facilitate chaining {@code builder.setXXX(..).setXXX(..)}.
diff --git a/wifi/java/android/net/wifi/rtt/RangingResult.java b/wifi/java/android/net/wifi/rtt/RangingResult.java
index 201833b..936a1f2 100644
--- a/wifi/java/android/net/wifi/rtt/RangingResult.java
+++ b/wifi/java/android/net/wifi/rtt/RangingResult.java
@@ -19,6 +19,7 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.SystemApi;
 import android.net.MacAddress;
 import android.net.wifi.aware.PeerHandle;
 import android.os.Handler;
@@ -27,22 +28,24 @@
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.util.Arrays;
 import java.util.List;
 import java.util.Objects;
 
 /**
  * Ranging result for a request started by
- * {@link WifiRttManager#startRanging(RangingRequest, RangingResultCallback, Handler)}. Results are
- * returned in {@link RangingResultCallback#onRangingResults(List)}.
+ * {@link WifiRttManager#startRanging(RangingRequest, java.util.concurrent.Executor, RangingResultCallback)}.
+ * Results are returned in {@link RangingResultCallback#onRangingResults(List)}.
  * <p>
  * A ranging result is the distance measurement result for a single device specified in the
  * {@link RangingRequest}.
  */
 public final class RangingResult implements Parcelable {
     private static final String TAG = "RangingResult";
+    private static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
 
     /** @hide */
-    @IntDef({STATUS_SUCCESS, STATUS_FAIL})
+    @IntDef({STATUS_SUCCESS, STATUS_FAIL, STATUS_RESPONDER_DOES_NOT_SUPPORT_IEEE80211MC})
     @Retention(RetentionPolicy.SOURCE)
     public @interface RangeResultStatus {
     }
@@ -59,43 +62,52 @@
      */
     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.
+     */
+    public static final int STATUS_RESPONDER_DOES_NOT_SUPPORT_IEEE80211MC = 2;
+
     private final int mStatus;
     private final MacAddress mMac;
     private final PeerHandle mPeerHandle;
     private final int mDistanceMm;
     private final int mDistanceStdDevMm;
     private final int mRssi;
-    private final LocationConfigurationInformation mLci;
-    private final LocationCivic mLcr;
+    private final byte[] mLci;
+    private final byte[] mLcr;
     private final long mTimestamp;
 
     /** @hide */
     public RangingResult(@RangeResultStatus int status, @NonNull MacAddress mac, int distanceMm,
-            int distanceStdDevMm, int rssi, LocationConfigurationInformation lci, LocationCivic lcr,
-            long timestamp) {
+            int distanceStdDevMm, int rssi, byte[] lci, byte[] lcr, long timestamp) {
         mStatus = status;
         mMac = mac;
         mPeerHandle = null;
         mDistanceMm = distanceMm;
         mDistanceStdDevMm = distanceStdDevMm;
         mRssi = rssi;
-        mLci = lci;
-        mLcr = lcr;
+        mLci = lci == null ? EMPTY_BYTE_ARRAY : lci;
+        mLcr = lcr == null ? EMPTY_BYTE_ARRAY : lcr;
         mTimestamp = timestamp;
     }
 
     /** @hide */
     public RangingResult(@RangeResultStatus int status, PeerHandle peerHandle, int distanceMm,
-            int distanceStdDevMm, int rssi, LocationConfigurationInformation lci, LocationCivic lcr,
-            long timestamp) {
+            int distanceStdDevMm, int rssi, byte[] lci, byte[] lcr, long timestamp) {
         mStatus = status;
         mMac = null;
         mPeerHandle = peerHandle;
         mDistanceMm = distanceMm;
         mDistanceStdDevMm = distanceStdDevMm;
         mRssi = rssi;
-        mLci = lci;
-        mLcr = lcr;
+        mLci = lci == null ? EMPTY_BYTE_ARRAY : lci;
+        mLcr = lcr == null ? EMPTY_BYTE_ARRAY : lcr;
         mTimestamp = timestamp;
     }
 
@@ -163,7 +175,7 @@
     }
 
     /**
-     * @return The average RSSI (in units of -0.5dB) observed during the RTT measurement.
+     * @return The average RSSI, in units of dBm, observed during the RTT measurement.
      * <p>
      * Only valid if {@link #getStatus()} returns {@link #STATUS_SUCCESS}, otherwise will throw an
      * exception.
@@ -181,13 +193,15 @@
      * <p>
      * Note: the information is NOT validated - use with caution. Consider validating it with
      * other sources of information before using it.
+     *
+     * @hide
      */
-    @Nullable
-    public LocationConfigurationInformation getReportedLocationConfigurationInformation() {
+    @SystemApi
+    @NonNull
+    public byte[] getLci() {
         if (mStatus != STATUS_SUCCESS) {
             throw new IllegalStateException(
-                    "getReportedLocationConfigurationInformation(): invoked on an invalid result: "
-                            + "getStatus()=" + mStatus);
+                    "getLci(): invoked on an invalid result: getStatus()=" + mStatus);
         }
         return mLci;
     }
@@ -197,9 +211,12 @@
      * <p>
      * Note: the information is NOT validated - use with caution. Consider validating it with
      * other sources of information before using it.
+     *
+     * @hide
      */
-    @Nullable
-    public LocationCivic getReportedLocationCivic() {
+    @SystemApi
+    @NonNull
+    public byte[] getLcr() {
         if (mStatus != STATUS_SUCCESS) {
             throw new IllegalStateException(
                     "getReportedLocationCivic(): invoked on an invalid result: getStatus()="
@@ -209,15 +226,18 @@
     }
 
     /**
-     * @return The timestamp, in us since boot, at which the ranging operation was performed.
+     * @return The timestamp at which the ranging operation was performed. The timestamp is in
+     * milliseconds since boot, including time spent in sleep, corresponding to values provided by
+     * {@link android.os.SystemClock#elapsedRealtime()}.
      * <p>
      * Only valid if {@link #getStatus()} returns {@link #STATUS_SUCCESS}, otherwise will throw an
      * exception.
      */
-    public long getRangingTimestampUs() {
+    public long getRangingTimestampMillis() {
         if (mStatus != STATUS_SUCCESS) {
             throw new IllegalStateException(
-                    "getRangingTimestamp(): invoked on an invalid result: getStatus()=" + mStatus);
+                    "getRangingTimestampMillis(): invoked on an invalid result: getStatus()="
+                            + mStatus);
         }
         return mTimestamp;
     }
@@ -245,18 +265,8 @@
         dest.writeInt(mDistanceMm);
         dest.writeInt(mDistanceStdDevMm);
         dest.writeInt(mRssi);
-        if (mLci == null) {
-            dest.writeBoolean(false);
-        } else {
-            dest.writeBoolean(true);
-            mLci.writeToParcel(dest, flags);
-        }
-        if (mLcr == null) {
-            dest.writeBoolean(false);
-        } else {
-            dest.writeBoolean(true);
-            mLcr.writeToParcel(dest, flags);
-        }
+        dest.writeByteArray(mLci);
+        dest.writeByteArray(mLcr);
         dest.writeLong(mTimestamp);
     }
 
@@ -282,16 +292,8 @@
             int distanceMm = in.readInt();
             int distanceStdDevMm = in.readInt();
             int rssi = in.readInt();
-            boolean lciPresent = in.readBoolean();
-            LocationConfigurationInformation lci = null;
-            if (lciPresent) {
-                lci = LocationConfigurationInformation.CREATOR.createFromParcel(in);
-            }
-            boolean lcrPresent = in.readBoolean();
-            LocationCivic lcr = null;
-            if (lcrPresent) {
-                lcr = LocationCivic.CREATOR.createFromParcel(in);
-            }
+            byte[] lci = in.createByteArray();
+            byte[] lcr = in.createByteArray();
             long timestamp = in.readLong();
             if (peerHandlePresent) {
                 return new RangingResult(status, peerHandle, distanceMm, distanceStdDevMm, rssi,
@@ -329,7 +331,7 @@
         return mStatus == lhs.mStatus && Objects.equals(mMac, lhs.mMac) && Objects.equals(
                 mPeerHandle, lhs.mPeerHandle) && mDistanceMm == lhs.mDistanceMm
                 && mDistanceStdDevMm == lhs.mDistanceStdDevMm && mRssi == lhs.mRssi
-                && Objects.equals(mLci, lhs.mLci) && Objects.equals(mLcr, lhs.mLcr)
+                && Arrays.equals(mLci, lhs.mLci) && Arrays.equals(mLcr, lhs.mLcr)
                 && mTimestamp == lhs.mTimestamp;
     }
 
diff --git a/wifi/java/android/net/wifi/rtt/RangingResultCallback.java b/wifi/java/android/net/wifi/rtt/RangingResultCallback.java
index 9639dc8..fa7d79e 100644
--- a/wifi/java/android/net/wifi/rtt/RangingResultCallback.java
+++ b/wifi/java/android/net/wifi/rtt/RangingResultCallback.java
@@ -18,7 +18,6 @@
 
 import android.annotation.IntDef;
 import android.annotation.NonNull;
-import android.os.Handler;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -26,11 +25,11 @@
 
 /**
  * Base class for ranging result callbacks. Should be extended by applications and set when calling
- * {@link WifiRttManager#startRanging(RangingRequest, RangingResultCallback, Handler)}. If the
- * ranging operation fails in whole (not attempted) then {@link #onRangingFailure(int)} will be
- * called with a failure code. If the ranging operation is performed for each of the requested
- * peers then the {@link #onRangingResults(List)} will be called with the set of results (@link
- * {@link RangingResult}, each of which has its own success/failure code
+ * {@link WifiRttManager#startRanging(RangingRequest, java.util.concurrent.Executor, RangingResultCallback)}.
+ * If the ranging operation fails in whole (not attempted) then {@link #onRangingFailure(int)}
+ * will be called with a failure code. If the ranging operation is performed for each of the
+ * requested peers then the {@link #onRangingResults(List)} will be called with the set of
+ * results (@link {@link RangingResult}, each of which has its own success/failure code
  * {@link RangingResult#getStatus()}.
  */
 public abstract class RangingResultCallback {
diff --git a/wifi/java/android/net/wifi/rtt/WifiRttManager.java b/wifi/java/android/net/wifi/rtt/WifiRttManager.java
index ec6c46e..d119579 100644
--- a/wifi/java/android/net/wifi/rtt/WifiRttManager.java
+++ b/wifi/java/android/net/wifi/rtt/WifiRttManager.java
@@ -21,6 +21,7 @@
 import static android.Manifest.permission.CHANGE_WIFI_STATE;
 import static android.Manifest.permission.LOCATION_HARDWARE;
 
+import android.annotation.CallbackExecutor;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
@@ -29,13 +30,12 @@
 import android.annotation.SystemService;
 import android.content.Context;
 import android.os.Binder;
-import android.os.Handler;
-import android.os.Looper;
 import android.os.RemoteException;
 import android.os.WorkSource;
 import android.util.Log;
 
 import java.util.List;
+import java.util.concurrent.Executor;
 
 /**
  * This class provides the primary API for measuring distance (range) to other devices using the
@@ -46,7 +46,7 @@
  * <li>Wi-Fi Aware peers
  * <p>
  * Ranging requests are triggered using
- * {@link #startRanging(RangingRequest, RangingResultCallback, Handler)}. Results (in case of
+ * {@link #startRanging(RangingRequest, Executor, RangingResultCallback)}. Results (in case of
  * successful operation) are returned in the {@link RangingResultCallback#onRangingResults(List)}
  * callback.
  * <p>
@@ -106,15 +106,13 @@
      *
      * @param request  A request specifying a set of devices whose distance measurements are
      *                 requested.
+     * @param executor The Executor on which to run the callback.
      * @param callback A callback for the result of the ranging request.
-     * @param handler  The Handler on whose thread to execute the callbacks of the {@code
-     *                 callback} object. If a null is provided then the application's main thread
-     *                 will be used.
      */
     @RequiresPermission(allOf = {ACCESS_COARSE_LOCATION, CHANGE_WIFI_STATE, ACCESS_WIFI_STATE})
     public void startRanging(@NonNull RangingRequest request,
-            @NonNull RangingResultCallback callback, @Nullable Handler handler) {
-        startRanging(null, request, callback, handler);
+            @NonNull @CallbackExecutor Executor executor, @NonNull RangingResultCallback callback) {
+        startRanging(null, request, executor, callback);
     }
 
     /**
@@ -124,10 +122,8 @@
      * @param workSource A mechanism to specify an alternative work-source for the request.
      * @param request  A request specifying a set of devices whose distance measurements are
      *                 requested.
+     * @param executor The Executor on which to run the callback.
      * @param callback A callback for the result of the ranging request.
-     * @param handler  The Handler on whose thread to execute the callbacks of the {@code
-     *                 callback} object. If a null is provided then the application's main thread
-     *                 will be used.
      *
      * @hide
      */
@@ -135,21 +131,36 @@
     @RequiresPermission(allOf = {LOCATION_HARDWARE, ACCESS_COARSE_LOCATION, CHANGE_WIFI_STATE,
             ACCESS_WIFI_STATE})
     public void startRanging(@Nullable WorkSource workSource, @NonNull RangingRequest request,
-            @NonNull RangingResultCallback callback, @Nullable Handler handler) {
+            @NonNull @CallbackExecutor Executor executor, @NonNull RangingResultCallback callback) {
         if (VDBG) {
             Log.v(TAG, "startRanging: workSource=" + workSource + ", request=" + request
-                    + ", callback=" + callback + ", handler=" + handler);
+                    + ", callback=" + callback + ", executor=" + executor);
         }
 
+        if (executor == null) {
+            throw new IllegalArgumentException("Null executor provided");
+        }
         if (callback == null) {
             throw new IllegalArgumentException("Null callback provided");
         }
 
-        Looper looper = (handler == null) ? Looper.getMainLooper() : handler.getLooper();
         Binder binder = new Binder();
         try {
             mService.startRanging(binder, mContext.getOpPackageName(), workSource, request,
-                    new RttCallbackProxy(looper, callback));
+                    new IRttCallback.Stub() {
+                        @Override
+                        public void onRangingFailure(int status) throws RemoteException {
+                            clearCallingIdentity();
+                            executor.execute(() -> callback.onRangingFailure(status));
+                        }
+
+                        @Override
+                        public void onRangingResults(List<RangingResult> results)
+                                throws RemoteException {
+                            clearCallingIdentity();
+                            executor.execute(() -> callback.onRangingResults(results));
+                        }
+                    });
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -157,7 +168,7 @@
 
     /**
      * Cancel all ranging requests for the specified work sources. The requests have been requested
-     * using {@link #startRanging(WorkSource, RangingRequest, RangingResultCallback, Handler)}.
+     * using {@link #startRanging(WorkSource, RangingRequest, Executor, RangingResultCallback)}.
      *
      * @param workSource The work-sources of the requesters.
      *
@@ -176,30 +187,4 @@
             throw e.rethrowFromSystemServer();
         }
     }
-
-    private static class RttCallbackProxy extends IRttCallback.Stub {
-        private final Handler mHandler;
-        private final RangingResultCallback mCallback;
-
-        RttCallbackProxy(Looper looper, RangingResultCallback callback) {
-            mHandler = new Handler(looper);
-            mCallback = callback;
-        }
-
-        @Override
-        public void onRangingFailure(int status) throws RemoteException {
-            if (VDBG) Log.v(TAG, "RttCallbackProxy: onRangingFailure: status=" + status);
-            mHandler.post(() -> {
-               mCallback.onRangingFailure(status);
-            });
-        }
-
-        @Override
-        public void onRangingResults(List<RangingResult> results) throws RemoteException {
-            if (VDBG) Log.v(TAG, "RttCallbackProxy: onRanginResults: results=" + results);
-            mHandler.post(() -> {
-               mCallback.onRangingResults(results);
-            });
-        }
-    }
 }
diff --git a/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java b/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java
index e7377c1..8a3a7f5 100644
--- a/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java
@@ -176,6 +176,8 @@
     @Test
     public void testGetOrCreateRandomizedMacAddress_SavesAndReturnsSameAddress() {
         WifiConfiguration config = new WifiConfiguration();
+        assertEquals(MacAddress.ALL_ZEROS_ADDRESS, config.getRandomizedMacAddress());
+
         MacAddress firstMacAddress = config.getOrCreateRandomizedMacAddress();
         MacAddress secondMacAddress = config.getOrCreateRandomizedMacAddress();
 
@@ -185,6 +187,8 @@
     @Test
     public void testSetRandomizedMacAddress_ChangesSavedAddress() {
         WifiConfiguration config = new WifiConfiguration();
+        assertEquals(MacAddress.ALL_ZEROS_ADDRESS, config.getRandomizedMacAddress());
+
         MacAddress macToChangeInto = MacAddress.createRandomUnicastAddress();
         config.setRandomizedMacAddress(macToChangeInto);
         MacAddress macAfterChange = config.getOrCreateRandomizedMacAddress();
diff --git a/wifi/tests/src/android/net/wifi/WifiManagerTest.java b/wifi/tests/src/android/net/wifi/WifiManagerTest.java
index 71ca068..f3a78bd 100644
--- a/wifi/tests/src/android/net/wifi/WifiManagerTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiManagerTest.java
@@ -611,6 +611,7 @@
     /**
      * Verify the watchLocalOnlyHotspot call goes to WifiServiceImpl.
      */
+    @Test
     public void testWatchLocalOnlyHotspot() throws Exception {
         TestLocalOnlyHotspotObserver observer = new TestLocalOnlyHotspotObserver();
 
diff --git a/wifi/tests/src/android/net/wifi/rtt/WifiRttManagerTest.java b/wifi/tests/src/android/net/wifi/rtt/WifiRttManagerTest.java
index 41c7f86..1e4cea1 100644
--- a/wifi/tests/src/android/net/wifi/rtt/WifiRttManagerTest.java
+++ b/wifi/tests/src/android/net/wifi/rtt/WifiRttManagerTest.java
@@ -17,7 +17,6 @@
 package android.net.wifi.rtt;
 
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.mock;
@@ -29,7 +28,6 @@
 import android.net.MacAddress;
 import android.net.wifi.ScanResult;
 import android.net.wifi.aware.PeerHandle;
-import android.os.Handler;
 import android.os.IBinder;
 import android.os.Parcel;
 import android.os.test.TestLooper;
@@ -42,6 +40,7 @@
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.concurrent.Executor;
 
 /**
  * Unit test harness for WifiRttManager class.
@@ -49,7 +48,7 @@
 public class WifiRttManagerTest {
     private WifiRttManager mDut;
     private TestLooper mMockLooper;
-    private Handler mMockLooperHandler;
+    private Executor mMockLooperExecutor;
 
     private final String packageName = "some.package.name.for.rtt.app";
 
@@ -65,7 +64,7 @@
 
         mDut = new WifiRttManager(mockContext, mockRttService);
         mMockLooper = new TestLooper();
-        mMockLooperHandler = new Handler(mMockLooper.getLooper());
+        mMockLooperExecutor = mMockLooper.getNewExecutor();
 
         when(mockContext.getOpPackageName()).thenReturn(packageName);
     }
@@ -84,7 +83,7 @@
         ArgumentCaptor<IRttCallback> callbackCaptor = ArgumentCaptor.forClass(IRttCallback.class);
 
         // verify ranging request passed to service
-        mDut.startRanging(request, callbackMock, mMockLooperHandler);
+        mDut.startRanging(request, mMockLooperExecutor, callbackMock);
         verify(mockRttService).startRanging(any(IBinder.class), eq(packageName), eq(null),
                 eq(request), callbackCaptor.capture());
 
@@ -108,7 +107,7 @@
         ArgumentCaptor<IRttCallback> callbackCaptor = ArgumentCaptor.forClass(IRttCallback.class);
 
         // verify ranging request passed to service
-        mDut.startRanging(request, callbackMock, mMockLooperHandler);
+        mDut.startRanging(request, mMockLooperExecutor, callbackMock);
         verify(mockRttService).startRanging(any(IBinder.class), eq(packageName), eq(null),
                 eq(request), callbackCaptor.capture());
 
@@ -227,7 +226,6 @@
      */
     @Test
     public void testRangingResultsParcel() {
-        // Note: not validating parcel code of ScanResult (assumed to work)
         int status = RangingResult.STATUS_SUCCESS;
         final MacAddress mac = MacAddress.fromString("00:01:02:03:04:05");
         PeerHandle peerHandle = new PeerHandle(10);
@@ -235,19 +233,8 @@
         int distanceStdDevCm = 10;
         int rssi = 5;
         long timestamp = System.currentTimeMillis();
-        double latitude = 5.5;
-        double latitudeUncertainty = 6.5;
-        double longitude = 7.5;
-        double longitudeUncertainty = 8.5;
-        int altitudeType = LocationConfigurationInformation.ALTITUDE_IN_METERS;
-        double altitude = 9.5;
-        double altitudeUncertainty = 55.5;
-        byte[] lcrData = { 0x1, 0x2, 0x3, 0xA, 0xB, 0xC };
-
-        LocationConfigurationInformation lci = new LocationConfigurationInformation(latitude,
-                latitudeUncertainty, longitude, longitudeUncertainty, altitudeType, altitude,
-                altitudeUncertainty);
-        LocationCivic lcr = new LocationCivic(lcrData);
+        byte[] lci = { 0x5, 0x6, 0x7 };
+        byte[] lcr = { 0x1, 0x2, 0x3, 0xA, 0xB, 0xC };
 
         // RangingResults constructed with a MAC address
         RangingResult result = new RangingResult(status, mac, distanceCm, distanceStdDevCm, rssi,
@@ -283,81 +270,25 @@
     }
 
     /**
-     * Validate that LocationConfigurationInformation parcel works (produces same object on
-     * write/read).
+     * Validate that RangingResults tests equal even if LCI/LCR is empty (length == 0) and null.
      */
     @Test
-    public void testLciParcel() {
-        double latitude = 1.5;
-        double latitudeUncertainty = 2.5;
-        double longitude = 3.5;
-        double longitudeUncertainty = 4.5;
-        int altitudeType = LocationConfigurationInformation.ALTITUDE_IN_FLOORS;
-        double altitude = 5.5;
-        double altitudeUncertainty = 6.5;
+    public void testRangingResultsEqualityLciLcr() {
+        int status = RangingResult.STATUS_SUCCESS;
+        final MacAddress mac = MacAddress.fromString("00:01:02:03:04:05");
+        PeerHandle peerHandle = new PeerHandle(10);
+        int distanceCm = 105;
+        int distanceStdDevCm = 10;
+        int rssi = 5;
+        long timestamp = System.currentTimeMillis();
+        byte[] lci = { };
+        byte[] lcr = { };
 
-        LocationConfigurationInformation lci = new LocationConfigurationInformation(latitude,
-                latitudeUncertainty, longitude, longitudeUncertainty, altitudeType, altitude,
-                altitudeUncertainty);
+        RangingResult rr1 = new RangingResult(status, mac, distanceCm, distanceStdDevCm, rssi, lci,
+                lcr, timestamp);
+        RangingResult rr2 = new RangingResult(status, mac, distanceCm, distanceStdDevCm, rssi, null,
+                null, timestamp);
 
-        Parcel parcelW = Parcel.obtain();
-        lci.writeToParcel(parcelW, 0);
-        byte[] bytes = parcelW.marshall();
-        parcelW.recycle();
-
-        Parcel parcelR = Parcel.obtain();
-        parcelR.unmarshall(bytes, 0, bytes.length);
-        parcelR.setDataPosition(0);
-        LocationConfigurationInformation rereadLci =
-                LocationConfigurationInformation.CREATOR.createFromParcel(parcelR);
-
-        assertEquals(lci, rereadLci);
-    }
-
-    /**
-     * Validate that the LCI throws an exception when accessing invalid fields an certain altitude
-     * types.
-     */
-    @Test
-    public void testLciInvalidAltitudeFieldAccess() {
-        boolean exceptionThrown;
-        LocationConfigurationInformation lci = new LocationConfigurationInformation(0, 0, 0, 0,
-                LocationConfigurationInformation.ALTITUDE_UNKNOWN, 0, 0);
-
-        // UNKNOWN - invalid altitude & altitude uncertainty
-        exceptionThrown = false;
-        try {
-            lci.getAltitude();
-        } catch (IllegalStateException e) {
-            exceptionThrown = true;
-        }
-        assertTrue("UNKNOWN / getAltitude()", exceptionThrown);
-
-        exceptionThrown = false;
-        try {
-            lci.getAltitudeUncertainty();
-        } catch (IllegalStateException e) {
-            exceptionThrown = true;
-        }
-        assertTrue("UNKNOWN / getAltitudeUncertainty()", exceptionThrown);
-
-        lci = new LocationConfigurationInformation(0, 0, 0, 0,
-                LocationConfigurationInformation.ALTITUDE_IN_FLOORS, 0, 0);
-
-        // FLOORS - invalid altitude uncertainty
-        exceptionThrown = false;
-        try {
-            lci.getAltitudeUncertainty();
-        } catch (IllegalStateException e) {
-            exceptionThrown = true;
-        }
-        assertTrue("FLOORS / getAltitudeUncertainty()", exceptionThrown);
-
-        // and good accesses just in case
-        lci.getAltitude();
-        lci = new LocationConfigurationInformation(0, 0, 0, 0,
-                LocationConfigurationInformation.ALTITUDE_IN_METERS, 0, 0);
-        lci.getAltitude();
-        lci.getAltitudeUncertainty();
+        assertEquals(rr1, rr2);
     }
 }